From 50d449376c9b41d0f2d08d525d5ecaf53f2dbb6b Mon Sep 17 00:00:00 2001
From: Arnaud Levy <contact@arnaudlevy.com>
Date: Sun, 22 Jan 2023 16:01:33 +0100
Subject: [PATCH] panel

---
 .../stylesheets/admin/appstack/style.sass     |  4 +
 app/assets/stylesheets/admin/pure/style.sass  |  4 +-
 app/helpers/admin/application_helper.rb       | 11 +++
 .../blocks/components/layout/_edit.html.erb   |  4 +-
 .../admin/communication/blocks/edit.html.erb  |  2 +-
 .../admin/communication/blocks/new.html.erb   |  2 +-
 .../templates/call_to_action/_edit.html.erb   |  2 +-
 .../blocks/templates/chapter/_edit.html.erb   |  2 +-
 .../blocks/templates/contact/_edit.html.erb   |  2 +-
 .../blocks/templates/datatable/_edit.html.erb |  2 +-
 .../templates/definitions/_edit.html.erb      |  2 +-
 .../blocks/templates/embed/_edit.html.erb     |  4 +-
 .../blocks/templates/files/_edit.html.erb     |  4 +-
 .../blocks/templates/gallery/_edit.html.erb   |  4 +-
 .../blocks/templates/image/_edit.html.erb     |  2 +-
 .../templates/key_figures/_edit.html.erb      |  2 +-
 .../organization_chart/_edit.html.erb         |  2 +-
 .../blocks/templates/pages/_edit.html.erb     |  2 +-
 .../blocks/templates/partners/_edit.html.erb  |  2 +-
 .../blocks/templates/posts/_edit.html.erb     |  2 +-
 .../blocks/templates/programs/_edit.html.erb  |  2 +-
 .../templates/testimonials/_edit.html.erb     |  2 +-
 .../blocks/templates/video/_edit.html.erb     |  2 +-
 .../websites/menus/items/_form.html.erb       |  4 +-
 .../websites/posts/_form.html.erb             |  4 +-
 .../websites/posts/show.html.erb              |  2 +-
 app/views/admin/dashboard/index.html.erb      | 86 +++++++------------
 .../layouts/themes/appstack/_panel.html.erb   | 13 +++
 .../admin/layouts/themes/pure/_panel.html.erb |  9 ++
 29 files changed, 101 insertions(+), 84 deletions(-)
 create mode 100644 app/views/admin/layouts/themes/appstack/_panel.html.erb
 create mode 100644 app/views/admin/layouts/themes/pure/_panel.html.erb

diff --git a/app/assets/stylesheets/admin/appstack/style.sass b/app/assets/stylesheets/admin/appstack/style.sass
index d0c9e8f1e..207823f07 100644
--- a/app/assets/stylesheets/admin/appstack/style.sass
+++ b/app/assets/stylesheets/admin/appstack/style.sass
@@ -22,6 +22,10 @@ main.content
     @include media-breakpoint-up(lg)
         left: 260px
 
+.category
+    font-size: 16px
+    margin-bottom: 24px
+    margin-top: 48px
 
 .card-footer
     .pagination
diff --git a/app/assets/stylesheets/admin/pure/style.sass b/app/assets/stylesheets/admin/pure/style.sass
index 2200d7a0f..b0f661a69 100644
--- a/app/assets/stylesheets/admin/pure/style.sass
+++ b/app/assets/stylesheets/admin/pure/style.sass
@@ -56,7 +56,7 @@ main
 h2
     font-weight: bold
 
-.section
+.category
     border-bottom: 1px solid $color-border
     font-size: $h5-font-size
     font-weight: normal
@@ -65,7 +65,7 @@ h2
     padding-bottom: $spacing0
     text-transform: uppercase
 
