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">&nbsp;</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