diff --git a/core/classes/Misc/Announcements.php b/core/classes/Misc/Announcements.php index 6e85560984..875fd250d2 100644 --- a/core/classes/Misc/Announcements.php +++ b/core/classes/Misc/Announcements.php @@ -5,7 +5,7 @@ * * @package NamelessMC\Misc * @author Aberdeener - * @version 2.1.0 + * @version 2.3.0 * @license MIT */ class Announcements diff --git a/core/classes/Templates/AssetTree.php b/core/classes/Templates/AssetTree.php index ed82ef3b91..ed375d18b6 100644 --- a/core/classes/Templates/AssetTree.php +++ b/core/classes/Templates/AssetTree.php @@ -84,6 +84,7 @@ class AssetTree * @var string Fomantic-UI bundle v2.8 (CSS + JS) */ public const FOMANTIC_UI = 'FOMANTIC_UI'; + public const ICON_PICKER = 'ICON_PICKER'; /** * @var mixed Tree of all available assets, with their applicable CSS/JS files. @@ -254,5 +255,13 @@ class AssetTree self::JQUERY, ], ], + self::ICON_PICKER => [ + 'js' => [ + 'vendor/@migliori/universal-icon-picker/assets/js/universal-icon-picker.min.js', + ], + 'css' => [ + 'vendor/fomantic-ui/dist/components/icon.min.css', + ] + ], ]; } diff --git a/core/includes/updates/220.php b/core/includes/updates/220.php new file mode 100644 index 0000000000..87e8777445 --- /dev/null +++ b/core/includes/updates/220.php @@ -0,0 +1,49 @@ +runMigrations(); + + $cache = new Cache(['name' => 'nameless', 'extension' => '.cache', 'path' => ROOT_PATH . '/cache/']); + + // Update icon definitions to just be class names instead of full HTML + $announcements = DB::getInstance()->get('announcements', ['icon', '<>', ''])->results(); + foreach ($announcements as $announcement) { + DB::getInstance()->update('announcements', $announcement->id, [ + 'icon' => $this->extractIconClasses($announcement->icon) + ]); + } + (new Announcements($cache))->resetCache(); + + $custom_pages = DB::getInstance()->get('custom_pages', ['icon', '<>', ''])->results(); + foreach ($custom_pages as $custom_page) { + DB::getInstance()->update('custom_pages', $custom_page->id, [ + 'icon' => $this->extractIconClasses($custom_page->icon) + ]); + } + + $forums = DB::getInstance()->get('forums', ['icon', '<>', ''])->results(); + foreach ($forums as $forum) { + DB::getInstance()->update('forums', $forum->id, [ + 'icon' => $this->extractIconClasses($forum->icon) + ]); + } + + $cache->setCache('navbar_icons'); + $icons = $cache->retrieveAll(); + foreach ($icons as $key => $icon) { + $cache->store($key, $this->extractIconClasses($icon)); + } + + $this->setVersion('2.3.0'); + } + + /** + * Transform "" to "fas fa-home" + */ + private function extractIconClasses(string $icon_html): string { + return preg_replace('/<\/i>/', '$1', $icon_html); + } + +}; diff --git a/custom/panel_templates/Default/core/announcements_form.tpl b/custom/panel_templates/Default/core/announcements_form.tpl index 203609be84..4a62b54ae5 100644 --- a/custom/panel_templates/Default/core/announcements_form.tpl +++ b/custom/panel_templates/Default/core/announcements_form.tpl @@ -90,11 +90,24 @@
- - + +
+
+ + + +
+ +
@@ -247,9 +260,20 @@ }).children().click(function (e) { e.stopPropagation(); }); + + new UniversalIconPicker('#nav-icon-picker', { + allowEmpty: false, + iconLibraries: [ + 'fomantic-ui.min.json', + 'font-awesome.min.json', + ], + onSelect: (icon) => { + document.getElementById('icon').value = icon.iconClass; + } + }); }); - \ No newline at end of file + diff --git a/custom/panel_templates/Default/core/navigation.tpl b/custom/panel_templates/Default/core/navigation.tpl index 81792b6d9a..4b8a343c4c 100644 --- a/custom/panel_templates/Default/core/navigation.tpl +++ b/custom/panel_templates/Default/core/navigation.tpl @@ -42,58 +42,68 @@
-
{$INFO}
+
{$INFO}

