diff --git a/app/assets/javascripts/admin/sortable.js b/app/assets/javascripts/admin/sortable.js new file mode 100644 index 0000000000000000000000000000000000000000..e34e6fbfd08c626604e59e291d180ac10a2ed92b --- /dev/null +++ b/app/assets/javascripts/admin/sortable.js @@ -0,0 +1,26 @@ +/*global $, Sortable */ +$(function () { + 'use strict'; + // Re-order elements of a table. Needs a "table-sortable" class on the table, a "data-reorder-url" param on the tbody and a "data-id" param on each tr + var nestedSortables = [].slice.call(document.querySelectorAll('.table-sortable tbody')), + i; + for (i = 0; i < nestedSortables.length; i += 1) { + new Sortable(nestedSortables[i], { + handle: '.handle', + group: 'nested', + animation: 150, + fallbackOnBody: true, + swapThreshold: 0.65, + onEnd: function (evt) { + var to = evt.to, + ids = [], + url = $(to).attr('data-reorder-url'); + // get list of ids + $('> tr', to).each(function () { + ids.push($(this).attr('data-id')); + }); + $.post(url, { ids: ids }); + } + }); + } +}); diff --git a/app/controllers/admin/communication/website/categories_controller.rb b/app/controllers/admin/communication/website/categories_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..e4ed189322b48bf825a59f7a31cccf10fc940eed --- /dev/null +++ b/app/controllers/admin/communication/website/categories_controller.rb @@ -0,0 +1,64 @@ +class Admin::Communication::Website::CategoriesController < Admin::Communication::Website::ApplicationController + load_and_authorize_resource class: Communication::Website::Category + + include Admin::Reorderable + + def index + @categories = @website.categories.ordered + breadcrumb + end + + def show + breadcrumb + end + + def new + @category.website = @website + breadcrumb + end + + def edit + breadcrumb + add_breadcrumb t('edit') + end + + def create + @category.university = current_university + @category.website = @website + if @category.save + redirect_to admin_communication_website_category_path(@category), notice: t('admin.successfully_created_html', model: @category.to_s) + else + breadcrumb + render :new, status: :unprocessable_entity + end + end + + def update + if @category.update(category_params) + redirect_to admin_communication_website_category_path(@category), notice: t('admin.successfully_updated_html', model: @category.to_s) + else + breadcrumb + add_breadcrumb t('edit') + render :edit, status: :unprocessable_entity + end + end + + def destroy + @category.destroy + redirect_to admin_communication_website_categories_url, notice: t('admin.successfully_destroyed_html', model: @category.to_s) + end + + protected + + def breadcrumb + super + add_breadcrumb Communication::Website::Category.model_name.human(count: 2), + admin_communication_website_categories_path + breadcrumb_for @category + end + + def category_params + params.require(:communication_website_category) + .permit(:university_id, :website_id, :name, :description) + end +end diff --git a/app/controllers/concerns/admin/reorderable.rb b/app/controllers/concerns/admin/reorderable.rb new file mode 100644 index 0000000000000000000000000000000000000000..2ce07bf582985548f7f69d1f07f0363034e669e6 --- /dev/null +++ b/app/controllers/concerns/admin/reorderable.rb @@ -0,0 +1,18 @@ +module Admin::Reorderable + extend ActiveSupport::Concern + + included do + def reorder + ids = params[:ids] + ids.each.with_index do |id, index| + object = model.find_by(id: id) + object.update_column(:position, index + 1) unless object.nil? + end + end + + def model + self.class.to_s.remove('Admin::').remove('Controller').singularize.safe_constantize + end + end + +end diff --git a/app/models/communication/website.rb b/app/models/communication/website.rb index c41cac826474e3dfc420fe3c9bb66f92960ab53a..eac3c8285a7b9cbfe9873ea92db139369f64e8ab 100644 --- a/app/models/communication/website.rb +++ b/app/models/communication/website.rb @@ -27,6 +27,7 @@ class Communication::Website < ApplicationRecord belongs_to :about, polymorphic: true, optional: true has_many :pages, foreign_key: :communication_website_id has_many :posts, foreign_key: :communication_website_id + has_many :categories, class_name: 'Communication::Website::Category', foreign_key: :communication_website_id has_one :imported_website, class_name: 'Communication::Website::Imported::Website', dependent: :destroy diff --git a/app/models/communication/website/category.rb b/app/models/communication/website/category.rb new file mode 100644 index 0000000000000000000000000000000000000000..8c7724b3b66f06382c8ffed5562eb9c674687ddd --- /dev/null +++ b/app/models/communication/website/category.rb @@ -0,0 +1,53 @@ +# == Schema Information +# +# Table name: communication_website_categories +# +# id :uuid not null, primary key +# description :text +# name :string +# position :integer +# created_at :datetime not null +# updated_at :datetime not null +# communication_website_id :uuid not null +# university_id :uuid not null +# +# Indexes +# +# idx_communication_website_post_cats_on_communication_website_id (communication_website_id) +# index_communication_website_categories_on_university_id (university_id) +# +# Foreign Keys +# +# fk_rails_... (communication_website_id => communication_websites.id) +# fk_rails_... (university_id => universities.id) +# +class Communication::Website::Category < ApplicationRecord + + belongs_to :university + belongs_to :website, + foreign_key: :communication_website_id + + validates :name, presence: true + + scope :ordered, -> { order(:position) } + + before_create :set_position + + + def to_s + "#{name}" + end + + protected + + def set_position + last_element = website.categories.ordered.last + + unless last_element.nil? + self.position = last_element.position + 1 + else + self.position = 1 + end + end + +end diff --git a/app/views/admin/communication/website/categories/_form.html.erb b/app/views/admin/communication/website/categories/_form.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..1d988e3fa744856c5353c2aef0df3e1a7ce668c2 --- /dev/null +++ b/app/views/admin/communication/website/categories/_form.html.erb @@ -0,0 +1,18 @@ +<%= simple_form_for [:admin, category] do |f| %> + <div class="row"> + <div class="col-md-8"> + <div class="card flex-fill w-100"> + <div class="card-header"> + <h5 class="card-title mb-0"><%= t('communication.website.content') %></h5> + </div> + <div class="card-body"> + <%= f.input :name %> + <%= f.input :description %> + </div> + </div> + </div> + </div> + <% content_for :action_bar_right do %> + <%= submit f %> + <% end %> +<% end %> diff --git a/app/views/admin/communication/website/categories/_list.html.erb b/app/views/admin/communication/website/categories/_list.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..dad41187f932bc67d1d0a660a9a80ac7a5156b2d --- /dev/null +++ b/app/views/admin/communication/website/categories/_list.html.erb @@ -0,0 +1,27 @@ +<table class="<%= table_classes %> table-sortable"> + <thead> + <tr> + <% if can? :reorder, Communication::Website::Category %> + <th width="20"> </th> + <% end %> + <th><%= Communication::Website::Category.human_attribute_name('title') %></th> + <th></th> + </tr> + </thead> + <tbody data-reorder-url="<%= reorder_admin_communication_website_categories_path(@website) %>"> + <% categories.each do |category| %> + <tr data-id="<%= category.id %>"> + <% if can? :reorder, Communication::Website::Category %> + <td><i class="fa fa-bars handle"></i></td> + <% end %> + <td><%= link_to category, admin_communication_website_category_path(website_id: category.website.id, id: category.id) %></td> + <td class="text-end"> + <div class="btn-group" role="group"> + <%= edit_link category %> + <%= destroy_link category %> + </div> + </td> + </tr> + <% end %> + </tbody> +</table> diff --git a/app/views/admin/communication/website/categories/edit.html.erb b/app/views/admin/communication/website/categories/edit.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..123bc888b09752ba30b4db4eba62ec37bcbd07d2 --- /dev/null +++ b/app/views/admin/communication/website/categories/edit.html.erb @@ -0,0 +1,3 @@ +<% content_for :title, @category %> + +<%= render 'form', category: @category %> diff --git a/app/views/admin/communication/website/categories/index.html.erb b/app/views/admin/communication/website/categories/index.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..bb47a5f4750937fd78a5d7a2c2141a87ae266782 --- /dev/null +++ b/app/views/admin/communication/website/categories/index.html.erb @@ -0,0 +1,7 @@ +<% content_for :title, "#{Communication::Website::Category.model_name.human(count: 2)} (#{@categories.count})" %> + +<%= render 'list', categories: @categories %> + +<% content_for :action_bar_right do %> + <%= create_link Communication::Website::Category %> +<% end %> diff --git a/app/views/admin/communication/website/categories/new.html.erb b/app/views/admin/communication/website/categories/new.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..f92532bde4aa34d077cb23a65cfdc18643b689a7 --- /dev/null +++ b/app/views/admin/communication/website/categories/new.html.erb @@ -0,0 +1,3 @@ +<% content_for :title, Communication::Website::Category.model_name.human %> + +<%= render 'form', category: @category %> diff --git a/app/views/admin/communication/website/categories/show.html.erb b/app/views/admin/communication/website/categories/show.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..96aa0af3fe3d008b278a5d1891db34d087e95f12 --- /dev/null +++ b/app/views/admin/communication/website/categories/show.html.erb @@ -0,0 +1,21 @@ +<% content_for :title, @category %> + +<div class="row"> + <div class="col-md-8"> + <div class="card flex-fill w-100"> + <div class="card-header"> + <h5 class="card-title mb-0"><%= t('communication.website.content') %></h5> + </div> + <div class="card-body"> + <p> + <strong><%= Communication::Website::Category.human_attribute_name('description') %></strong> + </p> + <%= sanitize @category.description %> + </div> + </div> + </div> +</div> + +<% content_for :action_bar_right do %> + <%= edit_link @category %> +<% end %> diff --git a/app/views/admin/communication/websites/show.html.erb b/app/views/admin/communication/websites/show.html.erb index 074e302de7c4299b43a6884f8130734542370f8c..8f372b3bcb2e39958ecfddf1000bea39a8ed3ee8 100644 --- a/app/views/admin/communication/websites/show.html.erb +++ b/app/views/admin/communication/websites/show.html.erb @@ -30,6 +30,7 @@ </div> <%= render 'admin/communication/website/posts/list', posts: @website.posts.recent %> </div> + <div class="card mt-5"> <div class="card-header"> <div class="float-end"> @@ -50,6 +51,21 @@ <%= render 'admin/communication/website/pages/list', pages: @website.pages.recent %> </div> +<div class="card mt-5"> + <div class="card-header"> + <div class="float-end"> + <%= link_to t('create'), + new_admin_communication_website_category_path(website_id: @website), + class: button_classes %> + </div> + <h2 class="card-title"> + <%= Communication::Website::Category.model_name.human(count: 2) %> + <%= "(#{@website.categories.count})" %> + </h2> + </div> + <%= render 'admin/communication/website/categories/list', categories: @website.categories.ordered %> +</div> + <% content_for :action_bar_right do %> <% if @website.imported? %> diff --git a/config/locales/communication/en.yml b/config/locales/communication/en.yml index b04f9923b29609e13850955103ba4d13df13e90c..857bbe2d329396bee0458bcd48f27cc35bb8a523 100644 --- a/config/locales/communication/en.yml +++ b/config/locales/communication/en.yml @@ -25,6 +25,13 @@ en: communication/website: one: Website other: Websites + communication/website/category: + one: Category + other: Categories + all: All categories + communication/website/imported/website: + one: Imported website + other: Imported websites communication/website/page: one: Page other: Pages @@ -33,9 +40,6 @@ en: one: Post other: Posts all: All posts - communication/website/imported/website: - one: Imported website - other: Imported websites attributes: communication/website: name: Name @@ -44,6 +48,9 @@ en: about_: Independent website (no specific subject) about_Research::Journal: Journal website about_Education::School: School website + communication/website/category: + description: Description + title: Title communication/website/imported/medium: filename: Filename communication/website/page: diff --git a/config/locales/communication/fr.yml b/config/locales/communication/fr.yml index cfd9c6d99e1541e7e60c3e08a574af44cedd0534..72f4d2b2e844e1fb38332cd27a60fef32f0bbcf4 100644 --- a/config/locales/communication/fr.yml +++ b/config/locales/communication/fr.yml @@ -25,6 +25,13 @@ fr: communication/website: one: Site Web other: Sites Web + communication/website/category: + one: Catégorie + other: Catégories + all: Toutes les catégories + communication/website/imported/website: + one: Site importé + other: Sites importés communication/website/page: one: Page other: Pages @@ -33,9 +40,6 @@ fr: one: Actualité other: Actualités all: Toutes les actualités - communication/website/imported/website: - one: Site importé - other: Sites importés attributes: communication/website: name: Nom @@ -44,6 +48,9 @@ fr: about_: Site indépendant (aucun sujet) about_Research::Journal: Site de revue scientifique about_Education::School: Site d'école + communication/website/category: + description: Description + title: Titre communication/website/imported/medium: filename: Nom du fichier communication/website/page: diff --git a/config/routes/admin/communication.rb b/config/routes/admin/communication.rb index 98e4d278f3283e539df38fee03866e27ad678d29..ece4457558c25348270668532e66de271dab4e7d 100644 --- a/config/routes/admin/communication.rb +++ b/config/routes/admin/communication.rb @@ -12,6 +12,11 @@ namespace :communication do get :children end end + resources :categories, controller: 'website/categories' do + collection do + post :reorder + end + end resources :posts, controller: 'website/posts' end end diff --git a/db/migrate/20211026124139_create_communication_website_categories.rb b/db/migrate/20211026124139_create_communication_website_categories.rb new file mode 100644 index 0000000000000000000000000000000000000000..febee26b527912f20c22fb12a9e0eed423c1b343 --- /dev/null +++ b/db/migrate/20211026124139_create_communication_website_categories.rb @@ -0,0 +1,16 @@ +class CreateCommunicationWebsiteCategories < ActiveRecord::Migration[6.1] + def change + create_table :communication_website_categories, id: :uuid do |t| + t.references :university, null: false, foreign_key: true, type: :uuid + t.references :communication_website, + null: false, + foreign_key: { to_table: :communication_websites }, + type: :uuid, + index: { name: 'idx_communication_website_post_cats_on_communication_website_id' } + t.string :name + t.text :description + t.integer :position + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 303bcfee2efd01c90219c4c8975c3c60550b4eb9..30cb480defa261ea41539ab542dc04830c4c42e4 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_10_26_094556) do +ActiveRecord::Schema.define(version: 2021_10_26_124139) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" @@ -78,6 +78,18 @@ ActiveRecord::Schema.define(version: 2021_10_26_094556) do t.index ["criterion_id"], name: "index_administration_qualiopi_indicators_on_criterion_id" end + create_table "communication_website_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false + t.uuid "communication_website_id", null: false + t.string "name" + t.text "description" + t.integer "position" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["communication_website_id"], name: "idx_communication_website_post_cats_on_communication_website_id" + t.index ["university_id"], name: "index_communication_website_categories_on_university_id" + end + create_table "communication_website_imported_media", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "identifier" t.jsonb "data" @@ -386,6 +398,8 @@ ActiveRecord::Schema.define(version: 2021_10_26_094556) do add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" add_foreign_key "administration_qualiopi_indicators", "administration_qualiopi_criterions", column: "criterion_id" + add_foreign_key "communication_website_categories", "communication_websites" + add_foreign_key "communication_website_categories", "universities" add_foreign_key "communication_website_imported_media", "communication_website_imported_websites", column: "website_id" add_foreign_key "communication_website_imported_media", "universities" add_foreign_key "communication_website_imported_pages", "communication_website_imported_media", column: "featured_medium_id"