diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 3e0c8c2..e859d56 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,6 +2,10 @@ class ApplicationController < ActionController::Base + include Dmpopidor::Controllers::Application + # Set Static Pages to use in navigation + before_filter :set_nav_static_pages + protect_from_forgery with: :exception before_action :configure_permitted_parameters, if: :devise_controller? diff --git a/app/controllers/paginable/static_pages_controller.rb b/app/controllers/paginable/static_pages_controller.rb new file mode 100644 index 0000000..8a2b9b7 --- /dev/null +++ b/app/controllers/paginable/static_pages_controller.rb @@ -0,0 +1,11 @@ +module Paginable + class StaticPagesController < ApplicationController + include Paginable + + # /paginable/static_pages/index/:page + def index + authorize(StaticPage) + paginable_renderise(partial: 'index', scope: StaticPage.all) + end + end +end \ No newline at end of file diff --git a/app/controllers/static/static_pages_controller.rb b/app/controllers/static/static_pages_controller.rb new file mode 100644 index 0000000..1e660df --- /dev/null +++ b/app/controllers/static/static_pages_controller.rb @@ -0,0 +1,31 @@ +module Static + class StaticPagesController < ApplicationController + before_action :set_static_page, only: :show + + # GET /static/:name + def show; end + + # Changed News feed + def news_feed + dcc_news_feed_url = "https://opidor.fr/category/dmp-news/feed/" + @dcc_news_feed = Feedjira::Feed.fetch_and_parse dcc_news_feed_url + respond_to do |format| + format.rss { redirect_to dcc_news_feed_url } + format.html + end + end + + # Added Tutorials Page + def tutorials + + end + + private + + # Define static page to be rendered, 404 if needed + def set_static_page + @static_page = StaticPage.find_by(url: params[:name]) + render file: "#{Rails.root}/public/404", status: 404 unless @static_page + end + end +end \ No newline at end of file diff --git a/app/controllers/super_admin/static_pages_controller.rb b/app/controllers/super_admin/static_pages_controller.rb new file mode 100644 index 0000000..c8623e6 --- /dev/null +++ b/app/controllers/super_admin/static_pages_controller.rb @@ -0,0 +1,101 @@ +module SuperAdmin + class StaticPagesController < ApplicationController + before_action :set_static_page, only: %i[edit update destroy] + before_action :set_static_pages, only: :index + before_action :set_languages, only: %i[new edit] + + # GET /static_pages + # GET /static_pages.json + def index + authorize(StaticPage) + render(:index, locals: { static_pages: @static_pages.page(1) }) + end + + # GET /static_pages/new + def new + authorize(StaticPage) + @static_page = StaticPage.new + end + + # GET /static_pages/1/edit + def edit + authorize(StaticPage) + end + + # POST /static_pages + # POST /static_pages.json + def create + authorize(StaticPage) + + begin + @static_page = StaticPage.create!(static_page_params) + flash[:notice] = _('Static Page created successfully') + rescue ActionController::ParameterMissing + flash[:alert] = _('Unable to save since static_page parameter is missing') + rescue ActiveRecord::RecordInvalid => e + flash[:alert] = e.message + end + + redirect_to action: :index + end + + # PATCH/PUT /static_pages/1 + # PATCH/PUT /static_pages/1.json + def update + authorize(StaticPage) + + begin + @static_page.update!(static_page_params) + flash[:notice] = _('Static Page updated successfully') + rescue ActionController::ParameterMissing + flash[:alert] = _('Unable to save since static_page parameter is missing') + rescue ActiveRecord::RecordInvalid => e + flash[:alert] = e.message + end + + redirect_to action: :index + end + + # DELETE /static_pages/1 + # DELETE /static_pages/1.json + def destroy + authorize(StaticPage) + + begin + @static_page.destroy + flash[:notice] = _('Successfully destroyed your Static Page') + rescue ActiveRecord::RecordNotDestroyed + flash[:alert] = _('The Static Page with id %{id} could not be destroyed') % { id: params[:id] } + end + + redirect_to action: :index + end + + private + + # Use callbacks to share common setup or constraints between actions. + def set_static_page + @static_page = StaticPage.find(params[:id]) + end + + # Use callbacks to share common setup or constraints between actions. + def set_static_pages + @static_pages = StaticPage.all + end + + # Use callbacks to share common setup or constraints between actions. + def set_languages + @languages = Language.order(default_language: :desc) + end + + # Never trust parameters from the scary internet, only allow the white list through. + def static_page_params + params.require(:static_page).permit( + :name, + :url, + :in_navigation, + static_page_contents_attributes: [%i[id language_id title content]] + ) + end + end +end \ No newline at end of file diff --git a/app/helpers/static_pages_helper.rb b/app/helpers/static_pages_helper.rb new file mode 100644 index 0000000..876d4f2 --- /dev/null +++ b/app/helpers/static_pages_helper.rb @@ -0,0 +1,10 @@ +module StaticPagesHelper + # Returns additionnal classes to make a Bootstrap tab active + # Used to set active tab in Static Pages edition depending on the locale + # @param locale locale abbreviation to check against + # @param content add the 'in' class for tab content ? (optionnal) + def active_tab?(locale, content = false) + return "#{'in' if content} active" if locale == session[:locale] + '' + end +end \ No newline at end of file diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 104f99d..6b5e56b 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -47,3 +47,4 @@ import '../views/users/notification_preferences'; import '../views/users/admin_grant_permissions'; import '../views/super_admin/notifications/edit'; +import '../views/super_admin/static_pages/edit'; diff --git a/app/javascript/views/super_admin/static_pages/edit.js b/app/javascript/views/super_admin/static_pages/edit.js new file mode 100644 index 0000000..f41ed7d --- /dev/null +++ b/app/javascript/views/super_admin/static_pages/edit.js @@ -0,0 +1,9 @@ +import { Tinymce } from '../../../utils/tinymce'; + +$(() => { + Tinymce.init({ + selector: '.content-editor', + forced_root_block: '', + toolbar: 'bold italic underline | formatselect | bullist numlist | link', + }); +}); diff --git a/app/models/static_page.rb b/app/models/static_page.rb new file mode 100644 index 0000000..2085c5b --- /dev/null +++ b/app/models/static_page.rb @@ -0,0 +1,60 @@ +# == Schema Information +# +# Table name: static_pages +# +# id :integer not null, primary key +# in_navigation :boolean default(TRUE) +# name :string not null +# url :string not null +# created_at :datetime not null +# updated_at :datetime not null +# + +# Static page class +class StaticPage < ActiveRecord::Base + has_many :static_page_contents, dependent: :destroy do + # Create or update a content from a file + # @param path path of the source file + # @param language language for the content (default is default language) + # @return [StaticPageContent] the created Static Page Content + def from_file(path, language = Language.default) + where(language: language) + .first_or_create(language: language) + .update(content: File.read(path)) + end + end + accepts_nested_attributes_for :static_page_contents, allow_destroy: true + + alias contents static_page_contents + + validates :name, :url, presence: true, uniqueness: true + + # After initialization, also initialize Static Page Contents + after_initialize if: :new_record? do + (Language.all.to_a - contents.map(&:language)).each do |l| + contents.new(language: l, content: '') + end + end + + scope :navigable, -> { StaticPage.where('in_navigation = ?', true) } + + # Get Static Page content for specified locale + # @param locale requested locale for page content + # @return [String] the localized Static Page Content + def localized_content(locale = Language.default.abbreviation) + spc = contents.find_by(language: Language.find_by(abbreviation: locale)) + + spc ? spc.content : nil + end + + # Get Static Page title for specified locale + # @param locale requested locale for page title + # @return [String] the localized Static Page title + def localized_name(locale = Language.default.abbreviation) + if (spc = contents.find_by(language: Language.find_by(abbreviation: locale))) + spc.title.empty? ? name : spc.title + else + name + end + end +end diff --git a/app/models/static_page_content.rb b/app/models/static_page_content.rb new file mode 100644 index 0000000..36c4800 --- /dev/null +++ b/app/models/static_page_content.rb @@ -0,0 +1,29 @@ +# == Schema Information +# +# Table name: static_page_contents +# +# id :integer not null, primary key +# content :text +# title :string +# created_at :datetime not null +# updated_at :datetime not null +# language_id :integer not null +# static_page_id :integer not null +# +# Indexes +# +# index_static_page_contents_on_language_id (language_id) +# index_static_page_contents_on_static_page_id (static_page_id) +# +# Foreign Keys +# +# fk_rails_... (language_id => languages.id) +# fk_rails_... (static_page_id => static_pages.id) +# + +class StaticPageContent < ActiveRecord::Base + belongs_to :static_page + belongs_to :language + + validates :language, uniqueness: { scope: :static_page_id } +end diff --git a/app/policies/static_page_policy.rb b/app/policies/static_page_policy.rb new file mode 100644 index 0000000..969288e --- /dev/null +++ b/app/policies/static_page_policy.rb @@ -0,0 +1,34 @@ +class StaticPagePolicy < ApplicationPolicy + def initializer(user, *_args) + raise Pundit::NotAuthorizedError, _('must be logged in') unless user + @user = user + end + + def index? + @user.can_super_admin? + end + + def new? + @user.can_super_admin? + end + + def create? + @user.can_super_admin? + end + + def show? + @user.can_super_admin? + end + + def edit? + @user.can_super_admin? + end + + def update? + @user.can_super_admin? + end + + def destroy? + @user.can_super_admin? + end +end \ No newline at end of file diff --git a/app/views/branded/layouts/_branding.html.erb b/app/views/branded/layouts/_branding.html.erb index f1da75d..785f9b6 100644 --- a/app/views/branded/layouts/_branding.html.erb +++ b/app/views/branded/layouts/_branding.html.erb @@ -107,6 +107,11 @@
  • > <%= link_to(_('Usage'), usage_index_path) %>
  • + <% end %> + <% if current_user.can_super_admin? %> +
  • > + <%= link_to d_('dmpopidor', 'Static pages'), super_admin_static_pages_path %> +
  • <% end %> <% if current_user.can_super_admin? %>
  • > diff --git a/app/views/branded/layouts/_footer.html.erb b/app/views/branded/layouts/_footer.html.erb index 029ab11..9a5ae09 100644 --- a/app/views/branded/layouts/_footer.html.erb +++ b/app/views/branded/layouts/_footer.html.erb @@ -13,6 +13,7 @@
  • <%= Rails.configuration.branding[:application][:version] %>
  • <%= _('About') %>
  • +
  • <%= d_('dmpopidor', 'News') %>
  • <%= _('Terms of use') %>
  • <%= d_('dmpopidor', 'Tutorials') %>
  • diff --git a/app/views/branded/layouts/_navigation.html.erb b/app/views/branded/layouts/_navigation.html.erb index aae5674..c3ab115 100644 --- a/app/views/branded/layouts/_navigation.html.erb +++ b/app/views/branded/layouts/_navigation.html.erb @@ -46,6 +46,21 @@
  • > <%= link_to _('Help'), help_path %>
  • + <% unless @nav_static_pages.empty? %> +
  • + + +
  • + <% end %>