{$NAVBAR_ORDER_INSTRUCTIONS}

{$NAVBAR_ICON_INSTRUCTIONS}


{foreach from=$NAV_ITEMS key=key item=item} - {$item.title|escape} -
-
-
- - -
-
- - + {$item.title|escape} +
+
+
+ + +
+
+ +
+
+ + + +
+ +
+
-
- {if isset($item.items) && count($item.items)} -
- {$item.title|escape} » {$DROPDOWN_ITEMS} -
- {foreach from=$item.items key=dropdown_key item=dropdown_item} - {$dropdown_item.title|escape} -
-
-
- - -
-
- - -
-
-
- {/foreach} - {/if} + {if isset($item.items) && count($item.items)} +
+ {$item.title|escape} » {$DROPDOWN_ITEMS} +
+ {foreach from=$item.items key=dropdown_key item=dropdown_item} + {$dropdown_item.title|escape} +
+
+
+ + +
+
+ + +
+
+
+ {/foreach} + {/if} {/foreach}
@@ -130,6 +140,24 @@ {include file='scripts.tpl'} + + - \ No newline at end of file + diff --git a/custom/panel_templates/Default/forum/forums_edit.tpl b/custom/panel_templates/Default/forum/forums_edit.tpl index d16e5eda4f..d01af9e681 100644 --- a/custom/panel_templates/Default/forum/forums_edit.tpl +++ b/custom/panel_templates/Default/forum/forums_edit.tpl @@ -78,9 +78,24 @@
- - + +
+
+ + + +
+ +
@@ -387,9 +402,20 @@ $("#InputHooks").select2({ placeholder: "{$NO_ITEM_SELECTED}" }); $("#InputDefaultLabels").select2({ placeholder: "{$NO_ITEM_SELECTED}" }); + + new UniversalIconPicker('#nav-icon-picker', { + allowEmpty: false, + iconLibraries: [ + 'fomantic-ui.min.json', + 'font-awesome.min.json', + ], + onSelect: (icon) => { + document.getElementById('InputIcon').value = icon.iconClass; + } + }); }); - \ No newline at end of file + diff --git a/custom/panel_templates/Default/forum/forums_new_step_1.tpl b/custom/panel_templates/Default/forum/forums_new_step_1.tpl index 13ffbbbcbf..82c445e32b 100644 --- a/custom/panel_templates/Default/forum/forums_new_step_1.tpl +++ b/custom/panel_templates/Default/forum/forums_new_step_1.tpl @@ -71,10 +71,24 @@ class="form-control" rows="3">{$FORUM_DESCRIPTION_VALUE}
- - + +
+
+ + + +
+ +
@@ -128,8 +142,21 @@ function showCancelModal() { $('#cancelModal').modal().show(); } + + $(document).ready(function () { + new UniversalIconPicker('#nav-icon-picker', { + allowEmpty: false, + iconLibraries: [ + 'fomantic-ui.min.json', + 'font-awesome.min.json', + ], + onSelect: (icon) => { + document.getElementById('forum_icon').value = icon.iconClass; + } + }); + }); - \ No newline at end of file + diff --git a/custom/panel_templates/Default/includes/alerts.tpl b/custom/panel_templates/Default/includes/alerts.tpl index 0489aec01c..cf6f4c155d 100644 --- a/custom/panel_templates/Default/includes/alerts.tpl +++ b/custom/panel_templates/Default/includes/alerts.tpl @@ -3,7 +3,7 @@ -
{$SUCCESS_TITLE}
+
{$SUCCESS_TITLE}
{$SUCCESS}
{/if} @@ -12,11 +12,11 @@ -
{$ERRORS_TITLE}
+
{$ERRORS_TITLE}
    {foreach from=$ERRORS item=error}
  • {$error}
  • {/foreach}
