From c51bcceafc08a4ae1a2af95e9efa5d465ed24fa7 Mon Sep 17 00:00:00 2001 From: Stephen Cameron Date: Sat, 5 Feb 2022 00:49:49 +0100 Subject: [PATCH] WIP #4893 @30 --- .../Controllers/Admin/PageCrudController.php | 9 ++ app/Models/Application.php | 6 ++ app/Models/News.php | 13 ++- app/SubForms/ImageBlock.php | 34 +++++++ app/Templates/Category.php | 6 ++ app/Templates/CategoryListing.php | 64 +++++++++++++ app/Templates/Home.php | 30 ++++-- app/Templates/News.php | 12 +-- app/Templates/Placeholder.php | 25 +++++ app/Templates/Solution.php | 41 +++++++-- app/Templates/SolutionPlaceholder.php | 35 +++++++ resources/styles/components/navigation.styl | 91 +++++++------------ resources/styles/components/solutions.styl | 2 +- .../components/application-item.blade.php | 22 +++++ .../views/components/link-button.blade.php | 4 +- .../views/components/news-item.blade.php | 2 +- .../views/pages/category_listing.blade.php | 65 +++++++++++++ resources/views/pages/home.blade.php | 44 ++++++++- resources/views/pages/news.blade.php | 6 +- resources/views/pages/solution.blade.php | 3 +- .../views/partials/product-link.blade.php | 10 +- 21 files changed, 424 insertions(+), 100 deletions(-) create mode 100644 app/SubForms/ImageBlock.php create mode 100644 app/Templates/CategoryListing.php create mode 100644 app/Templates/Placeholder.php create mode 100644 app/Templates/SolutionPlaceholder.php create mode 100644 resources/views/components/application-item.blade.php create mode 100644 resources/views/pages/category_listing.blade.php diff --git a/app/Http/Controllers/Admin/PageCrudController.php b/app/Http/Controllers/Admin/PageCrudController.php index 12ca640..23a2dc6 100644 --- a/app/Http/Controllers/Admin/PageCrudController.php +++ b/app/Http/Controllers/Admin/PageCrudController.php @@ -13,4 +13,13 @@ class PageCrudController extends CubistMagicNestedController protected $_clonable = true; protected $_bulk = true; protected $_oneInstance= false; + + public function setup() { + parent::setup(); + + // Override max menu depth when re-ordering. There's a parent level (eg. #main or #footer) + // so an extra level is needed to allow 4 menu levels on front-end. A depth setting of 0 = infinite. + // Ref: https://backpackforlaravel.com/docs/3.6/crud-operation-reorder + $this->crud->enableReorder('name', 5); + } } diff --git a/app/Models/Application.php b/app/Models/Application.php index f3fb011..b84c7c7 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -67,4 +67,10 @@ class Application extends CubistMagicPageModel parent::setFields(); } + + // Custom accessor: ->title_solutions_variant + // Provides more context (mainly used for Applications 'SelectFromModel' field in Solutions template) + public function getTitleSolutionsVariantAttribute() { + return $this->title_solutions . ' ['. implode(', ', $this->variant) .']'; + } } diff --git a/app/Models/News.php b/app/Models/News.php index 534eebf..c9a563b 100644 --- a/app/Models/News.php +++ b/app/Models/News.php @@ -11,6 +11,9 @@ use Cubist\Backpack\app\Magic\Models\News as BaseNews; class News extends BaseNews { + public $thumb_width = 348; + public $thumb_height = 196; + public function registerMediaConversions(Media $media = null) { parent::registerMediaConversions($media); @@ -19,7 +22,7 @@ class News extends BaseNews ->width(768); $this->addMediaConversion('index_thumb') - ->crop(Manipulations::CROP_CENTER, 348, 196); + ->crop(Manipulations::CROP_CENTER, $this->thumb_width, $this->thumb_height); } public static function getPosts($per_page = 8, $exclude = null) { @@ -61,7 +64,13 @@ class News extends BaseNews return $fallback; } - return ''. $alt .''; + // Include thumbnail dimensions to avoid grid jumping as post images are loaded + // Ideally this should be based on actual dimensions of each image but for now it'll do + // See: https://github.com/spatie/laravel-medialibrary/issues/893 + $dimensions = ($size == 'index_thumb') ? + 'width="'. $this->thumb_width .'" height="'. $this->thumb_height .'"' : ''; + + return ''. $alt .''; } public function getURL($id) { diff --git a/app/SubForms/ImageBlock.php b/app/SubForms/ImageBlock.php new file mode 100644 index 0000000..497774b --- /dev/null +++ b/app/SubForms/ImageBlock.php @@ -0,0 +1,34 @@ +addField(['name' => 'title', + 'label' => 'Titre', + 'type' => 'Text']); + + $this->addField(['name' => 'text', + 'label' => 'Texte', + 'type' => 'Textarea', + 'attributes' => [ + 'rows' => 4, + ], + ]); + + $this->addField(['name' => 'image', + 'label' => 'Image', + 'type' => 'Images']); + + $this->addField(['name' => 'button', + 'label' => 'Lien', + 'type' => 'Button']); + } +} diff --git a/app/Templates/Category.php b/app/Templates/Category.php index 1c18ad4..1e28c42 100644 --- a/app/Templates/Category.php +++ b/app/Templates/Category.php @@ -39,6 +39,12 @@ class Category extends Base 'type' => 'Text', 'label' => 'Filtres', 'tab' => 'Catégorie']); + + $this->addField(['name' => 'highlights', + 'type' => 'Markdown', + 'label' => 'Liste de 3 highlights affichés sur le template « Listing Catégories »', + 'tab' => 'Highlights']); + } public function setData(&$data) diff --git a/app/Templates/CategoryListing.php b/app/Templates/CategoryListing.php new file mode 100644 index 0000000..b349515 --- /dev/null +++ b/app/Templates/CategoryListing.php @@ -0,0 +1,64 @@ +addField([ + 'name' => 'intro', + 'type' => 'BunchOfFields', + 'bunch' => 'App\SubForms\Intro', + 'label' => 'Introduction', + 'tab' => 'Introduction', + 'translatable' => true, + ]); + + $this->addField(['name' => 'related_applications', + 'label' => 'Applications associées', + 'type' => 'SelectFromModel', + 'optionsmodel' => Application::class, + 'multiple' => true, + 'attribute' => 'title', + 'tab' => 'Applications Associées', + ]); + } + + public function setData(&$data) + { + parent::setData($data); + + // Get all the child pages of this page that use the template 'category'. + // These will be used to populate the grid of sub-categories + $current_page_ID = $data['page']->id; + $categories = Page::with('media') + ->where('parent_id', $current_page_ID) + ->where('template', 'category') + ->orderBy('lft') + ->get(); + + $data['categories'] = []; + + foreach ($categories as $category) { + $data['categories'][$category->id] = $category->getPageData(); + } + + // Get related applications, if any + if (isset($data['page']->related_applications) && count($data['page']->related_applications) > 0) { + $data['applications'] = PageData::fromEntities(Application::whereVariant()->whereIn('id', $data['page']->related_applications)->get()); + } + } +} diff --git a/app/Templates/Home.php b/app/Templates/Home.php index f9f61c4..fb2ae07 100644 --- a/app/Templates/Home.php +++ b/app/Templates/Home.php @@ -2,7 +2,9 @@ namespace App\Templates; +use App\Models\Application; use App\Models\News; +use Cubist\Backpack\app\Magic\PageData; class Home extends Base { @@ -21,6 +23,22 @@ class Home extends Base { parent::init(); + $this->removeField('intro'); // Replaced by custom intro fields below + + $this->addField(['name' => 'our_business_title', + 'label' => 'Titre', + 'type' => 'Text', + 'tab' => 'Intro']); + + $this->addField([ + 'name' => 'our_business_details', + 'type' => 'BunchOfFieldsMultiple', + 'bunch' => 'App\SubForms\ImageBlock', + 'label' => 'Notre métier', + 'tab' => 'Intro', + ]); + + $this->addField([ 'name' => 'slideshow', 'type' => 'BunchOfFieldsMultiple', @@ -66,15 +84,11 @@ class Home extends Base // Set extra data for Home blade view public function setData(&$data) { - $page = $data['page']; + // Latest News posts + $data['news'] = News::getPosts(4); - // News data - $data['news'] = $this->_getNews(); - } - - protected function _getNews() - { - return News::getPosts(4); + // Latest Applications + $data['applications'] = PageData::fromEntities(Application::with('media')->whereVariant()->latest()->take(4)->get()); } diff --git a/app/Templates/News.php b/app/Templates/News.php index 8120919..5ce5bfd 100644 --- a/app/Templates/News.php +++ b/app/Templates/News.php @@ -25,16 +25,14 @@ class News extends Base Debugbar::startMeasure('nav_news', 'Make news nav items'); parent::setMenuChildren($menu); - $news = NewsModel::whereVariant()->get(); + $locale = app()->getLocale(); - $i = 0; + $news = NewsModel::whereVariant() + ->where("status->$locale", 1) + ->whereDate('date', '<=', Carbon::now()) + ->get(); foreach ($news as $newsItem) { - // Don't include offline items - if ($newsItem->getPageData()->get('status') != 1) { - continue; - } - $item = new PageItem(); $item->initFromEntity($newsItem); $item->setLocale($menu->getLocale()); diff --git a/app/Templates/Placeholder.php b/app/Templates/Placeholder.php new file mode 100644 index 0000000..a271b80 --- /dev/null +++ b/app/Templates/Placeholder.php @@ -0,0 +1,25 @@ + 'Applications', 'type' => 'SelectFromModel', 'optionsmodel' => 'App\Models\Application', - 'attribute' => 'title_solutions', + 'attribute' => 'title_solutions_variant', // Custom accessor provides more detail 'order' => true, 'multiple' => true, 'tab' => 'Applications']); @@ -34,17 +36,16 @@ class Solution extends Base Debugbar::startMeasure('nav_applications', 'Make applications nav items'); parent::setMenuChildren($menu); - $applications = Application::whereVariant($menu->getVariant())->get(); - $solution_apps = $menu->getPageData()->get('applications'); - if (null === $solution_apps || !$solution_apps) { + + if (null === $solution_apps || !is_array($solution_apps)) { return; } + $applications = self::_getApplications($menu->getVariant(), $menu->getLocale()); + foreach ($applications as $application) { - if (!in_array($application->id, $solution_apps)) { - continue; - } + $item = new PageItem(); $item->initFromEntity($application); $item->setVariant($menu->getVariant()); @@ -53,7 +54,13 @@ class Solution extends Base $item->setHref($application->getSlugOrTitleAttribute()); $item->setId('application/' . $application->id); $item->setController(['controller' => 'ApplicationController', 'action' => 'view', 'params' => ['id' => $application->id]]); - $item->showInAllMenus(); + + if (!in_array($application->id, $solution_apps)) { + $item->hideInAllMenus(); + } else { + $item->showInAllMenus(); + } + $menu->addChild($item); } @@ -66,6 +73,22 @@ class Solution extends Base $data['applications'] = []; return; } - $data['applications'] = PageData::fromEntities(Application::whereIn('id', $data['page']->applications)->get()); + $data['applications'] = PageData::fromEntities(Application::whereVariant()->whereIn('id', $data['page']->applications)->get()); + } + + /** + * @param $variant + * @param $locale + * @return Application[] + */ + public static function _getApplications($variant, $locale) + { + if (!isset(self::$_applications[$variant][$locale])) { + self::$_applications[$variant][$locale] = []; + } + if (empty(self::$_applications[$variant][$locale])) { + self::$_applications[$variant][$locale] = Application::whereVariant($variant)->get(); + } + return self::$_applications[$variant][$locale]; } } diff --git a/app/Templates/SolutionPlaceholder.php b/app/Templates/SolutionPlaceholder.php new file mode 100644 index 0000000..7d70a96 --- /dev/null +++ b/app/Templates/SolutionPlaceholder.php @@ -0,0 +1,35 @@ +removeField('intro'); + } + + public function setMenuChildren($menu) + { + Debugbar::startMeasure('nav_applications_placeholder', 'Make applications nav items (placeholder template)'); + parent::setMenuChildren($menu); + Debugbar::stopMeasure('nav_applications_placeholder'); + } +} diff --git a/resources/styles/components/navigation.styl b/resources/styles/components/navigation.styl index e4bcb4b..74b44f1 100644 --- a/resources/styles/components/navigation.styl +++ b/resources/styles/components/navigation.styl @@ -8,8 +8,11 @@ .nav-primary @apply flex mx-auto px-8 - // Top level items + // Trigger for submenus, at any depth + li:hover > ul + display: block // Or set to flex so we can have 2 menus side-by-side in submenu + // Top level items > li @apply py-4 //position: relative @@ -24,54 +27,36 @@ &:not(:last-child) @apply mr-10 - &:hover - > ul // First level submenus - display: block // Set to flex so we can have 2 menus side-by-side in submenu - animation: submenu-fade-in 0.3s - - // Top level links - - > li > a - @apply text-inherit cursor-pointer - white-space nowrap + // Top level links + > a + @apply text-inherit cursor-pointer + white-space nowrap - &:hover - @apply text-primary + &:hover + @apply text-primary + // 1st level Submenus + > li > ul + margin-top: 1rem // Extra margin to replace top: 100% (see IE11 notes above) + animation: submenu-fade-in 0.3s - // Submenus + // Any Submenus below the first level + > li > ul li > ul + top: -1rem // To offset extra padding on
  • s (sub-submenus are relative to parent
  • ) + left: 100% + // ALL Submenus > li ul @apply bg-white text-base shadow-2xl - //top: 100% - //left: 0 - position: absolute + position: absolute // Any deeper submenus will be relative to the parent