From 64da45e676dbc6349b600ee1ecf0a3edcd5700d5 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 3 Feb 2021 10:14:03 +0100 Subject: [PATCH] add feature: order categories --- css/admin.css | 18 +++++ lib/AppInfo/Application.php | 7 +- lib/Controller/NavController.php | 63 ++++++------------ lib/Service/CategoryRepository.php | 101 +++++++++++++++++++++++++++++ lib/Settings/Admin.php | 19 +++++- src/admin.js | 16 +++++ src/l10n/fixtures/de.yaml | 7 ++ src/l10n/fixtures/fr.yaml | 7 ++ templates/settings/admin-form.php | 60 ++++++++++++++++- 9 files changed, 250 insertions(+), 48 deletions(-) create mode 100644 lib/Service/CategoryRepository.php diff --git a/css/admin.css b/css/admin.css index a118556..61f7c1a 100644 --- a/css/admin.css +++ b/css/admin.css @@ -68,3 +68,21 @@ .side-menu-toggler { cursor: pointer; } + +.side-menu-setting#categories-list ul { + margin: 10px 4px 4px 0px; +} + +.side-menu-setting#categories-list li { + padding: 5px 10px; + border: 1px solid #ccc; + max-width: 300px; + margin: 2px 0; + border-radius: 4px; + cursor: pointer; +} + +.side-menu-setting.arrow { + color: #ccc; + padding-right: 5px; +} diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index aa89d0c..0558e9a 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -6,6 +6,7 @@ use OC; use OC\Security\CSP\ContentSecurityPolicyNonceManager; use OC\User\User; use OCA\SideMenu\Service\AppRepository; +use OCA\SideMenu\Service\CategoryRepository; use OCA\SideMenu\Service\ConfigProxy; use OCP\AppFramework\App; use OCP\IUserSession; @@ -84,8 +85,12 @@ class Application extends App return new AppRepository(); }); + $container->registerService('CategoryRepository', function (ContainerInterface $c) { + return new CategoryRepository(); + }); + $container->registerService('ConfigProxy', function (ContainerInterface $c) { - return new ConfigProxy($this->config); + return new ConfigProxy(); }); } diff --git a/lib/Controller/NavController.php b/lib/Controller/NavController.php index 6c3751e..2c80673 100644 --- a/lib/Controller/NavController.php +++ b/lib/Controller/NavController.php @@ -21,13 +21,11 @@ namespace OCA\SideMenu\Controller; use OC; use OC\App\AppStore\Fetcher\CategoryFetcher; use OC\URLGenerator; -use OCA\SideMenu\AppInfo\Application; use OCA\SideMenu\Service\AppRepository; +use OCA\SideMenu\Service\CategoryRepository; use OCA\SideMenu\Service\ConfigProxy; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\JSONResponse; -use OCP\IConfig; -use OCP\IL10N; use OCP\IRequest; use OCP\IUserSession; use OCP\L10N\IFactory; @@ -39,11 +37,6 @@ class NavController extends Controller */ protected $config; - /** - * @var IConfig - */ - protected $iConfig; - /** * @var AppRepository */ @@ -67,20 +60,17 @@ class NavController extends Controller public function __construct( string $appName, IRequest $request, - IConfig $iConfig, ConfigProxy $config, AppRepository $appRepository, - CategoryFetcher $categoryFetcher, + CategoryRepository $categoryRepository, URLGenerator $router, - IL10N $trans, IFactory $l10nFactory ) { parent::__construct($appName, $request); $this->config = $config; - $this->iConfig = $iConfig; $this->appRepository = $appRepository; - $this->categoryFetcher = $categoryFetcher; + $this->categoryRepository = $categoryRepository; $this->l10nFactory = $l10nFactory; $this->router = $router; } @@ -94,14 +84,7 @@ class NavController extends Controller */ public function items() { - $apps = $this->appRepository->getVisibleApps(); - $currentLanguage = substr($this->l10nFactory->findLanguage(), 0, 2); - $externalSitesInTopMenu = $this->config->getAppValueBool('external-sites-in-top-menu', '0'); - $hiddenApps = $this->config->getAppValueArray('big-menu-hidden-apps', '[]'); $user = OC::$server[IUserSession::class]->getUser(); - $isForced = $this->config->getAppValueBool('force', '0'); - $appsCategories = []; - $categoriesAppsCount = []; $items = []; if (!$user) { @@ -110,34 +93,19 @@ class NavController extends Controller ]); } - $categoriesLabels = $this->config->getAppValueArray('cache-categories', '[]'); - - if (empty($categoriesLabels)) { - $categoriesLabels = $this->categoryFetcher->get(); - - $this->iConfig->setAppValue(Application::APP_ID, 'cache-categories', json_encode($categoriesLabels)); - } - + $apps = $this->appRepository->getVisibleApps(); + $categoriesLabels = $this->categoryRepository->getOrderedCategories(); + $hiddenApps = $this->config->getAppValueArray('big-menu-hidden-apps', '[]'); + $isForced = $this->config->getAppValueBool('force', '0'); $topMenuApps = $this->config->getAppValueArray('top-menu-apps', '[]'); $userTopMenuApps = $this->config->getUserValueArray($user, 'top-menu-apps', '[]'); + $appsCategories = []; + $categoriesAppsCount = []; if (!$isForced && !empty($userTopMenuApps)) { $topMenuApps = $userTopMenuApps; } - foreach ($categoriesLabels as $k => $category) { - $categoriesLabels[$category['id']] = $category['translations'][$currentLanguage]['name'] ?? $category['translations']['en']['name']; - - unset($categoriesLabels[$k]); - } - - $categoriesLabels['external_links'] = $this->l10nFactory->get('external')->t('External sites'); - - $items['other'] = [ - 'name' => '', - 'apps' => [], - ]; - foreach ($apps as $app) { if (in_array($app['id'], $topMenuApps)) { continue; @@ -158,6 +126,7 @@ class NavController extends Controller if (!isset($items[$category])) { $items[$category] = [ 'name' => $categoriesLabels[$category] ?? $category, + 'categoryId' => $category, 'apps' => [], ]; } @@ -216,8 +185,16 @@ class NavController extends Controller } } - usort($items, function ($a, $b) { - return ($a['name'] < $b['name']) ? -1 : 1; + usort($items, function ($a, $b) use ($categoriesLabels) { + foreach ($categoriesLabels as $key => $value) { + if ($a['categoryId'] === $key) { + return -1; + } elseif ($b['categoryId'] === $key) { + return 1; + } + } + + return 0; }); return new JSONResponse([ diff --git a/lib/Service/CategoryRepository.php b/lib/Service/CategoryRepository.php new file mode 100644 index 0000000..b39628f --- /dev/null +++ b/lib/Service/CategoryRepository.php @@ -0,0 +1,101 @@ + + */ +class CategoryRepository +{ + /** + * @var CategoryFetcher + */ + protected $categoryFetcher; + + /** + * @var IFactory + */ + protected $l10nFactory; + + /** + * @var ConfigProxy + */ + protected $config; + + /** + * @var IConfig + */ + protected $iConfig; + + public function __construct( + CategoryFetcher $categoryFetcher, + ConfigProxy $config, + IConfig $iConfig, + IFactory $l10nFactory + ) + { + $this->categoryFetcher = $categoryFetcher; + $this->l10nFactory = $l10nFactory; + $this->config = $config; + $this->iConfig = $iConfig; + } + + /** + * Retrieves categories. + * + * @return array + */ + public function getOrderedCategories() + { + $currentLanguage = substr($this->l10nFactory->findLanguage(), 0, 2); + $type = $this->config->getAppValueArray('categories-order-type', 'default'); + $order = $this->config->getAppValueArray('categories-order', '[]'); + + $categoriesLabels = $this->config->getAppValueArray('cache-categories', '[]'); + + if (empty($categoriesLabels)) { + $categoriesLabels = $this->categoryFetcher->get(); + + $this->iConfig->setAppValue(Application::APP_ID, 'cache-categories', json_encode($categoriesLabels)); + } + + foreach ($categoriesLabels as $k => $category) { + $categoriesLabels[$category['id']] = $category['translations'][$currentLanguage]['name'] ?? $category['translations']['en']['name']; + + unset($categoriesLabels[$k]); + } + + $categoriesLabels['external_links'] = $this->l10nFactory->get('external')->t('External sites'); + $categoriesLabels['other'] = ''; + + asort($categoriesLabels); + + if ('custom' === $type || true) { + $ordered = []; + + foreach ($order as $id) { + if (isset($categoriesLabels[$id])) { + $ordered[$id] = $categoriesLabels[$id]; + } + } + + foreach ($categoriesLabels as $id => $value) { + if (!isset($ordered[$id])) { + $ordered[$id] = $value; + } + } + + $categoriesLabels = $ordered; + } + + return $categoriesLabels; + } +} diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php index 1707818..9b0a1ab 100644 --- a/lib/Settings/Admin.php +++ b/lib/Settings/Admin.php @@ -20,6 +20,7 @@ namespace OCA\SideMenu\Settings; use OCA\SideMenu\AppInfo\Application; use OCA\SideMenu\Service\AppRepository; +use OCA\SideMenu\Service\CategoryRepository; use OCA\SideMenu\Service\ConfigProxy; use OCP\AppFramework\Http\TemplateResponse; use OCP\IL10N; @@ -48,12 +49,23 @@ class Admin implements ISettings */ private $appRepository; - public function __construct(IL10N $l, ILogger $logger, ConfigProxy $config, AppRepository $appRepository) - { + /** + * @var CategoryRepository + */ + private $categoryRepository; + + public function __construct( + IL10N $l, + ILogger $logger, + ConfigProxy $config, + AppRepository $appRepository, + CategoryRepository $categoryRepository + ) { $this->l = $l; $this->logger = $logger; $this->config = $config; $this->appRepository = $appRepository; + $this->categoryRepository = $categoryRepository; } /** @@ -92,7 +104,10 @@ class Admin implements ISettings 'target-blank-apps' => $this->config->getAppValueArray('target-blank-apps', '[]'), 'top-menu-apps' => $this->config->getAppValueArray('top-menu-apps', '[]'), 'default-enabled' => $this->config->getAppValue('default-enabled', '1'), + 'categories-order-type' => $this->config->getAppValue('categories-order-type', 'default'), + 'categories-order' => $this->config->getAppValueArray('categories-order', '[]'), 'apps' => $this->appRepository->getVisibleApps(), + 'categories' => $this->categoryRepository->getOrderedCategories(), ]; return new TemplateResponse(Application::APP_ID, 'settings/admin-form', $parameters, ''); diff --git a/src/admin.js b/src/admin.js index 5728602..63504a8 100644 --- a/src/admin.js +++ b/src/admin.js @@ -129,4 +129,20 @@ jQuery(document).ready(() => { elementToggler(element) }) + + jQuery("#categories-list ul").sortable({ + forcePlaceholderSize: true, + placeholder: 'placeholder', + stop: function (event, ui) { + let value = [] + + jQuery('#categories-list li').each(function() { + value.push(jQuery(this).attr('data-id')) + }); + + value = JSON.stringify(value) + + jQuery('input[name="categories-order"]').val(value) + } + }); }); diff --git a/src/l10n/fixtures/de.yaml b/src/l10n/fixtures/de.yaml index 7ce4fe6..6fca236 100644 --- a/src/l10n/fixtures/de.yaml +++ b/src/l10n/fixtures/de.yaml @@ -67,3 +67,10 @@ "Apps that should not be displayed in the menu": "Apps, die nicht im Menü angezeigt werden sollen" "This feature is only compatible with the big menu display.": "Kompatibel mit der Anzeige Großes Menü ." "The logo is a link to the default app": "Das Logo ist ein Link zur Standard-App" +"Others": "Andere" +"Categories": "Kategorien" +"Customize sorting": "Sortierung anpassen" +"Order by": "Sortieren nach" +"Name": "Name" +"Customed": "Kundenspezifisch" +"Show and hide the list of categories": "Liste der Kategorien ein- und ausblenden" diff --git a/src/l10n/fixtures/fr.yaml b/src/l10n/fixtures/fr.yaml index 8a21e06..0c5c20a 100644 --- a/src/l10n/fixtures/fr.yaml +++ b/src/l10n/fixtures/fr.yaml @@ -67,3 +67,10 @@ "Apps that should not be displayed in the menu": "Applications qui ne doivent pas être affichées dans le menu" "This feature is only compatible with the big menu display.": "Compatible avec l'affichage Menu large." "The logo is a link to the default app": "Le logo est un lien vers l'application par défaut" +"Others": "Autres" +"Categories": "Catégories" +"Customize sorting": "Personnaliser le tri" +"Order by": "Trier par" +"Name": "Nom" +"Customed": "Personnalisé" +"Show and hide the list of categories": "Afficher et masquer la liste des catégories" diff --git a/templates/settings/admin-form.php b/templates/settings/admin-form.php index 7b858be..ecf4ca3 100644 --- a/templates/settings/admin-form.php +++ b/templates/settings/admin-form.php @@ -529,6 +529,61 @@ $choicesSizes = [ + +
+

+ t('Categories')); ?> +

+
+ + + 'default', + 'Customed' => 'custom', + ]; + ?> + + +
+ +
+ +
+ +

+ + 🖱️ t('Show and hide the list of categories')); ?> + +

+ + + + ' name="categories-order" class="side-menu-setting"> +
+

t('Tips')); ?> @@ -574,14 +629,15 @@ $choicesSizes = [ +

+ +
-
-