-{/if} \ No newline at end of file +{/if} diff --git a/custom/templates/DefaultRevamp/css/custom.css b/custom/templates/DefaultRevamp/css/custom.css index 33a551b08c..bcf690dbd0 100755 --- a/custom/templates/DefaultRevamp/css/custom.css +++ b/custom/templates/DefaultRevamp/css/custom.css @@ -1052,6 +1052,23 @@ select { } } +/* + Fix icons displaying small as forum icons + */ +.one.wide.column.mobile.hidden > i:first-child { + font-size: 2.3em; +} + +/* + Fix FontAwesome icons displaying strangely announcement icons + Styles copied from Fomantic UI's .message>.icon class + */ +.ui.icon.message.announcement > i:first-child:not(.icon) { + font-size: 3em; + margin-right: .6em; + opacity: .8; +} + #darkmode { display: inline-block; } diff --git a/custom/templates/DefaultRevamp/forum/forum_index.tpl b/custom/templates/DefaultRevamp/forum/forum_index.tpl index c148ad8faf..efed08482c 100755 --- a/custom/templates/DefaultRevamp/forum/forum_index.tpl +++ b/custom/templates/DefaultRevamp/forum/forum_index.tpl @@ -55,33 +55,34 @@ {foreach from=$forum.subforums item=subforum} {if $subforum->redirect_forum neq 1}
- {else} - {$item.icon} {$item.title} + {if $item.icon} + + {/if} + {$item.title} {/if} {/foreach} @@ -53,49 +61,49 @@
@@ -166,22 +174,20 @@ {/if} {if !empty($ANNOUNCEMENTS)} - {foreach from=$ANNOUNCEMENTS item=$ANNOUNCEMENT} -
- {if $ANNOUNCEMENT->closable} - - {/if} - {if $ANNOUNCEMENT->icon} - - {/if} -
-
{$ANNOUNCEMENT->header}
-

{$ANNOUNCEMENT->message|escape}

-
-
- {/foreach} + {foreach from=$ANNOUNCEMENTS item=$ANNOUNCEMENT} +
+ {if $ANNOUNCEMENT->closable} + + {/if} + {if $ANNOUNCEMENT->icon} + + {/if} +
+
{$ANNOUNCEMENT->header}
+

{$ANNOUNCEMENT->message|escape}

