From 72246de0a3fa733d3898a1e48114d4ef9b85f874 Mon Sep 17 00:00:00 2001 From: pabois <pierreandre.boissinot@noesya.coop> Date: Wed, 27 Oct 2021 17:13:42 +0200 Subject: [PATCH] categories as tree --- app/assets/stylesheets/admin/treeview.sass | 5 +- .../website/categories_controller.rb | 27 +++++++- .../communication/website/pages_controller.rb | 1 - app/models/communication/website/category.rb | 9 +++ app/models/communication/website/page.rb | 3 +- .../website/categories/_form.html.erb | 13 ++++ .../website/categories/_list.html.erb | 12 +--- .../website/categories/_treebranch.html.erb | 28 +++++++++ .../website/categories/children.js.erb | 8 +++ .../website/categories/index.html.erb | 4 +- .../website/pages/_treebranch.html.erb | 2 +- .../website/pages/index.html.erb | 1 - .../communication/websites/show.html.erb | 63 ++++++++++--------- config/routes/admin/communication.rb | 3 + 14 files changed, 132 insertions(+), 47 deletions(-) create mode 100644 app/views/admin/communication/website/categories/_treebranch.html.erb create mode 100644 app/views/admin/communication/website/categories/children.js.erb diff --git a/app/assets/stylesheets/admin/treeview.sass b/app/assets/stylesheets/admin/treeview.sass index fa8dfffbf..929f7613f 100644 --- a/app/assets/stylesheets/admin/treeview.sass +++ b/app/assets/stylesheets/admin/treeview.sass @@ -52,8 +52,9 @@ .open_btn--without_children display: inline - & > .treeview__children .treeview__empty - display: inline + &.treeview__element--loaded + & > .treeview__children .treeview__empty + display: inline &--sortable .treeview__element diff --git a/app/controllers/admin/communication/website/categories_controller.rb b/app/controllers/admin/communication/website/categories_controller.rb index e4ed18932..b44e50315 100644 --- a/app/controllers/admin/communication/website/categories_controller.rb +++ b/app/controllers/admin/communication/website/categories_controller.rb @@ -1,13 +1,30 @@ class Admin::Communication::Website::CategoriesController < Admin::Communication::Website::ApplicationController load_and_authorize_resource class: Communication::Website::Category - include Admin::Reorderable + before_action :get_root_categories, only: [:index, :new, :create, :edit, :update] def index - @categories = @website.categories.ordered breadcrumb end + def reorder + parent_id = params['parentId'].blank? ? nil : params['parentId'] + ids = params['ids'] + ids.each.with_index do |id, index| + category = @website.categories.find(id) + category.update( + parent_id: parent_id, + position: index + 1 + ) + end + end + + def children + return unless request.xhr? + @category = @website.categories.find(params[:id]) + @children = @category.children.ordered + end + def show breadcrumb end @@ -50,6 +67,10 @@ class Admin::Communication::Website::CategoriesController < Admin::Communication protected + def get_root_categories + @root_categories = @website.categories.root.ordered + end + def breadcrumb super add_breadcrumb Communication::Website::Category.model_name.human(count: 2), @@ -59,6 +80,6 @@ class Admin::Communication::Website::CategoriesController < Admin::Communication def category_params params.require(:communication_website_category) - .permit(:university_id, :website_id, :name, :description) + .permit(:university_id, :website_id, :name, :description, :slug, :parent_id) end end diff --git a/app/controllers/admin/communication/website/pages_controller.rb b/app/controllers/admin/communication/website/pages_controller.rb index 3238ed540..fbdae9c68 100644 --- a/app/controllers/admin/communication/website/pages_controller.rb +++ b/app/controllers/admin/communication/website/pages_controller.rb @@ -4,7 +4,6 @@ class Admin::Communication::Website::PagesController < Admin::Communication::Web before_action :get_root_pages, only: [:index, :new, :create, :edit, :update] def index - breadcrumb end diff --git a/app/models/communication/website/category.rb b/app/models/communication/website/category.rb index 675f1c697..c1e4482a6 100644 --- a/app/models/communication/website/category.rb +++ b/app/models/communication/website/category.rb @@ -27,6 +27,7 @@ # class Communication::Website::Category < ApplicationRecord include WithSlug + include WithTree belongs_to :university belongs_to :website, @@ -54,6 +55,14 @@ class Communication::Website::Category < ApplicationRecord before_create :set_position + def list_of_other_categories + categories = [] + website.categories.where.not(id: id).root.ordered.each do |category| + categories.concat(category.self_and_children(0)) + end + categories.reject! { |p| p[:id] == id } + categories + end def to_s "#{name}" diff --git a/app/models/communication/website/page.rb b/app/models/communication/website/page.rb index 7f2e3da54..e7434dc80 100644 --- a/app/models/communication/website/page.rb +++ b/app/models/communication/website/page.rb @@ -49,7 +49,8 @@ class Communication::Website::Page < ApplicationRecord optional: true has_many :children, class_name: 'Communication::Website::Page', - foreign_key: :parent_id + foreign_key: :parent_id, + dependent: :nullify validates :title, presence: true diff --git a/app/views/admin/communication/website/categories/_form.html.erb b/app/views/admin/communication/website/categories/_form.html.erb index 1d988e3fa..d1d631c95 100644 --- a/app/views/admin/communication/website/categories/_form.html.erb +++ b/app/views/admin/communication/website/categories/_form.html.erb @@ -11,6 +11,19 @@ </div> </div> </div> + <div class="col-md-4"> + <div class="card flex-fill w-100"> + <div class="card-header"> + <h5 class="card-title mb-0"><%= t('communication.website.metadata') %></h5> + </div> + <div class="card-body"> + <%= f.input :slug, as: :string %> + <%= f.association :parent, collection: category.list_of_other_categories, label_method: ->(p) { sanitize p[:label] }, value_method: ->(p) { p[:id] } %> + <ul> + </ul> + </div> + </div> + </div> </div> <% content_for :action_bar_right do %> <%= submit f %> diff --git a/app/views/admin/communication/website/categories/_list.html.erb b/app/views/admin/communication/website/categories/_list.html.erb index 7a798b996..6b0f36e71 100644 --- a/app/views/admin/communication/website/categories/_list.html.erb +++ b/app/views/admin/communication/website/categories/_list.html.erb @@ -1,19 +1,13 @@ -<table class="<%= table_classes %> table-sortable"> +<table class="<%= table_classes %>"> <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) %>"> + <tbody> <% 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 %> + <tr> <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"> diff --git a/app/views/admin/communication/website/categories/_treebranch.html.erb b/app/views/admin/communication/website/categories/_treebranch.html.erb new file mode 100644 index 000000000..7b9b979b7 --- /dev/null +++ b/app/views/admin/communication/website/categories/_treebranch.html.erb @@ -0,0 +1,28 @@ +<% categories.each do |category| %> + <li class="treeview__element js-treeview-element <%= 'treeview__element--empty' unless category.has_children? %>" data-id="<%= category.id %>" data-parent="<%= category.parent_id %>"> + <div class="d-flex align-items-center treeview__label border-bottom p-1"> + <%= link_to children_admin_communication_website_category_path(website_id: category.website.id, id: category.id), + class: 'js-treeview-openzone d-inline-block p-2 ps-0', style: 'width: 22px', remote: true do %> + <% icon_style = category.has_children? ? 'fas' : 'far' %> + <span class="open_btn"> + <i class="open_btn--with_children fas fa-folder"></i> + <i class="open_btn--without_children far fa-folder"></i> + </span> + <span class="close_btn"> + <i class="close_btn--with_children fas fa-folder-open"></i> + <i class="close_btn--without_children far fa-folder-open"></i> + </span> + <% end %> + <%= link_to category, admin_communication_website_category_path(website_id: category.website.id, id: category.id) %> + <span class="move_btn py-2 ps-2"><i class="fas fa-sort"></i></span> + </div> + <ul class="list-unstyled treeview__children js-treeview-children js-treeview-sortable-container ms-4" data-id="<%= category.id %>"> + <li class="treeview__empty"> + <div class="d-flex align-items-center treeview__label border-bottom p-1"> + <span class="p-2 ps-0"><%= t('empty_folder') %></span> + </div> + </li> + <li class="treeview__loading border-bottom p-1"><%= t('loading') %></li> + </ul> + </li> +<% end %> diff --git a/app/views/admin/communication/website/categories/children.js.erb b/app/views/admin/communication/website/categories/children.js.erb new file mode 100644 index 000000000..477bb23c0 --- /dev/null +++ b/app/views/admin/communication/website/categories/children.js.erb @@ -0,0 +1,8 @@ +$branch = $('.js-treeview-element[data-id=<%= @category.id %>]'); +<% if @children.any? %> + $('.js-treeview-children', $branch).append("<%= escape_javascript(render 'treebranch', categories: @children) %>"); +<% else %> + $branch.addClass('treeview__element--empty'); +<% end %> +$branch.addClass('treeview__element--loaded'); +window.osuny.treeView.initSortable(); diff --git a/app/views/admin/communication/website/categories/index.html.erb b/app/views/admin/communication/website/categories/index.html.erb index bb47a5f47..dde54f4b5 100644 --- a/app/views/admin/communication/website/categories/index.html.erb +++ b/app/views/admin/communication/website/categories/index.html.erb @@ -1,6 +1,8 @@ <% content_for :title, "#{Communication::Website::Category.model_name.human(count: 2)} (#{@categories.count})" %> -<%= render 'list', categories: @categories %> +<ul class="list-unstyled treeview treeview--sortable js-treeview js-treeview-sortable js-treeview-sortable-container" data-id="" data-sort-url="<%= reorder_admin_communication_website_categories_path %>"> + <%= render 'treebranch', categories: @root_categories %> +</ul> <% content_for :action_bar_right do %> <%= create_link Communication::Website::Category %> diff --git a/app/views/admin/communication/website/pages/_treebranch.html.erb b/app/views/admin/communication/website/pages/_treebranch.html.erb index cad2da67b..89110854f 100644 --- a/app/views/admin/communication/website/pages/_treebranch.html.erb +++ b/app/views/admin/communication/website/pages/_treebranch.html.erb @@ -22,7 +22,7 @@ <span class="p-2 ps-0"><%= t('empty_folder') %></span> </div> </li> - <li class="treeview__loading"><%= t('loading') %></li> + <li class="treeview__loading border-bottom p-1"><%= t('loading') %></li> </ul> </li> <% end %> diff --git a/app/views/admin/communication/website/pages/index.html.erb b/app/views/admin/communication/website/pages/index.html.erb index ddd2e1f5d..5acbb551c 100644 --- a/app/views/admin/communication/website/pages/index.html.erb +++ b/app/views/admin/communication/website/pages/index.html.erb @@ -1,6 +1,5 @@ <% content_for :title, "#{Communication::Website::Page.model_name.human(count: 2)} (#{@website.pages.count})" %> - <ul class="list-unstyled treeview treeview--sortable js-treeview js-treeview-sortable js-treeview-sortable-container" data-id="" data-sort-url="<%= reorder_admin_communication_website_pages_path %>"> <%= render 'treebranch', pages: @root_pages %> </ul> diff --git a/app/views/admin/communication/websites/show.html.erb b/app/views/admin/communication/websites/show.html.erb index 950960f1f..1d2fe5e25 100644 --- a/app/views/admin/communication/websites/show.html.erb +++ b/app/views/admin/communication/websites/show.html.erb @@ -10,49 +10,30 @@ <% end %> <% end %> -<div class="card mt-5"> - <div class="card-header"> - <div class="float-end"> - <%= link_to_if can?(:create, Communication::Website::Post), - t('create'), - new_admin_communication_website_post_path(website_id: @website), - class: button_classes %> - </div> - <h2 class="card-title"> - <%= link_to admin_communication_website_posts_path(website_id: @website) do %> - <%= t('communication.website.last_posts') %> - <small> - - - <%= t('communication.website.see_all', number: @website.posts.count) %> - </small> - <% end %> - </h2> - </div> - <%= render 'admin/communication/website/posts/list', posts: @website.posts.recent %> -</div> - <div class="row"> <div class="col-md-7"> <div class="card mt-5"> <div class="card-header"> <div class="float-end"> - <%= link_to t('create'), - new_admin_communication_website_page_path(website_id: @website), + <%= link_to_if can?(:create, Communication::Website::Post), + t('create'), + new_admin_communication_website_post_path(website_id: @website), class: button_classes %> </div> <h2 class="card-title"> - <%= link_to admin_communication_website_pages_path(website_id: @website) do %> - <%= t('communication.website.last_pages') %> + <%= link_to admin_communication_website_posts_path(website_id: @website) do %> + <%= t('communication.website.last_posts') %> <small> - - <%= t('communication.website.see_all', number: @website.pages.count) %> + <%= t('communication.website.see_all', number: @website.posts.count) %> </small> <% end %> </h2> </div> - <%= render 'admin/communication/website/pages/list', pages: @website.pages.recent %> + <%= render 'admin/communication/website/posts/list', posts: @website.posts.recent %> </div> </div> + <div class="col-md-5"> <div class="card mt-5"> <div class="card-header"> @@ -71,11 +52,37 @@ <% end %> </h2> </div> - <%= render 'admin/communication/website/categories/list', categories: @website.categories.ordered %> + <%= render 'admin/communication/website/categories/list', categories: @website.categories.root.ordered %> + </div> + </div> +</div> + +<div class="row"> + <div class="col-md-12"> + <div class="card mt-5"> + <div class="card-header"> + <div class="float-end"> + <%= link_to t('create'), + new_admin_communication_website_page_path(website_id: @website), + class: button_classes %> + </div> + <h2 class="card-title"> + <%= link_to admin_communication_website_pages_path(website_id: @website) do %> + <%= t('communication.website.last_pages') %> + <small> + - + <%= t('communication.website.see_all', number: @website.pages.count) %> + </small> + <% end %> + </h2> + </div> + <%= render 'admin/communication/website/pages/list', pages: @website.pages.recent %> </div> </div> </div> + + <% content_for :action_bar_right do %> <% if @website.imported? %> <%= link_to t('communication.website.imported.show'), diff --git a/config/routes/admin/communication.rb b/config/routes/admin/communication.rb index ece445755..436bbdbb2 100644 --- a/config/routes/admin/communication.rb +++ b/config/routes/admin/communication.rb @@ -16,6 +16,9 @@ namespace :communication do collection do post :reorder end + member do + get :children + end end resources :posts, controller: 'website/posts' end -- GitLab