-.row-small
+.pure__row--small
     margin-left: calc(-.5 * #{$spacing1})
     margin-right: calc(-.5 * #{$spacing1})
     > *
diff --git a/app/helpers/admin/application_helper.rb b/app/helpers/admin/application_helper.rb
index 81df5fccd..976bd721d 100644
--- a/app/helpers/admin/application_helper.rb
+++ b/app/helpers/admin/application_helper.rb
@@ -45,6 +45,17 @@ module Admin::ApplicationHelper
                   aria-controls=\"preview\">#{ t 'preview.button'}</button>"
   end
 
+  def panel(title: nil, subtitle: nil, action: nil, &block)
+    render  layout: "admin/layouts/themes/#{current_admin_theme}/panel",
+            locals: { 
+              title: title, 
+              subtitle: subtitle,
+              action: action
+            } do
+      capture(&block)
+    end
+  end
+
   def duplicate_link(object)
     return unless can?(:update, object)
     link_to t('admin.duplicate'),
diff --git a/app/views/admin/communication/blocks/components/layout/_edit.html.erb b/app/views/admin/communication/blocks/components/layout/_edit.html.erb
index 61cfd7982..a6b572ac9 100644
--- a/app/views/admin/communication/blocks/components/layout/_edit.html.erb
+++ b/app/views/admin/communication/blocks/components/layout/_edit.html.erb
@@ -15,7 +15,7 @@ layouts = template.class.layouts
   </a>
 </p>
 
-<div class="row row-small collapse" id="layouts">
+<div class="row pure__row--small collapse" id="layouts">
   <% layouts.each do |layout| %>
     <%
     i18n = "admin.communication.blocks.templates.#{template.kind}.layouts.#{layout}"
@@ -25,7 +25,7 @@ layouts = template.class.layouts
     <div class="col-xxl-6">
       <div class="card mb-4">
         <label for="layout-<%= layout %>">
-          <div class="row row-small">
+          <div class="row pure__row--small">
             <div class="col-8 col-xxl-6">
               <div class="card-body">
                 <div class="form-check">
diff --git a/app/views/admin/communication/blocks/edit.html.erb b/app/views/admin/communication/blocks/edit.html.erb
index b88d674bf..e537888e3 100644
--- a/app/views/admin/communication/blocks/edit.html.erb
+++ b/app/views/admin/communication/blocks/edit.html.erb
@@ -9,7 +9,7 @@
 
     <div class="row">
       <div class="col-xxl-9 col-lg-8">
-        <div class="row row-small">
+        <div class="row pure__row--small">
           <div class="col-lg-6">
             <%= f.input :title %>
           </div>
diff --git a/app/views/admin/communication/blocks/new.html.erb b/app/views/admin/communication/blocks/new.html.erb
index bfe43bae6..975d546fd 100644
--- a/app/views/admin/communication/blocks/new.html.erb
+++ b/app/views/admin/communication/blocks/new.html.erb
@@ -7,7 +7,7 @@
       <p class="text-end lead"><%= t "admin.communication.blocks.categories.#{category}.description" %></p>
     </div>
     <hr class="mt-0">
-    <div class="row row-small">
+    <div class="row pure__row--small">
       <% kinds.each do |kind| %>
         <%
         @block.template_reset!
diff --git a/app/views/admin/communication/blocks/templates/call_to_action/_edit.html.erb b/app/views/admin/communication/blocks/templates/call_to_action/_edit.html.erb
index d49dca48f..8536cd91a 100644
--- a/app/views/admin/communication/blocks/templates/call_to_action/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/call_to_action/_edit.html.erb
@@ -1,4 +1,4 @@
-<div class="row row-small mb-5">
+<div class="row pure__row--small mb-5">
   <div class="col-md-6">
     <div class="summernote">
       <%= block_component_edit :text,
diff --git a/app/views/admin/communication/blocks/templates/chapter/_edit.html.erb b/app/views/admin/communication/blocks/templates/chapter/_edit.html.erb
index c815514dc..bd17197b0 100644
--- a/app/views/admin/communication/blocks/templates/chapter/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/chapter/_edit.html.erb
@@ -1,6 +1,6 @@
 <%= block_component_edit :layout %>
 
-<div class="row row-small mb-4">
+<div class="row pure__row--small mb-4">
   <div class="col-xxl-8">
     <%= block_component_edit :text %>
     <%= block_component_edit :notes %>
diff --git a/app/views/admin/communication/blocks/templates/contact/_edit.html.erb b/app/views/admin/communication/blocks/templates/contact/_edit.html.erb
index 00ad26147..4b5d8277c 100644
--- a/app/views/admin/communication/blocks/templates/contact/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/contact/_edit.html.erb
@@ -1,4 +1,4 @@
-<div class="row row-small">
+<div class="row pure__row--small">
   <div class="col-xl-6">
     <%= block_component_edit :description %>
   </div>
diff --git a/app/views/admin/communication/blocks/templates/datatable/_edit.html.erb b/app/views/admin/communication/blocks/templates/datatable/_edit.html.erb
index 7686558bf..546c3eaa3 100644
--- a/app/views/admin/communication/blocks/templates/datatable/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/datatable/_edit.html.erb
@@ -1,4 +1,4 @@
-<div class="row row-small">
+<div class="row pure__row--small">
   <div class="col-xl-6">
     <%= block_component_edit :description %>
   </div>
diff --git a/app/views/admin/communication/blocks/templates/definitions/_edit.html.erb b/app/views/admin/communication/blocks/templates/definitions/_edit.html.erb
index 6b669d85c..acf892a73 100644
--- a/app/views/admin/communication/blocks/templates/definitions/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/definitions/_edit.html.erb
@@ -1,4 +1,4 @@
-<div class="row row-small">
+<div class="row pure__row--small">
   <div class="col-xl-6">
     <%= block_component_edit :description %>
   </div>
diff --git a/app/views/admin/communication/blocks/templates/embed/_edit.html.erb b/app/views/admin/communication/blocks/templates/embed/_edit.html.erb
index c66f6ae0a..b653c9f73 100644
--- a/app/views/admin/communication/blocks/templates/embed/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/embed/_edit.html.erb
@@ -1,9 +1,9 @@
-<div class="row row-small">
+<div class="row pure__row--small">
   <div class="col-md-6">
     <p class="text-danger lead"><%= t '.warning' %></p>
   </div>
 </div>
-<div class="row row-small">
+<div class="row pure__row--small">
   <div class="col-md-6">
     <%= block_component_edit :code %>
   </div>
diff --git a/app/views/admin/communication/blocks/templates/files/_edit.html.erb b/app/views/admin/communication/blocks/templates/files/_edit.html.erb
index b7cf262a2..dd7c974b6 100644
--- a/app/views/admin/communication/blocks/templates/files/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/files/_edit.html.erb
@@ -1,4 +1,4 @@
-<div class="row row-small">
+<div class="row pure__row--small">
   <div class="col-xl-6">
     <%= block_component_edit :description %>
   </div>
@@ -6,7 +6,7 @@
 
 <%= block_component_add_element t('.add_file') %>
 
-<draggable :list="data.elements" handle=".dragHandle" class="row row-small">
+<draggable :list="data.elements" handle=".dragHandle" class="row pure__row--small">
   <div v-for="(element, index) in data.elements" class="col-md-4">
     <div class="card">
       <div class="card-header border-bottom">
diff --git a/app/views/admin/communication/blocks/templates/gallery/_edit.html.erb b/app/views/admin/communication/blocks/templates/gallery/_edit.html.erb
index 555dfbaae..f3a67262f 100644
--- a/app/views/admin/communication/blocks/templates/gallery/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/gallery/_edit.html.erb
@@ -1,4 +1,4 @@
-<div class="row row-small">
+<div class="row pure__row--small">
   <div class="col-xl-6">
     <%= block_component_edit :description %>
   </div>
@@ -11,7 +11,7 @@
 
   <p>Déplacer les images ci-dessous pour les mettre dans l'ordre souhaité</p>
 
-  <draggable :list="data.elements" class="row row-small">
+  <draggable :list="data.elements" class="row pure__row--small">
     <div v-for="(element, index) in data.elements" class="col-xxl-1 col-lg-2 col-4">
       <div class="card">
         <div class="card-header p-1 text-center">
diff --git a/app/views/admin/communication/blocks/templates/image/_edit.html.erb b/app/views/admin/communication/blocks/templates/image/_edit.html.erb
index 107fd237f..e4a5433e6 100644
--- a/app/views/admin/communication/blocks/templates/image/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/image/_edit.html.erb
@@ -1,4 +1,4 @@
-<div class="row row-small">
+<div class="row pure__row--small">
   <div class="col-md-6">
     <%= block_component_edit :image %>
   </div>
diff --git a/app/views/admin/communication/blocks/templates/key_figures/_edit.html.erb b/app/views/admin/communication/blocks/templates/key_figures/_edit.html.erb
index b0b070e00..d3326874e 100644
--- a/app/views/admin/communication/blocks/templates/key_figures/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/key_figures/_edit.html.erb
@@ -1,4 +1,4 @@
-<div class="row row-small">
+<div class="row pure__row--small">
   <div class="col-xl-6">
     <%= block_component_edit :description %>
   </div>
diff --git a/app/views/admin/communication/blocks/templates/organization_chart/_edit.html.erb b/app/views/admin/communication/blocks/templates/organization_chart/_edit.html.erb
index 1814ee1a5..5997f3dce 100644
--- a/app/views/admin/communication/blocks/templates/organization_chart/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/organization_chart/_edit.html.erb
@@ -1,4 +1,4 @@
-<div class="row row-small">
+<div class="row pure__row--small">
   <div class="col-xl-6">
     <%= block_component_edit :description %>
   </div>
diff --git a/app/views/admin/communication/blocks/templates/pages/_edit.html.erb b/app/views/admin/communication/blocks/templates/pages/_edit.html.erb
index eef4145c8..115ca7b29 100644
--- a/app/views/admin/communication/blocks/templates/pages/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/pages/_edit.html.erb
@@ -2,7 +2,7 @@
 
 <%= block_component_edit :layout %>
 
-<div class="row row-small">
+<div class="row pure__row--small">
   <div class="col-lg-6">
     <div class="mb-5">
       <%= block_component_edit :mode %>
diff --git a/app/views/admin/communication/blocks/templates/partners/_edit.html.erb b/app/views/admin/communication/blocks/templates/partners/_edit.html.erb
index 552fee473..8decbfa3c 100644
--- a/app/views/admin/communication/blocks/templates/partners/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/partners/_edit.html.erb
@@ -1,4 +1,4 @@
-<div class="row row-small">
+<div class="row pure__row--small">
   <div class="col-xl-6">
     <%= block_component_edit :description %>
   </div>
diff --git a/app/views/admin/communication/blocks/templates/posts/_edit.html.erb b/app/views/admin/communication/blocks/templates/posts/_edit.html.erb
index 5d81b6649..bfaa46d91 100644
--- a/app/views/admin/communication/blocks/templates/posts/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/posts/_edit.html.erb
@@ -4,7 +4,7 @@
 
 <div class="mb-3">
   <%= block_component_edit :mode %>
-  <div class="row row-small">
+  <div class="row pure__row--small">
     <div v-if="data.mode === 'category' || data.mode === 'all'" class="col-lg-3">
       <%= block_component_edit :posts_quantity %>
     </div>
diff --git a/app/views/admin/communication/blocks/templates/programs/_edit.html.erb b/app/views/admin/communication/blocks/templates/programs/_edit.html.erb
index 3dd1978b5..16b833103 100644
--- a/app/views/admin/communication/blocks/templates/programs/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/programs/_edit.html.erb
@@ -1,6 +1,6 @@
 <% pages = collection_tree(@block.university.programs) %>
 
-<div class="row row-small">
+<div class="row pure__row--small">
   <div class="col-lg-6">
     <div class="mb-4">
       <%= block_component_add_element t('.add') %>
diff --git a/app/views/admin/communication/blocks/templates/testimonials/_edit.html.erb b/app/views/admin/communication/blocks/templates/testimonials/_edit.html.erb
index e5e4e16e4..c31511b79 100644
--- a/app/views/admin/communication/blocks/templates/testimonials/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/testimonials/_edit.html.erb
@@ -1,6 +1,6 @@
 <%= block_component_add_element t('.add_testimonial') %>
 
-<draggable :list="data.elements" handle=".dragHandle" class="row row-small">
+<draggable :list="data.elements" handle=".dragHandle" class="row pure__row--small">
   <div v-for="(element, index) in data.elements" class="list-group-item">
     <div class="d-flex">
       <div>
diff --git a/app/views/admin/communication/blocks/templates/video/_edit.html.erb b/app/views/admin/communication/blocks/templates/video/_edit.html.erb
index 58e2a9d64..33fb78314 100644
--- a/app/views/admin/communication/blocks/templates/video/_edit.html.erb
+++ b/app/views/admin/communication/blocks/templates/video/_edit.html.erb
@@ -1,4 +1,4 @@
-<div class="row row-small">
+<div class="row pure__row--small">
   <div class="col-md-6">
     <%= block_component_edit :url %>
     <%= block_component_edit :video_title %>
diff --git a/app/views/admin/communication/websites/menus/items/_form.html.erb b/app/views/admin/communication/websites/menus/items/_form.html.erb
index 2a1fce91e..fd977e794 100644
--- a/app/views/admin/communication/websites/menus/items/_form.html.erb
+++ b/app/views/admin/communication/websites/menus/items/_form.html.erb
@@ -6,7 +6,7 @@
   <%= f.input :parent_id, as: :hidden, wrapper: false %>
     <h2 class="h3"><%= t('content') %></h2>
     <div class="card-body">
-      <div class="row row-small">
+      <div class="row pure__row--small">
         <div class="col-lg-6">
           <%= f.input :title %>
         </div>
@@ -57,7 +57,7 @@
           <%= Communication::Website::Menu::Item.human_attribute_name('kind') %>
           <abbr title="required">*</abbr>
         </label>
-        <div class="row row-small">
+        <div class="row pure__row--small">
           <% @website.menu_item_kinds.keys.each do |kind| %>
             <div class="col-6 col-lg-4 col-xl-3 col-xxl-2">
               <div class="card kind" data-kind="<%= kind %>">
diff --git a/app/views/admin/communication/websites/posts/_form.html.erb b/app/views/admin/communication/websites/posts/_form.html.erb
index 92e1a03b2..bec8f60e5 100644
--- a/app/views/admin/communication/websites/posts/_form.html.erb
+++ b/app/views/admin/communication/websites/posts/_form.html.erb
@@ -10,7 +10,7 @@
         <%= render 'admin/application/summary/form', f: f, about: post %>
         <%= f.input :text, as: :summernote if post.text&.to_plain_text.present? %>
       </section>
-      <div class="row row-small">
+      <div class="row pure__row--small">
         <% if @website.categories.any? %>
           <div class="col-md-6">
             <h2 class="h3">
@@ -31,7 +31,7 @@
       <section class="mb-5">
         <h2 class="h3"><%= t('metadata') %></h2>
         <% if can? :publish, post %>
-          <div class="row row-small">
+          <div class="row pure__row--small">
             <div class="col-6">
               <%= f.input :published %>
             </div>
diff --git a/app/views/admin/communication/websites/posts/show.html.erb b/app/views/admin/communication/websites/posts/show.html.erb
index de65b65c6..de5f9051a 100644
--- a/app/views/admin/communication/websites/posts/show.html.erb
+++ b/app/views/admin/communication/websites/posts/show.html.erb
@@ -16,7 +16,7 @@
         <% end %>
       </div>
       <h2 class="h3"><%= t('metadata') %></h2>
-      <div class="row row-small">
+      <div class="row pure__row--small">
         <div class="col-6">
           <h3 class="h5"><%= Communication::Website::Post.human_attribute_name('published') %></h3>
           <p>
diff --git a/app/views/admin/dashboard/index.html.erb b/app/views/admin/dashboard/index.html.erb
index b53917cc0..c851cdfd7 100644
--- a/app/views/admin/dashboard/index.html.erb
+++ b/app/views/admin/dashboard/index.html.erb
@@ -3,87 +3,67 @@
 
 <div class="row mb-5">
   <div class="col-md-6 pb-4">
-    <h2 class="h4"><%= t('hello', name: current_user.first_name) %></h2>
-    <% if current_university.logo.attached? %>
-      <%= image_tag current_university.logo, width: 120, class: 'float-end' %>
-    <% else %>
-      <p><%= current_university %></p>
+    <%= panel title: t('hello', name: current_user.first_name) do %>
+      <div class="text-end">
+        <% if current_university.logo.attached? %>
+          <%= image_tag current_university.logo, width: 120 %>
+        <% else %>
+          <%= current_university %>
+        <% end %>
+      </div>
     <% end %>
   </div>
   <div class="col-md-6 pb-4">
-    <div class="d-flex align-items-start">
-      <div class="flex-grow-1">
-        <h2 class="h4 mb-2"><%= Delayed::Job.all.length %></h2>
-        <p class="mb-0"><%= t 'admin.pending_tasks.label' %></p>
-        <p class="mb-0 small"><%= t 'admin.pending_tasks.hint' %></p>
-      </div>
-      <div class="d-inline-block ms-3">
-        <div class="stat stat-sm">
-          <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-clock align-baseline"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>
-        </div>
-      </div>
-    </div>
+    <%= panel title: Delayed::Job.all.length, 
+              action: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-clock align-baseline"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>' do %>
+      <p class="mb-0"><%= t 'admin.pending_tasks.label' %></p>
+      <p class="mb-0 small"><%= t 'admin.pending_tasks.hint' %></p>
+    <% end %>
   </div>
 </div>
 
 <% if current_university.communication_websites.any? && can?(:read, Communication::Website) %>
-  <h2 class="section"><%= Communication::Website.model_name.human(count: 2) %></h2>
-  <div class="row row-small">
+  <h2 class="category"><%= Communication::Website.model_name.human(count: 2) %></h2>
+  <div class="row">
     <% current_university.communication_websites.each do |website| %>
       <% next unless can?(:read, website) %>
       <div class="<%= classes %>">
-        <div class="card flex-fill">
-          <div class="card-body">
-            <span class="float-end">
-              <i class="fas fa-<%= Icon::COMMUNICATION_WEBSITE %>"></i>
-            </span>
-            <h3 class="card-title"><%= website %></h3>
-            <p class="small"><%= website.url %></p>
-            <%= link_to t('show'), [:admin, website], class: button_classes('stretched-link') %>
-          </div>
-        </div>
+        <%= panel title: website, 
+                  action: "<i class=\"fas fa-#{ Icon::COMMUNICATION_WEBSITE }\"></i>" do %>
+          <p class="small"><%= website.url %></p>
+          <%= link_to t('show'), [:admin, website], class: button_classes('stretched-link') %>
+        <% end %>
       </div>
     <% end %>
   </div>
 <% end %>
 
 <% if current_university.communication_extranets.any? && can?(:read, Communication::Extranet) %>
-  <h2 class="section"><%= Communication::Extranet.model_name.human(count: 2) %></h2>
-  <div class="row row-small">
+  <h2 class="category"><%= Communication::Extranet.model_name.human(count: 2) %></h2>
+  <div class="row">
     <% current_university.communication_extranets.each do |extranet| %>
       <% next unless can?(:read, extranet) %>
       <div class="<%= classes %>">
-        <div class="card flex-fill">
-          <div class="card-body">
-            <span class="float-end">
-              <i class="fas fa-<%= Icon::COMMUNICATION_EXTRANET %>"></i>
-            </span>
-            <h3 class="card-title"><%= extranet %></h3>
-            <p class="small"><%= extranet.url %></p>
-            <%= link_to t('show'), [:admin, extranet], class: button_classes('stretched-link') %>
-          </div>
-        </div>
+        <%= panel title: extranet, 
+                  action: "<i class=\"fas fa-#{ Icon::COMMUNICATION_EXTRANET }\"></i>" do %>
+          <p class="small"><%= extranet.url %></p>
+          <%= link_to t('show'), [:admin, extranet], class: button_classes('stretched-link') %>
+        <% end %>
       </div>
     <% end %>
   </div>
 <% end %>
 
 <% if current_university.research_journals.any? && can?(:read, Research::Journal) %>
-  <h2 class="section"><%= Research::Journal.model_name.human(count: 2) %></h2>
-  <div class="row row-small">
+  <h2 class="category"><%= Research::Journal.model_name.human(count: 2) %></h2>
+  <div class="row pure__row--small">
     <% current_university.research_journals.each do |journal| %>
       <% next unless can?(:read, journal) %>
       <div class="<%= classes %>">
-        <div class="card flex-fill">
-          <div class="card-body">
-            <span class="float-end">
-              <i class="fas fa-<%= Icon::RESEARCH_JOURNAL %>"></i>
-            </span>
-            <h3 class="card-title"><%= journal %></h3>
-            <p>&nbsp;</p>
-            <%= link_to t('show'), [:admin, journal], class: button_classes('stretched-link') %>
-          </div>
-        </div>
+        <%= panel title: journal, 
+            action: "<i class=\"fas fa-#{ Icon::RESEARCH_JOURNAL }\"></i>" do %>
+          <%= link_to t('show'), [:admin, journal], class: button_classes('stretched-link') %>
+        <% end %>
       </div>
     <% end %>
   </div>
diff --git a/app/views/admin/layouts/themes/appstack/_panel.html.erb b/app/views/admin/layouts/themes/appstack/_panel.html.erb
new file mode 100644
index 000000000..7fd6e84c2
--- /dev/null
+++ b/app/views/admin/layouts/themes/appstack/_panel.html.erb
@@ -0,0 +1,13 @@
+<div class="card flex-fill">
+  <% if title %>
+    <div class="card-header">
+      <% if action %>
+        <div class="float-end"><%= raw action %></div>
+      <% end %>
+      <h2 class="card-title mb-0"><%= title  %></h2>
+    </div>
+  <% end %>
+  <div class="card-body">
+    <%= yield %>
+  </div>
+</div>
\ No newline at end of file
diff --git a/app/views/admin/layouts/themes/pure/_panel.html.erb b/app/views/admin/layouts/themes/pure/_panel.html.erb
new file mode 100644
index 000000000..1db841f05
--- /dev/null
+++ b/app/views/admin/layouts/themes/pure/_panel.html.erb
@@ -0,0 +1,9 @@
+<section class="flex-fill position-relative">
+  <% if action %>
+    <div class="float-end"><%= raw action %></div>
+  <% end %>
+  <% if title %>
+    <h2 class="h4"><%= title %></h2>
+  <% end %>
+  <%= yield %>
+</section>
\ No newline at end of file
-- 
GitLab