+
+
+ {/foreach} {/if} {if isset($MUST_VALIDATE_ACCOUNT)} diff --git a/dev/scripts/postinstall.js b/dev/scripts/postinstall.js index 1e5045cdc6..d2ee7b14ef 100644 --- a/dev/scripts/postinstall.js +++ b/dev/scripts/postinstall.js @@ -44,6 +44,7 @@ const publicAssets = { 'dist/semantic.min.css', 'dist/semantic.min.js', 'dist/themes/default', + 'dist/components/icon.min.css', ], 'image-picker': [ 'image-picker/image-picker.css', @@ -78,6 +79,9 @@ const publicAssets = { 'bundles/skinview3d.bundle.js.map', 'assets/minecraft.woff2', ], + '@migliori/universal-icon-picker': [ + 'assets', + ], }; fse.emptyDirSync('core/assets/vendor'); diff --git a/modules/Core/pages/panel/announcements.php b/modules/Core/pages/panel/announcements.php index 70dc15b561..9ed226f836 100644 --- a/modules/Core/pages/panel/announcements.php +++ b/modules/Core/pages/panel/announcements.php @@ -30,6 +30,10 @@ $page_title = $language->get('admin', 'announcements'); require_once ROOT_PATH . '/core/templates/backend_init.php'; +$template->assets()->include( + AssetTree::ICON_PICKER, +); + if (!isset($_GET['action'])) { // View all announcements diff --git a/modules/Core/pages/panel/navigation.php b/modules/Core/pages/panel/navigation.php index 05a966ab9f..84131785f7 100644 --- a/modules/Core/pages/panel/navigation.php +++ b/modules/Core/pages/panel/navigation.php @@ -29,6 +29,10 @@ $page_title = $language->get('admin', 'navigation'); require_once ROOT_PATH . '/core/templates/backend_init.php'; +$template->assets()->include( + AssetTree::ICON_PICKER, +); + // Deal with input if (Input::exists()) { $errors = []; diff --git a/modules/Forum/language/en_UK.json b/modules/Forum/language/en_UK.json index 42ebd87b03..34319b4945 100644 --- a/modules/Forum/language/en_UK.json +++ b/modules/Forum/language/en_UK.json @@ -42,6 +42,7 @@ "forum/forum_description": "Forum Description", "forum/forum_description_maximum": "The forum description must be a maximum of 255 characters.", "forum/forum_icon": "Forum Icon", + "forum/forum_icon_instructions": "You can also add an to the forum here, for example using {{faLink}} or {{semLink}}.", "forum/forum_icon_maximum": "The forum icon must be a maximum of 256 characters.", "forum/forum_index": "Home", "forum/forum_name": "Forum Name", diff --git a/modules/Forum/pages/panel/forums.php b/modules/Forum/pages/panel/forums.php index c95be0f119..185bd50c28 100644 --- a/modules/Forum/pages/panel/forums.php +++ b/modules/Forum/pages/panel/forums.php @@ -31,6 +31,10 @@ $page_title = $forum_language->get('forum', 'forums'); require_once ROOT_PATH . '/core/templates/backend_init.php'; +$template->assets()->include( + AssetTree::ICON_PICKER, +); + if (!isset($_GET['action']) && !isset($_GET['forum'])) { $forums = DB::getInstance()->orderAll('forums', 'forum_order', 'ASC')->results(); $template_array = []; @@ -163,6 +167,11 @@ 'FORUM_DESCRIPTION_VALUE' => Output::getClean(Input::get('forumdesc')), 'FORUM_ICON' => $forum_language->get('forum', 'forum_icon'), 'FORUM_ICON_VALUE' => Output::getClean(Input::get('forum_icon')), + 'INFO' => $language->get('general', 'info'), + 'ICON_INFO' => Output::getClean($forum_language->get('forum', 'forum_icon_instructions', [ + 'faLink' => 'Font Awesome', + 'semLink' => 'Fomantic UI', + ])), ]); $template_file = 'forum/forums_new_step_1'; @@ -782,6 +791,10 @@ 'HOOKS_ARRAY' => $hooks_array, 'FORUM_HOOKS' => json_decode($forum_hooks), 'INFO' => $language->get('general', 'info'), + 'ICON_INFO' => Output::getClean($forum_language->get('forum', 'forum_icon_instructions', [ + 'faLink' => 'Font Awesome', + 'semLink' => 'Fomantic UI', + ])), 'HOOK_SELECT_INFO' => $language->get('admin', 'hook_select_info'), 'FORUM_PERMISSIONS' => $forum_language->get('forum', 'forum_permissions'), 'GUESTS' => $language->get('user', 'guests'), diff --git a/package-lock.json b/package-lock.json index 38ca1db926..cdeaa46402 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "license": "MIT", "dependencies": { "@fortawesome/fontawesome-free": "^6.1.1", + "@migliori/universal-icon-picker": "^1.1.4", "@popperjs/core": "^2.10.2", "bootstrap": "4.6.1", "bootstrap-colorpicker": "^3.4.0", @@ -58,6 +59,11 @@ "node": ">=6" } }, + "node_modules/@migliori/universal-icon-picker": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@migliori/universal-icon-picker/-/universal-icon-picker-1.1.5.tgz", + "integrity": "sha512-nfWmFXfCIeEfWcHmxF2SXf0ptYayMXLfxfAdBITQ6GpVw1bi1nI1nqlYf3PFW4XSZbFsz+z2kvNVk0tS5REF/g==" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -8400,6 +8406,11 @@ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.3.0.tgz", "integrity": "sha512-qVtd5i1Cc7cdrqnTWqTObKQHjPWAiRwjUPaXObaeNPcy7+WKxJumGBx66rfSFgK6LNpIasVKkEgW8oyf0tmPLA==" }, + "@migliori/universal-icon-picker": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@migliori/universal-icon-picker/-/universal-icon-picker-1.1.5.tgz", + "integrity": "sha512-nfWmFXfCIeEfWcHmxF2SXf0ptYayMXLfxfAdBITQ6GpVw1bi1nI1nqlYf3PFW4XSZbFsz+z2kvNVk0tS5REF/g==" + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", diff --git a/package.json b/package.json index 07f73486c7..5d2965dc77 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "private": true, "dependencies": { "@fortawesome/fontawesome-free": "^6.1.1", + "@migliori/universal-icon-picker": "^1.1.4", "@popperjs/core": "^2.10.2", "bootstrap": "4.6.1", "bootstrap-colorpicker": "^3.4.0",