From e4e24690a0237ee6718097a24957634457ee0f55 Mon Sep 17 00:00:00 2001 From: Joshua Pease Date: Wed, 13 Dec 2023 12:00:42 -0800 Subject: [PATCH] [#72] Implement new parts kit template code --- src/Module.php | 10 -- src/controllers/PartsKitController.php | 16 --- src/models/NavNode.php | 2 +- src/services/PartsKit.php | 146 ++++----------------- src/templates/_layouts/parts-kit-root.html | 16 +++ src/templates/_layouts/parts-kit.html | 114 +--------------- tests/unit/PartsKitTest.php | 54 -------- 7 files changed, 46 insertions(+), 312 deletions(-) create mode 100644 src/templates/_layouts/parts-kit-root.html diff --git a/src/Module.php b/src/Module.php index 9037916..d1c0a55 100644 --- a/src/Module.php +++ b/src/Module.php @@ -168,16 +168,6 @@ function (RegisterTemplateRootsEvent $e) { } } ); - - Event::on( - UrlManager::class, - UrlManager::EVENT_REGISTER_SITE_URL_RULES, - function (RegisterUrlRulesEvent $event) { - $partsKitDir = self::$config['partsKit']['directory']; - - $event->rules[$partsKitDir] = 'parts-kit/redirect-index'; - } - ); } } diff --git a/src/controllers/PartsKitController.php b/src/controllers/PartsKitController.php index 7e21f2c..677df9c 100644 --- a/src/controllers/PartsKitController.php +++ b/src/controllers/PartsKitController.php @@ -10,22 +10,6 @@ class PartsKitController extends \craft\web\Controller { protected array|int|bool $allowAnonymous = true; - /** - * Redirect to the first component in the parts kit - * - * @return Response - */ - public function actionRedirectIndex(): Response - { - $redirectUrl = Module::getInstance()->partsKit->getFirstNavUrl(); - - if (!$redirectUrl) { - throw new \Exception('Looks like you don’t have any parts kit components setup yet.'); - } - - return $this->redirect($redirectUrl, 301); - } - public function actionConfig(): Response { return $this->asJson([ diff --git a/src/models/NavNode.php b/src/models/NavNode.php index c97d861..f72dd99 100644 --- a/src/models/NavNode.php +++ b/src/models/NavNode.php @@ -6,8 +6,8 @@ class NavNode implements \JsonSerializable { public function __construct( public string $title, - public string $url, public string $path, + public ?string $url = null, public array $children = [], ) {} diff --git a/src/services/PartsKit.php b/src/services/PartsKit.php index 6c21d78..6740b38 100644 --- a/src/services/PartsKit.php +++ b/src/services/PartsKit.php @@ -6,7 +6,6 @@ use craft\helpers\StringHelper; use craft\helpers\FileHelper; use craft\helpers\Template as TemplateHelper; -use craft\helpers\ArrayHelper; use craft\elements\Asset; use Twig\Markup; use viget\base\models\NavNode; @@ -27,6 +26,16 @@ public static function isRequest(): bool return (Craft::$app->request->segments[0] ?? null) === self::getConfig('directory'); } + /** + * Determine if this is a request to the root of the parts kit + * @return bool + */ + public static function isRootRequest(): bool + { + $isRoot = count(Craft::$app->request->getSegments()) === 1; + return $isRoot && self::isRequest(); + } + /** * Get a config item either the default or from the config file * @@ -46,7 +55,8 @@ public static function getConfig(string $key) public static function getNav(): array { $templatesPath = Craft::$app->getPath()->getSiteTemplatesPath(); - $partsPath = $templatesPath . '/' . 'parts-kit' . '/'; + $partsKitFolderName = self::getConfig('directory'); + $partsPath = $templatesPath . '/' . $partsKitFolderName . '/'; // Combine and sort all files & directories in the parts kit $directories = \yii\helpers\FileHelper::findDirectories($partsPath); @@ -67,13 +77,15 @@ public static function getNav(): array foreach ($templates as $templatePath) { $path = str_replace($partsPath, '', $templatePath); $pathParts = explode('/', $path); - // TODO format name - $title = end($pathParts); + $title = self::_formatTitle(end($pathParts)); + $url = is_file($templatePath) + ? '/' . $partsKitFolderName . '/' . self::_removeExtension($path) + : null; $result[$path] = new NavNode( title: $title, - url: $path, // TODO only use URL if there's a file path: $path, + url: $url, ); } @@ -100,128 +112,13 @@ public static function getNav(): array return array_values($result); } - /** - * Get the first component's URL - * - * @return string|null - */ - public static function getFirstNavUrl(): ?string - { - $nav = self::getNav(); - $firstUrl = ArrayHelper::firstValue($nav)['items'][0]['url'] ?? null; - - if (!$firstUrl) return null; - - return parse_url($firstUrl)['path']; - } - - /** - * Get the CSS variables that power the theme - * - * @return string - */ - public static function getTheme(): string - { - $themes = [ - 'light' => [ - 'background' => '#ededed', - 'main-background' => '#fff', - 'text' => '#202020', - 'nav-icon' => '#148bbe', - 'nav-item-text-hover' => '#202020', - 'nav-item-background-hover' => '#dbdbdb', - 'nav-subitem-text-hover' => '#202020', - 'nav-subitem-background-hover' => '#dbdbdb', - 'nav-subitem-background-active' => '#148bbe', - 'nav-subitem-text-active' => '#fff', - 'controls-text' => '#a7a9ac', - 'controls-border' => '#dbdbdb', - ], - - 'dark' => [ - 'background' => '#2f2f2f', - 'main-background' => '#333', - 'text' => 'rgba(255, 255, 255, 0.8)', - 'nav-icon' => '#1ea7fd', - 'nav-item-text-hover' => '#fff', - 'nav-item-background-hover' => 'rgba(250, 250, 252, 0.1)', - 'nav-subitem-text-hover' => '#fff', - 'nav-subitem-background-hover' => 'rgba(250, 250, 252, 0.1)', - 'nav-subitem-background-active' => '#1ea7fd', - 'nav-subitem-text-active' => '#fff', - 'controls-text' => '#999', - 'controls-border' => 'rgba(255, 255, 255, 0.1)', - ], - ]; - - $theme = self::getConfig('theme'); - - // If a theme name is passed instead of - // custom config, select that theme - if (!is_array($theme)) { - $theme = $themes[$theme] ?? $themes['light']; - } - - $css = []; - foreach ($theme as $property => $value) { - $css[] = "--pk-{$property}: {$value};"; - } - return implode('', $css); - } - - /** - * Get templates in parts kit folder - * - * @param string $partsKitDir - * @return array - */ - private static function _getTemplates(string $partsKitDir): array - { - $templates = []; - - $templatesPath = Craft::$app->getPath()->getSiteTemplatesPath(); - $partsPath = $templatesPath . '/' . $partsKitDir . '/'; - - if (!is_dir($partsPath)) return []; - - $files = FileHelper::findFiles($partsPath); - - foreach ($files as $file) { - $file = str_replace($partsPath, '', $file); - $count = substr_count($file, '/'); - - // This doesn't fit the dir/file structure, so ignore - if ($count !== 1) continue; - - $fileParts = explode('/', $file); - $dir = $fileParts[0]; - $fileName = $fileParts[1]; - - // Don't include templates that are "hidden" - if ($fileName[0] === '_' || $fileName[0] === '.') continue; - - // Key already exists, add to array - if (array_key_exists($dir, $templates)) { - $templates[$dir][] = self::_cleanFilename($fileName); - } else { - $templates[$dir] = [ - self::_cleanFilename($fileName), - ]; - } - } - - ksort($templates, SORT_NATURAL); - - return $templates; - } - /** * Remove extension from file name * * @param string $file * @return string */ - private static function _cleanFileName(string $file): string + private static function _removeExtension(string $file): string { $extensions = array_map(function($extension) { return '.' . $extension; @@ -236,9 +133,12 @@ private static function _cleanFileName(string $file): string * @param string $str * @return string */ - private static function _formatName(string $str): string + private static function _formatTitle(string $str): string { - return str_replace('-', ' ', StringHelper::humanize($str)); + $str = self::_removeExtension($str); + $str = StringHelper::toKebabCase($str); + $str = StringHelper::humanize($str); + return str_replace('-', ' ', $str); } /** diff --git a/src/templates/_layouts/parts-kit-root.html b/src/templates/_layouts/parts-kit-root.html new file mode 100644 index 0000000..fd3830e --- /dev/null +++ b/src/templates/_layouts/parts-kit-root.html @@ -0,0 +1,16 @@ + + + + + + Parts Kit + + + + + + + diff --git a/src/templates/_layouts/parts-kit.html b/src/templates/_layouts/parts-kit.html index 0a4f56b..d356bbf 100644 --- a/src/templates/_layouts/parts-kit.html +++ b/src/templates/_layouts/parts-kit.html @@ -1,111 +1,9 @@ -{% extends craft.viget.partsKit.getConfig('layout') %} +{% extends craft.viget.partsKit.isRootRequest() + ? 'viget-base/_layouts/parts-kit-root' + : craft.viget.partsKit.getConfig('layout') +%} {% block content %} - - -
- - -
-
-
- - -
- -
- {% block main %}{% endblock %} -
-
-
-
+ {% block main %} + {% endblock %} {% endblock %} diff --git a/tests/unit/PartsKitTest.php b/tests/unit/PartsKitTest.php index 8450061..aa2c082 100644 --- a/tests/unit/PartsKitTest.php +++ b/tests/unit/PartsKitTest.php @@ -26,64 +26,10 @@ public function _fixtures(): array ]; } - public function testNav() - { - Craft::$app->request->setUrl('/parts-kit/button/default'); - - $nav = Module::getInstance()->partsKit->getNav(); - - $this->assertEquals([ - 'Button' => [ - 'items' => [ - [ - 'title' => 'Blue', - 'url' => 'https://test.craftcms.test/parts-kit/button/blue', - 'isActive' => false, - ], - [ - 'title' => 'Default', - 'url' => 'https://test.craftcms.test/parts-kit/button/default', - 'isActive' => true, - ], - ], - 'isActive' => true, - ], - 'Cta block' => [ - 'items' => [ - [ - 'title' => 'Dark theme', - 'url' => 'https://test.craftcms.test/parts-kit/cta-block/dark-theme', - 'isActive' => false, - ], - [ - 'title' => 'Default', - 'url' => 'https://test.craftcms.test/parts-kit/cta-block/default', - 'isActive' => false, - ], - ], - 'isActive' => false, - ] - ], $nav); - } - - public function testThemeCss() - { - $themeCss = Module::getInstance()->partsKit->getTheme(); - - $this->assertEquals('--pk-background: #2c3e50;--pk-main-background: #34495e;--pk-text: white;--pk-nav-icon: #2ecc71;--pk-nav-item-text-hover: white;--pk-nav-item-background-hover: rgba(255, 255, 255, 0.1);--pk-nav-subitem-text-hover: white;--pk-nav-subitem-background-hover: rgba(255, 255, 255, 0.1);--pk-nav-subitem-background-active: #2ecc71;--pk-nav-subitem-text-active: #fff;--pk-controls-text: rgba(255, 255, 255, 0.3);--pk-controls-border: rgba(255, 255, 255, 0.1);', $themeCss); - } - public function testGetImage() { $image = Module::getInstance()->partsKit->getImage('sample.png'); $this->assertInstanceOf('craft\elements\Asset', $image); } - - public function testGetFirstNavUrl() - { - Craft::$app->request->setUrl('/parts-kit'); - - $this->assertEquals('/parts-kit/button/blue', Module::getInstance()->partsKit->getFirstNavUrl()); - } }