mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-31 19:15:58 +01:00
Acp redesign (#11639)
* acp sidebar
* gap in nav
* remove shadow
* label fixes
* color fixes
* feat: settings page wip
* feat: scroll spy 👓
move social into general, store social in meta.config like other settings
write upgrade script
* remove social
* rermove openapi routes
* cleanup, highlight selected nav item
* more cleanup
* advanced margin top
* derp
* match design
* bring back version alert
fix homepage js, since it moved to general settings
* remove unused tpls
these moved to general settings
* remove more css
* offcanvas for mobile
fix search
* add timeout
* add new props
* manage categories
* small fixes
* category-edit
* feat category page fixes
* add title to settings pages
add user settings page
* small fixes
* some more settings pages
* fix: plugin page titles
* more settings pages
* more padding
* more pages, add acp paginator.tpl
so it doesn't change when active theme changes
* remove placeholder
* dashboard table
* fix: openapi
* fix: controller tests
* use fonts from core
* some small fixes
* fix rep page
* refactor: fix name of upgrade script
* create category modal
group edit
* group/groups pages
* admins mods
* privs
* uploads
* missing margin
* more acp pages
* more pages
* plugins/rewards/widgets
* wrap rewards
* fix widgets
* fix widget clone button
* fix group acp edit link
* update search dropdown
* remove display block from tbody
* use less css
* remove some derp links
* remove striped tables
* remove p tags from lang files
* update email settings
* Update api.tpl
* move tag-whitelist
This commit is contained in:
committed by
GitHub
parent
6d4ab1d0c1
commit
c3afe44686
@@ -29,6 +29,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@adactive/bootstrap-tagsinput": "0.8.2",
|
"@adactive/bootstrap-tagsinput": "0.8.2",
|
||||||
|
"@fontsource/inter": "^4.5.14",
|
||||||
|
"@fontsource/poppins": "^4.5.10",
|
||||||
"@isaacs/ttlcache": "1.4.0",
|
"@isaacs/ttlcache": "1.4.0",
|
||||||
"@popperjs/core": "2.11.8",
|
"@popperjs/core": "2.11.8",
|
||||||
"ace-builds": "1.22.0",
|
"ace-builds": "1.22.0",
|
||||||
@@ -82,7 +84,6 @@
|
|||||||
"lodash": "4.17.21",
|
"lodash": "4.17.21",
|
||||||
"logrotate-stream": "0.2.9",
|
"logrotate-stream": "0.2.9",
|
||||||
"lru-cache": "9.1.1",
|
"lru-cache": "9.1.1",
|
||||||
"material-design-lite": "1.3.0",
|
|
||||||
"mime": "3.0.0",
|
"mime": "3.0.0",
|
||||||
"mkdirp": "3.0.1",
|
"mkdirp": "3.0.1",
|
||||||
"mongodb": "5.5.0",
|
"mongodb": "5.5.0",
|
||||||
|
|||||||
@@ -4,6 +4,13 @@
|
|||||||
|
|
||||||
"acp-title": "%1 | NodeBB Admin Control Panel",
|
"acp-title": "%1 | NodeBB Admin Control Panel",
|
||||||
"settings-header-contents": "Contents",
|
"settings-header-contents": "Contents",
|
||||||
|
"changes-saved": "Changes Saved",
|
||||||
|
"changes-saved-message": "Your changes to the NodeBB configuration have been saved.",
|
||||||
"changes-not-saved": "Changes Not Saved",
|
"changes-not-saved": "Changes Not Saved",
|
||||||
"changes-not-saved-message": "NodeBB encountered a problem saving your changes. (%1)"
|
"changes-not-saved-message": "NodeBB encountered a problem saving your changes. (%1)",
|
||||||
|
"save-changes": "Save changes",
|
||||||
|
"min": "Min:",
|
||||||
|
"max": "Max:",
|
||||||
|
"view": "View",
|
||||||
|
"edit": "Edit"
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
"uptime-seconds": "Uptime in Seconds",
|
"uptime-seconds": "Uptime in Seconds",
|
||||||
"uptime-days": "Uptime in Days",
|
"uptime-days": "Uptime in Days",
|
||||||
|
|
||||||
"mongo": "Mongo",
|
"mongo": "MongoDB",
|
||||||
"mongo.version": "MongoDB Version",
|
"mongo.version": "MongoDB Version",
|
||||||
"mongo.storage-engine": "Storage Engine",
|
"mongo.storage-engine": "Storage Engine",
|
||||||
"mongo.collections": "Collections",
|
"mongo.collections": "Collections",
|
||||||
|
|||||||
@@ -26,13 +26,13 @@
|
|||||||
"updates": "Updates",
|
"updates": "Updates",
|
||||||
"running-version": "You are running <strong>NodeBB v<span id=\"version\">%1</span></strong>.",
|
"running-version": "You are running <strong>NodeBB v<span id=\"version\">%1</span></strong>.",
|
||||||
"keep-updated": "Always make sure that your NodeBB is up to date for the latest security patches and bug fixes.",
|
"keep-updated": "Always make sure that your NodeBB is up to date for the latest security patches and bug fixes.",
|
||||||
"up-to-date": "<p>You are <strong>up-to-date</strong> <i class=\"fa fa-check\"></i></p>",
|
"up-to-date": "You are <strong>up-to-date</strong> <i class=\"fa fa-check\"></i>",
|
||||||
"upgrade-available": "<p>A new version (v%1) has been released. Consider <a href=\"https://docs.nodebb.org/configuring/upgrade/\" target=\"_blank\">upgrading your NodeBB</a>.</p>",
|
"upgrade-available": "A new version (v%1) has been released. Consider <a href=\"https://docs.nodebb.org/configuring/upgrade/\" target=\"_blank\">upgrading your NodeBB</a>.",
|
||||||
"prerelease-upgrade-available": "<p>This is an outdated pre-release version of NodeBB. A new version (v%1) has been released. Consider <a href=\"https://docs.nodebb.org/configuring/upgrade/\" target=\"_blank\">upgrading your NodeBB</a>.</p>",
|
"prerelease-upgrade-available": "This is an outdated pre-release version of NodeBB. A new version (v%1) has been released. Consider <a href=\"https://docs.nodebb.org/configuring/upgrade/\" target=\"_blank\">upgrading your NodeBB</a>.",
|
||||||
"prerelease-warning": "<p>This is a <strong>pre-release</strong> version of NodeBB. Unintended bugs may occur. <i class=\"fa fa-exclamation-triangle\"></i></p>",
|
"prerelease-warning": "This is a <strong>pre-release</strong> version of NodeBB. Unintended bugs may occur. <i class=\"fa fa-exclamation-triangle\"></i>",
|
||||||
"fallback-emailer-not-found": "Fallback emailer not found!",
|
"fallback-emailer-not-found": "Fallback emailer not found!",
|
||||||
"running-in-development": "<span>Forum is running in development mode. The forum may be open to potential vulnerabilities; please contact your system administrator.</span>",
|
"running-in-development": "Forum is running in development mode. The forum may be open to potential vulnerabilities; please contact your system administrator",
|
||||||
"latest-lookup-failed": "<p>Failed to look up latest available version of NodeBB</p>",
|
"latest-lookup-failed": "Failed to look up latest available version of NodeBB",
|
||||||
|
|
||||||
"notices": "Notices",
|
"notices": "Notices",
|
||||||
"restart-not-required": "Restart not required",
|
"restart-not-required": "Restart not required",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"plugins": "Plugins",
|
||||||
"trending": "Trending",
|
"trending": "Trending",
|
||||||
"installed": "Installed",
|
"installed": "Installed",
|
||||||
"active": "Active",
|
"active": "Active",
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
{
|
{
|
||||||
"rewards": "Rewards",
|
"rewards": "Rewards",
|
||||||
|
"add-reward": "Add reward",
|
||||||
"condition-if-users": "If User's",
|
"condition-if-users": "If User's",
|
||||||
"condition-is": "Is:",
|
"condition-is": "Is:",
|
||||||
"condition-then": "Then:",
|
"condition-then": "Then:",
|
||||||
"max-claims": "Amount of times reward is claimable",
|
"max-claims": "Amount of times reward is claimable",
|
||||||
"zero-infinite": "Enter 0 for infinite",
|
"zero-infinite": "Enter 0 for infinite",
|
||||||
|
"select-reward": "Select reward",
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"enable": "Enable",
|
"enable": "Enable",
|
||||||
"disable": "Disable",
|
"disable": "Disable",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"widgets": "Widgets",
|
||||||
"available": "Available Widgets",
|
"available": "Available Widgets",
|
||||||
"explanation": "Select a widget from the dropdown menu and then drag and drop it into a template's widget area on the left.",
|
"explanation": "Select a widget from the dropdown menu and then drag and drop it into a template's widget area on the left.",
|
||||||
"none-installed": "No widgets found! Activate the widget essentials plugin in the <a href=\"%1\">plugins</a> control panel.",
|
"none-installed": "No widgets found! Activate the widget essentials plugin in the <a href=\"%1\">plugins</a> control panel.",
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
{
|
{
|
||||||
|
"manage-admins-and-mods": "Manage Admins & Mods",
|
||||||
"administrators": "Administrators",
|
"administrators": "Administrators",
|
||||||
"global-moderators": "Global Moderators",
|
"global-moderators": "Global Moderators",
|
||||||
"moderators": "Moderators",
|
"moderators": "Moderators",
|
||||||
"no-global-moderators": "No Global Moderators",
|
"no-global-moderators": "No Global Moderators",
|
||||||
"no-sub-categories": "No subcategories",
|
"no-sub-categories": "No subcategories",
|
||||||
"subcategories": "%1 subcategories",
|
"view-children": "View children (%1)",
|
||||||
"no-moderators": "No Moderators",
|
"no-moderators": "No Moderators",
|
||||||
"add-administrator": "Add Administrator",
|
"add-administrator": "Add Administrator",
|
||||||
"add-global-moderator": "Add Global Moderator",
|
"add-global-moderator": "Add Global Moderator",
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
{
|
{
|
||||||
|
"manage-categories": "Manage Categories",
|
||||||
|
"add-category": "Add category",
|
||||||
|
"jump-to": "Jump to...",
|
||||||
"settings": "Category Settings",
|
"settings": "Category Settings",
|
||||||
|
"edit-category": "Edit Category",
|
||||||
"privileges": "Privileges",
|
"privileges": "Privileges",
|
||||||
|
"back-to-categories": "Back to categories",
|
||||||
"name": "Category Name",
|
"name": "Category Name",
|
||||||
"description": "Category Description",
|
"description": "Category Description",
|
||||||
"bg-color": "Background Colour",
|
"bg-color": "Background Colour",
|
||||||
@@ -15,8 +19,11 @@
|
|||||||
"post-queue": "Post queue",
|
"post-queue": "Post queue",
|
||||||
"tag-whitelist": "Tag Whitelist",
|
"tag-whitelist": "Tag Whitelist",
|
||||||
"upload-image": "Upload Image",
|
"upload-image": "Upload Image",
|
||||||
|
"upload": "Upload",
|
||||||
|
"select-icon": "Select Icon",
|
||||||
"delete-image": "Remove",
|
"delete-image": "Remove",
|
||||||
"category-image": "Category Image",
|
"category-image": "Category Image",
|
||||||
|
"image-and-icon": "Image & Icon",
|
||||||
"parent-category": "Parent Category",
|
"parent-category": "Parent Category",
|
||||||
"optional-parent-category": "(Optional) Parent Category",
|
"optional-parent-category": "(Optional) Parent Category",
|
||||||
"top-level": "Top Level",
|
"top-level": "Top Level",
|
||||||
@@ -31,6 +38,7 @@
|
|||||||
"disable": "Disable",
|
"disable": "Disable",
|
||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"analytics": "Analytics",
|
"analytics": "Analytics",
|
||||||
|
|
||||||
"view-category": "View category",
|
"view-category": "View category",
|
||||||
"set-order": "Set order",
|
"set-order": "Set order",
|
||||||
"set-order-help": "Setting the order of the category will move this category to that order and update the order of other categories as necessary. Minimum order is 1 which puts the category at the top.",
|
"set-order-help": "Setting the order of the category will move this category to that order and update the order of other categories as necessary. Minimum order is 1 which puts the category at the top.",
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
{
|
{
|
||||||
|
"manage-groups": "Manage groups",
|
||||||
|
"add-group": "Add group",
|
||||||
|
"edit-group": "Edit Group",
|
||||||
|
"back-to-groups": "Back to groups",
|
||||||
|
"view-group": "View group",
|
||||||
|
"icon-and-title": "Icon & Title",
|
||||||
"name": "Group Name",
|
"name": "Group Name",
|
||||||
"badge": "Badge",
|
"badge": "Badge",
|
||||||
"properties": "Properties",
|
"properties": "Properties",
|
||||||
@@ -10,7 +16,7 @@
|
|||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"privileges": "Privileges",
|
"privileges": "Privileges",
|
||||||
"download-csv": "CSV",
|
"members-csv": "Members (CSV)",
|
||||||
"search-placeholder": "Search",
|
"search-placeholder": "Search",
|
||||||
"create": "Create Group",
|
"create": "Create Group",
|
||||||
"description-placeholder": "A short description about your group",
|
"description-placeholder": "A short description about your group",
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
{
|
{
|
||||||
|
"manage-privileges": "Manage Privileges",
|
||||||
|
"discard-changes": "Discard changes",
|
||||||
"global": "Global",
|
"global": "Global",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"group-privileges": "Group Privileges",
|
"group-privileges": "Group Privileges",
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
{
|
{
|
||||||
|
"manage-tags": "Manage Tags",
|
||||||
"none": "Your forum does not have any topics with tags yet.",
|
"none": "Your forum does not have any topics with tags yet.",
|
||||||
"bg-color": "Background Colour",
|
"bg-color": "Background Colour",
|
||||||
"text-color": "Text Colour",
|
"text-color": "Text Colour",
|
||||||
"description": "Select tags by clicking or dragging, use <code>CTRL</code> to select multiple tags.",
|
"description": "Select tags by clicking or dragging, use <code>CTRL</code> to select multiple tags.",
|
||||||
"create": "Create Tag",
|
"create": "Create Tag",
|
||||||
|
"add-tag": "Add tag",
|
||||||
"modify": "Modify Tags",
|
"modify": "Modify Tags",
|
||||||
"rename": "Rename Tags",
|
"rename": "Rename Tags",
|
||||||
"delete": "Delete Selected Tags",
|
"delete": "Delete Selected Tags",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"manage-uploads": "Manage Uploads",
|
||||||
"upload-file": "Upload File",
|
"upload-file": "Upload File",
|
||||||
"filename": "Filename",
|
"filename": "Filename",
|
||||||
"usage": "Post Usage",
|
"usage": "Post Usage",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"manage-users": "Manage Users",
|
||||||
"users": "Users",
|
"users": "Users",
|
||||||
"edit": "Actions",
|
"edit": "Actions",
|
||||||
"make-admin": "Make Admin",
|
"make-admin": "Make Admin",
|
||||||
|
|||||||
@@ -72,7 +72,9 @@
|
|||||||
"development/info": "Info",
|
"development/info": "Info",
|
||||||
|
|
||||||
"rebuild-and-restart-forum": "Rebuild & Restart Forum",
|
"rebuild-and-restart-forum": "Rebuild & Restart Forum",
|
||||||
|
"rebuild-and-restart": "Rebuild & Restart",
|
||||||
"restart-forum": "Restart Forum",
|
"restart-forum": "Restart Forum",
|
||||||
|
"restart": "Restart",
|
||||||
"logout": "Log out",
|
"logout": "Log out",
|
||||||
"view-forum": "View Forum",
|
"view-forum": "View Forum",
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
{
|
{
|
||||||
|
"general-settings": "General Settings",
|
||||||
|
"on-this-page": "On this page:",
|
||||||
"site-settings": "Site Settings",
|
"site-settings": "Site Settings",
|
||||||
"title": "Site Title",
|
"title": "Site Title",
|
||||||
"title.short": "Short Title",
|
"title.short": "Short Title",
|
||||||
"title.short-placeholder": "If no short title is specified, the site title will be used",
|
"title.short-placeholder": "If no short title is specified, the site title will be used",
|
||||||
"title.url": "Title Link URL",
|
"title.url": "Title Link URL",
|
||||||
"title.url-placeholder": "The URL of the site title",
|
"title.url-placeholder": "The URL of the site title",
|
||||||
"title.url-help": "When the title is clicked, send users to this address. If left blank, user will be sent to the forum index. <br> Note: This is not the external URL used in emails, etc. That is set by the <code>url</code> property in config.json",
|
"title.url-help": "When the title is clicked, send users to this address. If left blank, user will be sent to the forum index. Note: This is not the external URL used in emails, etc. That is set by the <code>url</code> property in config.json",
|
||||||
"title.name": "Your Community Name",
|
"title.name": "Your Community Name",
|
||||||
"title.show-in-header": "Show Site Title in Header",
|
"title.show-in-header": "Show Site Title in Header",
|
||||||
"browser-title": "Browser Title",
|
"browser-title": "Browser Title",
|
||||||
@@ -16,7 +18,7 @@
|
|||||||
"description": "Site Description",
|
"description": "Site Description",
|
||||||
"keywords": "Site Keywords",
|
"keywords": "Site Keywords",
|
||||||
"keywords-placeholder": "Keywords describing your community, comma-separated",
|
"keywords-placeholder": "Keywords describing your community, comma-separated",
|
||||||
"logo": "Site Logo",
|
"logo-and-icons": "Site Logo & Icons",
|
||||||
"logo.image": "Image",
|
"logo.image": "Image",
|
||||||
"logo.image-placeholder": "Path to a logo to display on forum header",
|
"logo.image-placeholder": "Path to a logo to display on forum header",
|
||||||
"logo.upload": "Upload",
|
"logo.upload": "Upload",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
|
"guest-settings": "Guest settings",
|
||||||
"handles.enabled": "Allow guest handles",
|
"handles.enabled": "Allow guest handles",
|
||||||
"handles.enabled-help": "This option exposes a new field that allows guests to pick a name to associate with each post they make. If disabled, they will simply be called \"Guest\"",
|
"handles.enabled-help": "This option exposes a new field that allows guests to pick a name to associate with each post they make. If disabled, they will simply be called \"Guest\"",
|
||||||
"topic-views.enabled": "Allow guests to increase topic view counts",
|
"topic-views.enabled": "Allow guests to increase topic view counts",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"navigation": "Navigation",
|
||||||
"icon": "Icon:",
|
"icon": "Icon:",
|
||||||
"change-icon": "change",
|
"change-icon": "change",
|
||||||
"route": "Route:",
|
"route": "Route:",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"general": "General",
|
||||||
"sorting": "Post Sorting",
|
"sorting": "Post Sorting",
|
||||||
"sorting.post-default": "Default Post Sorting",
|
"sorting.post-default": "Default Post Sorting",
|
||||||
"sorting.oldest-to-newest": "Oldest to Newest",
|
"sorting.oldest-to-newest": "Oldest to Newest",
|
||||||
@@ -23,10 +24,8 @@
|
|||||||
"restrictions.seconds-edit-after": "Number of seconds a post remains editable (set to 0 to disable)",
|
"restrictions.seconds-edit-after": "Number of seconds a post remains editable (set to 0 to disable)",
|
||||||
"restrictions.seconds-delete-after": "Number of seconds a post remains deletable (set to 0 to disable)",
|
"restrictions.seconds-delete-after": "Number of seconds a post remains deletable (set to 0 to disable)",
|
||||||
"restrictions.replies-no-delete": "Number of replies after users are disallowed to delete their own topics (set to 0 to disable)",
|
"restrictions.replies-no-delete": "Number of replies after users are disallowed to delete their own topics (set to 0 to disable)",
|
||||||
"restrictions.min-title-length": "Minimum Title Length",
|
"restrictions.title-length": "Title Length",
|
||||||
"restrictions.max-title-length": "Maximum Title Length",
|
"restrictions.post-length": "Post Length",
|
||||||
"restrictions.min-post-length": "Minimum Post Length",
|
|
||||||
"restrictions.max-post-length": "Maximum Post Length",
|
|
||||||
"restrictions.days-until-stale": "Days until topic is considered stale",
|
"restrictions.days-until-stale": "Days until topic is considered stale",
|
||||||
"restrictions.stale-help": "If a topic is considered \"stale\", then a warning will be shown to users who attempt to reply to that topic.",
|
"restrictions.stale-help": "If a topic is considered \"stale\", then a warning will be shown to users who attempt to reply to that topic.",
|
||||||
"timestamp": "Timestamp",
|
"timestamp": "Timestamp",
|
||||||
@@ -41,10 +40,9 @@
|
|||||||
"teaser.last-reply": "Last – Show the latest reply, or a \"No replies\" placeholder if no replies",
|
"teaser.last-reply": "Last – Show the latest reply, or a \"No replies\" placeholder if no replies",
|
||||||
"teaser.first": "First",
|
"teaser.first": "First",
|
||||||
"showPostPreviewsOnHover": "Show a preview of posts when mouse overed",
|
"showPostPreviewsOnHover": "Show a preview of posts when mouse overed",
|
||||||
"unread": "Unread Settings",
|
"unread-and-recent": "Unread & Recent Settings",
|
||||||
"unread.cutoff": "Unread cutoff days",
|
"unread.cutoff": "Unread cutoff days",
|
||||||
"unread.min-track-last": "Minimum posts in topic before tracking last read",
|
"unread.min-track-last": "Minimum posts in topic before tracking last read",
|
||||||
"recent": "Recent Settings",
|
|
||||||
"recent.max-topics": "Maximum topics on /recent",
|
"recent.max-topics": "Maximum topics on /recent",
|
||||||
"recent.categoryFilter.disable": "Disable filtering of topics in ignored categories on the /recent page",
|
"recent.categoryFilter.disable": "Disable filtering of topics in ignored categories on the /recent page",
|
||||||
"signature": "Signature Settings",
|
"signature": "Signature Settings",
|
||||||
|
|||||||
@@ -27,5 +27,5 @@
|
|||||||
"flags.action-on-resolve": "Do the following when a flag is resolved",
|
"flags.action-on-resolve": "Do the following when a flag is resolved",
|
||||||
"flags.action-on-reject": "Do the following when a flag is rejected",
|
"flags.action-on-reject": "Do the following when a flag is rejected",
|
||||||
"flags.action.nothing": "Do nothing",
|
"flags.action.nothing": "Do nothing",
|
||||||
"flags.action.rescind": "Rescind the notification send to moderators/administrators"
|
"flags.action.rescind": "Rescind the notification sent to moderators/administrators"
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"post-sharing": "Post Sharing",
|
"post-sharing": "Post Sharing",
|
||||||
"info-plugins-additional": "Plugins can add additional networks for sharing posts.",
|
"info-plugins-additional": "Plugins can add additional networks for sharing posts."
|
||||||
"save-success": "Successfully saved Post Sharing Networks!"
|
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
"link-to-manage": "Manage Tags",
|
"link-to-manage": "Manage Tags",
|
||||||
"system-tags": "System Tags",
|
"system-tags": "System Tags",
|
||||||
"system-tags-help": "Only privileged users will be able to use these tags.",
|
"system-tags-help": "Only privileged users will be able to use these tags.",
|
||||||
|
"tags-per-topic": "Tags per topic",
|
||||||
"min-per-topic": "Minimum Tags per Topic",
|
"min-per-topic": "Minimum Tags per Topic",
|
||||||
"max-per-topic": "Maximum Tags per Topic",
|
"max-per-topic": "Maximum Tags per Topic",
|
||||||
"min-length": "Minimum Tag Length",
|
"min-length": "Minimum Tag Length",
|
||||||
|
|||||||
@@ -59,7 +59,7 @@
|
|||||||
"max-about-me-length": "Maximum About Me Length",
|
"max-about-me-length": "Maximum About Me Length",
|
||||||
"terms-of-use": "Forum Terms of Use <small>(Leave blank to disable)</small>",
|
"terms-of-use": "Forum Terms of Use <small>(Leave blank to disable)</small>",
|
||||||
"user-search": "User Search",
|
"user-search": "User Search",
|
||||||
"user-search-results-per-page": "Number of results to display",
|
"user-search-results-per-page": "Number of users to display in search results",
|
||||||
"default-user-settings": "Default User Settings",
|
"default-user-settings": "Default User Settings",
|
||||||
"show-email": "Show email",
|
"show-email": "Show email",
|
||||||
"show-fullname": "Show fullname",
|
"show-fullname": "Show fullname",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
"save_changes": "Save Changes",
|
"save_changes": "Save Changes",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
|
"create": "Create",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
|
|
||||||
|
|||||||
@@ -82,14 +82,8 @@ paths:
|
|||||||
$ref: 'read/admin/dashboard/searches.yaml'
|
$ref: 'read/admin/dashboard/searches.yaml'
|
||||||
"/api/admin/settings/{term}":
|
"/api/admin/settings/{term}":
|
||||||
$ref: 'read/admin/settings/term.yaml'
|
$ref: 'read/admin/settings/term.yaml'
|
||||||
/api/admin/settings/languages:
|
|
||||||
$ref: 'read/admin/settings/languages.yaml'
|
|
||||||
/api/admin/settings/navigation:
|
/api/admin/settings/navigation:
|
||||||
$ref: 'read/admin/settings/navigation.yaml'
|
$ref: 'read/admin/settings/navigation.yaml'
|
||||||
/api/admin/settings/homepage:
|
|
||||||
$ref: 'read/admin/settings/homepage.yaml'
|
|
||||||
/api/admin/settings/social:
|
|
||||||
$ref: 'read/admin/settings/social.yaml'
|
|
||||||
/api/admin/settings/api:
|
/api/admin/settings/api:
|
||||||
$ref: 'read/admin/settings/api.yaml'
|
$ref: 'read/admin/settings/api.yaml'
|
||||||
/api/admin/settings/email:
|
/api/admin/settings/email:
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ get:
|
|||||||
properties:
|
properties:
|
||||||
categoriesPerPage:
|
categoriesPerPage:
|
||||||
type: number
|
type: number
|
||||||
|
selectCategoryLabel:
|
||||||
|
type: string
|
||||||
categoriesTree:
|
categoriesTree:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
@@ -23,6 +25,8 @@ get:
|
|||||||
description: A category identifier
|
description: A category identifier
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
disabled:
|
disabled:
|
||||||
type: number
|
type: number
|
||||||
icon:
|
icon:
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ get:
|
|||||||
allOf:
|
allOf:
|
||||||
- type: object
|
- type: object
|
||||||
properties:
|
properties:
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
groupsExemptFromMaintenanceMode:
|
groupsExemptFromMaintenanceMode:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ get:
|
|||||||
allOf:
|
allOf:
|
||||||
- type: object
|
- type: object
|
||||||
properties:
|
properties:
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
tokens:
|
tokens:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ get:
|
|||||||
allOf:
|
allOf:
|
||||||
- type: object
|
- type: object
|
||||||
properties:
|
properties:
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
emails:
|
emails:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
get:
|
|
||||||
tags:
|
|
||||||
- admin
|
|
||||||
summary: Get homepage settings
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: ""
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
allOf:
|
|
||||||
- type: object
|
|
||||||
properties:
|
|
||||||
routes:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
route:
|
|
||||||
type: string
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
- $ref: ../../../components/schemas/CommonProps.yaml#/CommonProps
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
get:
|
|
||||||
tags:
|
|
||||||
- admin
|
|
||||||
summary: Get language settings
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: A JSON object containing available languages and settings
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
allOf:
|
|
||||||
- type: object
|
|
||||||
properties:
|
|
||||||
languages:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
description: Localised name of the language
|
|
||||||
code:
|
|
||||||
type: string
|
|
||||||
description: A language code (similar to ISO-639)
|
|
||||||
dir:
|
|
||||||
type: string
|
|
||||||
description: Directionality of the language
|
|
||||||
enum: [ltr, rtl]
|
|
||||||
selected:
|
|
||||||
type: boolean
|
|
||||||
description: Denotes the currently selected default system language on the forum
|
|
||||||
autoDetectLang:
|
|
||||||
type: integer
|
|
||||||
description: Whether the forum will attempt to guess language based on browser's `Accept-Language` header
|
|
||||||
- $ref: ../../../components/schemas/CommonProps.yaml#/CommonProps
|
|
||||||
@@ -111,4 +111,6 @@ get:
|
|||||||
navigation:
|
navigation:
|
||||||
type: array
|
type: array
|
||||||
description: A clone of `enabled`
|
description: A clone of `enabled`
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
- $ref: ../../../components/schemas/CommonProps.yaml#/CommonProps
|
- $ref: ../../../components/schemas/CommonProps.yaml#/CommonProps
|
||||||
@@ -11,6 +11,8 @@ get:
|
|||||||
allOf:
|
allOf:
|
||||||
- type: object
|
- type: object
|
||||||
properties:
|
properties:
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
groupsExemptFromPostQueue:
|
groupsExemptFromPostQueue:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
get:
|
|
||||||
tags:
|
|
||||||
- admin
|
|
||||||
summary: Get post social sharing settings
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: "A JSON object containing post social sharing settings"
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
allOf:
|
|
||||||
- type: object
|
|
||||||
properties:
|
|
||||||
posts:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
id:
|
|
||||||
type: string
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
class:
|
|
||||||
type: string
|
|
||||||
description: A FontAwesome icon string
|
|
||||||
activated:
|
|
||||||
type: boolean
|
|
||||||
- $ref: ../../../components/schemas/CommonProps.yaml#/CommonProps
|
|
||||||
@@ -17,7 +17,17 @@ get:
|
|||||||
schema:
|
schema:
|
||||||
allOf:
|
allOf:
|
||||||
- type: object
|
- type: object
|
||||||
properties: {}
|
properties:
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
|
routes:
|
||||||
|
type: array
|
||||||
|
postSharing:
|
||||||
|
type: array
|
||||||
|
languages:
|
||||||
|
type: array
|
||||||
|
autoDetectLang:
|
||||||
|
type: number
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: object
|
type: object
|
||||||
description: Most of the settings pages have their values loaded on the client-side, so the settings are not exposed server-side.
|
description: Most of the settings pages have their values loaded on the client-side, so the settings are not exposed server-side.
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ get:
|
|||||||
allOf:
|
allOf:
|
||||||
- type: object
|
- type: object
|
||||||
properties:
|
properties:
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
notificationSettings:
|
notificationSettings:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
@import "./mixins";
|
@import "fonts";
|
||||||
|
@import "mixins";
|
||||||
|
@import "common";
|
||||||
|
|
||||||
@import "./header";
|
@import "sidebar";
|
||||||
@import "./mobile";
|
@import "./mobile";
|
||||||
|
|
||||||
@import "./general/dashboard";
|
@import "./general/dashboard";
|
||||||
@@ -12,10 +14,8 @@
|
|||||||
@import "./settings/api";
|
@import "./settings/api";
|
||||||
@import "./appearance/customise";
|
@import "./appearance/customise";
|
||||||
@import "./extend/plugins";
|
@import "./extend/plugins";
|
||||||
@import "./extend/rewards";
|
|
||||||
@import "./extend/widgets";
|
@import "./extend/widgets";
|
||||||
@import "./advanced/database";
|
@import "settings";
|
||||||
@import "./settings";
|
|
||||||
|
|
||||||
@import "./modules/alerts";
|
@import "./modules/alerts";
|
||||||
@import "./modules/selectable";
|
@import "./modules/selectable";
|
||||||
@@ -27,26 +27,29 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.admin {
|
.admin {
|
||||||
background: #fff;
|
.acp-page-container {
|
||||||
font-size: 14px;
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacer * 1.5;
|
||||||
|
padding: $spacer * 1.5;
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
.acp-page-main-header {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
h1 {
|
.settings, .categories, .category, .admins-mods {
|
||||||
font-size: 35px;
|
hr {
|
||||||
}
|
color: $gray-500;
|
||||||
.form-label, .form-check-label {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
.btn {
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
.btn-outline-secondary {
|
|
||||||
color: $gray-700;
|
|
||||||
box-shadow: 0 1px 4px rgba(0, 0, 0, .4) !important;
|
|
||||||
&:hover {
|
|
||||||
background-color: $gray-200 !important;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-control::placeholder, .bootstrap-tagsinput::placeholder {
|
||||||
|
color: $gray-500 !important;
|
||||||
|
}
|
||||||
|
|
||||||
// .floating-button can either be a container or the button itself
|
// .floating-button can either be a container or the button itself
|
||||||
.floating-button {
|
.floating-button {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@@ -73,22 +76,6 @@ body {
|
|||||||
background: $primary !important;
|
background: $primary !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodebb-logo {
|
|
||||||
img {
|
|
||||||
height: 31px;
|
|
||||||
margin-top: -8px;
|
|
||||||
margin-left: -7px;
|
|
||||||
vertical-align: -43%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include box-header-font;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#breadcrumbs {
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin acp-panel-heading() {
|
@mixin acp-panel-heading() {
|
||||||
padding: 7px 14px;
|
padding: 7px 14px;
|
||||||
border: 0;
|
border: 0;
|
||||||
@@ -114,10 +101,6 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-header {
|
|
||||||
@include box-header-font;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-container {
|
.icon-container {
|
||||||
.fa-nbb-none {
|
.fa-nbb-none {
|
||||||
border: 1px dotted black;
|
border: 1px dotted black;
|
||||||
@@ -141,27 +124,6 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-static-top, .navbar-fixed-top {
|
|
||||||
box-shadow: 0px -3px 12px rgba(0, 0, 0, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-header > .navbar-toggle {
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-nav {
|
|
||||||
>li {
|
|
||||||
>#reconnect {
|
|
||||||
color: $gray-700;
|
|
||||||
}
|
|
||||||
|
|
||||||
>#reconnect:focus, >#reconnect:hover {
|
|
||||||
color: $gray-700;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#taskbar {
|
#taskbar {
|
||||||
display: none; /* not sure why I have to do this, but it only seems to show up on prod */
|
display: none; /* not sure why I have to do this, but it only seems to show up on prod */
|
||||||
}
|
}
|
||||||
@@ -172,57 +134,21 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.bootstrap-tagsinput {
|
.bootstrap-tagsinput {
|
||||||
|
box-shadow: $input-box-shadow;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 0;
|
|
||||||
box-shadow: none;
|
|
||||||
padding-left: 0;
|
|
||||||
|
|
||||||
input {
|
input {
|
||||||
width: 100%;
|
font-size: 0.875rem;
|
||||||
margin-left: 1px;
|
width: 64px;
|
||||||
margin-top: 9px;
|
padding: 0;
|
||||||
border-bottom: 1px dotted #ccc !important;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allowing text to the right of an image-type brand
|
.dropdown-left .dropdown-menu {
|
||||||
// See: https://github.com/twbs/bootstrap/commit/8e2348e9eda51296eb680192379ab37f10355ca3
|
--bs-position: start;
|
||||||
.navbar-brand > img {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
}
|
||||||
|
.dropdown-right .dropdown-menu {
|
||||||
.category-settings-form {
|
|
||||||
h3 {
|
|
||||||
margin-top: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-preview {
|
|
||||||
cursor: pointer;
|
|
||||||
width: 100%;
|
|
||||||
height: 100px;
|
|
||||||
text-align: center;
|
|
||||||
color: white;
|
|
||||||
margin-top: 0;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
line-height: 40px;
|
|
||||||
display: inline-block;
|
|
||||||
margin: 35px 5px 0 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-dropdown-container.right .category-dropdown-menu {
|
|
||||||
--bs-position: end;
|
--bs-position: end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,10 +187,6 @@ body {
|
|||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
form small {
|
|
||||||
color: $gray-700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.caret {
|
.caret {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 0;
|
width: 0;
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
.database-info {
|
|
||||||
span {
|
|
||||||
display:inline-block;
|
|
||||||
width:220px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
73
public/scss/admin/common.scss
Normal file
73
public/scss/admin/common.scss
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
|
||||||
|
.form-label {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
font-family: $font-family-base;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-text {
|
||||||
|
font-size: 0.75rem!important;;
|
||||||
|
font-family: $font-family-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tracking-tight { letter-spacing: -0.02em; }
|
||||||
|
|
||||||
|
$btn-ghost-hover-color: mix($light, $dark, 90%);
|
||||||
|
|
||||||
|
@mixin btn-ghost-base {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: ($spacer * 0.5);
|
||||||
|
border-radius: $border-radius-sm;
|
||||||
|
border-width: 1px;
|
||||||
|
border-color: transparent;
|
||||||
|
background-color: transparent;
|
||||||
|
padding: ($spacer * 0.25) ($spacer * 0.5);
|
||||||
|
text-align: left;
|
||||||
|
--bs-text-opacity: 1;
|
||||||
|
color: rgb(73 80 87 / var(--bs-text-opacity));
|
||||||
|
font-family: $font-family-secondary;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover, &.active {
|
||||||
|
background-color: $btn-ghost-hover-color;
|
||||||
|
color: rgb(73 80 87 / var(--bs-text-opacity));
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-ghost {
|
||||||
|
@include btn-ghost-base();
|
||||||
|
line-height: 1.5rem;
|
||||||
|
> i {
|
||||||
|
line-height: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-ghost-sm {
|
||||||
|
@include btn-ghost-base();
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
> i {
|
||||||
|
line-height: 1.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline {
|
||||||
|
@include btn-ghost-base();
|
||||||
|
border-color: $border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline-sm {
|
||||||
|
@include btn-ghost-base();
|
||||||
|
border-color: $border-color;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-basis-md-200 {
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
flex-basis: 200px!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +1,4 @@
|
|||||||
.plugins {
|
.plugins {
|
||||||
padding-left: 0px;
|
|
||||||
|
|
||||||
li {
|
|
||||||
list-style-type: none;
|
|
||||||
background: rgba(64, 64, 64, 0.05);
|
|
||||||
padding: 1em;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
border-left: 5px solid #08c;
|
|
||||||
margin-left: -40px;
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: 16px;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.plugin-list.ui-sortable {
|
.plugin-list.ui-sortable {
|
||||||
li {
|
li {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
#rewards {
|
|
||||||
ul {
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 0px;
|
|
||||||
margin: 0px;
|
|
||||||
|
|
||||||
> li {
|
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
&:last-child {
|
|
||||||
border-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.rewards { width: 100%; }
|
|
||||||
|
|
||||||
.card {
|
|
||||||
border-radius: 2px;
|
|
||||||
border-width: 2px;
|
|
||||||
color: #333;
|
|
||||||
|
|
||||||
&.if-block {
|
|
||||||
border-color: $primary;
|
|
||||||
max-width: 33%;
|
|
||||||
}
|
|
||||||
&.this-block {
|
|
||||||
border-color: $warning;
|
|
||||||
max-width: 33%;
|
|
||||||
}
|
|
||||||
&.then-block {
|
|
||||||
border-color: $success;
|
|
||||||
max-width: 33%;
|
|
||||||
}
|
|
||||||
&.reward-block {
|
|
||||||
border-color: $success;
|
|
||||||
background-color: lighten($success, 15%);
|
|
||||||
color: #fff;
|
|
||||||
a, select, input { color: #fff; }
|
|
||||||
select > option { color: #333; }
|
|
||||||
width: 100%;
|
|
||||||
min-height: 110px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-admin-rewards {
|
|
||||||
#new {
|
|
||||||
bottom: calc(64px + $spacer);
|
|
||||||
background-color: $success;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
21
public/scss/admin/fonts.scss
Normal file
21
public/scss/admin/fonts.scss
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
@use "@fontsource/inter/scss/mixins" as Inter;
|
||||||
|
@use "@fontsource/poppins/scss/mixins" as Poppins;
|
||||||
|
|
||||||
|
$weights: $font-weight-light, $font-weight-normal, $font-weight-semibold, $font-weight-bold;
|
||||||
|
|
||||||
|
@each $weight in $weights {
|
||||||
|
@include Inter.fontFace(
|
||||||
|
$weight: $weight,
|
||||||
|
$display: fallback,
|
||||||
|
$fontDir: "./plugins/core/inter"
|
||||||
|
);
|
||||||
|
@include Poppins.fontFace(
|
||||||
|
$weight: $weight,
|
||||||
|
$display: fallback,
|
||||||
|
$fontDir: "./plugins/core/poppins"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ff-base { font-family: $font-family-base !important; }
|
||||||
|
.ff-sans { font-family: $font-family-sans-serif !important; }
|
||||||
|
.ff-secondary { font-family: $font-family-secondary; }
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
.header {
|
|
||||||
user-select: none;
|
|
||||||
position: relative;
|
|
||||||
background: #333;
|
|
||||||
width: 100%;
|
|
||||||
height: 200px;
|
|
||||||
margin-bottom: 50px;
|
|
||||||
font-size: 16px;
|
|
||||||
|
|
||||||
#main-page-title {
|
|
||||||
position: absolute;
|
|
||||||
left: 48px;
|
|
||||||
bottom: 50px;
|
|
||||||
color: #aaa;
|
|
||||||
font-size: 47px;
|
|
||||||
font-weight: 300;
|
|
||||||
}
|
|
||||||
|
|
||||||
.quick-actions {
|
|
||||||
position: static;
|
|
||||||
padding: 15px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row-reverse;
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
> * {
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .menu-button {
|
|
||||||
margin-right: 0;
|
|
||||||
padding: 0 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alert {
|
|
||||||
font-size: 14px;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
|
|
||||||
&.alert-info {
|
|
||||||
background-color: #eee;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown {
|
|
||||||
margin-right: 0px;
|
|
||||||
|
|
||||||
.dropdown-toggle i {
|
|
||||||
padding: 0 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.fa {
|
|
||||||
line-height: 44px;
|
|
||||||
font-size: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#user_dropdown {
|
|
||||||
font-size: 25px;
|
|
||||||
color: #eee;
|
|
||||||
|
|
||||||
i {
|
|
||||||
margin-top: 12px;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#acp-search {
|
|
||||||
input {
|
|
||||||
padding: 10px 20px;
|
|
||||||
width: 250px;
|
|
||||||
height: 44px;
|
|
||||||
background-color: rgba(0,0,0,.2);
|
|
||||||
border-radius: 3px;
|
|
||||||
box-shadow: none;
|
|
||||||
transition: .4s ease background-color;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
background-color: #eee;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown:not(.open) {
|
|
||||||
&:before {
|
|
||||||
content: '/';
|
|
||||||
border: 1px solid $gray-500;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 0px 6px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 600;
|
|
||||||
pointer-events: none;
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
top: 13px;
|
|
||||||
left: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
content: attr(data-text);
|
|
||||||
position: absolute;
|
|
||||||
top: 13px;
|
|
||||||
left: 3em;
|
|
||||||
font-size: small;
|
|
||||||
font-weight: 600;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
color: transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-match {
|
|
||||||
font-weight: 700;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#main-menu > li {
|
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> ul {
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 0px;
|
|
||||||
position: absolute;
|
|
||||||
bottom: -16px;
|
|
||||||
left: 50px;
|
|
||||||
|
|
||||||
> li {
|
|
||||||
float: left;
|
|
||||||
margin-right: 30px;
|
|
||||||
border-bottom: 4px solid transparent;
|
|
||||||
transition: border-color 150ms linear;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-color: darken($primary, 20%);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
border-color: $primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
> a {
|
|
||||||
color: white;
|
|
||||||
text-transform: uppercase;
|
|
||||||
text-decoration: none;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.plugins-menu {
|
|
||||||
max-height: 50vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +1,20 @@
|
|||||||
div.categories {
|
div.categories {
|
||||||
ul[data-cid] {
|
ul[data-cid] {
|
||||||
user-select: none;
|
|
||||||
list-style-type: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
> li > ul > li {
|
> li > ul > li {
|
||||||
margin-left: 4.5rem;
|
padding-left: 3rem;
|
||||||
}
|
|
||||||
> li > a {
|
|
||||||
margin-left: 4.5rem;
|
|
||||||
}
|
|
||||||
.row {
|
|
||||||
margin-left: -15px;
|
|
||||||
margin-right: -15px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> li li:last-child {
|
|
||||||
.row {
|
|
||||||
border-bottom: 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
> li {
|
> li {
|
||||||
margin: 16px 0 24px 0;
|
|
||||||
|
|
||||||
&.placeholder {
|
&.placeholder {
|
||||||
border: 1px dashed #2196F3;
|
border: 1px dashed #2196F3;
|
||||||
background-color: #E1F5FE;
|
background-color: #E1F5FE;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats {
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
li {
|
|
||||||
min-height: 0;
|
|
||||||
display: inline;
|
|
||||||
margin: 0 16px 0 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.disabled > .category-row {
|
.disabled > .category-row {
|
||||||
|
.icon, .title, .description {
|
||||||
.icon, .category-header, .description {
|
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,34 +26,15 @@ div.categories {
|
|||||||
.toggle {
|
.toggle {
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
border-radius: 50%;
|
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
text-align: center;
|
|
||||||
vertical-align: bottom;
|
|
||||||
background-size: cover;
|
|
||||||
float: left;
|
|
||||||
margin-right: 0px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
.fa {
|
|
||||||
font-size: 85%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.information {
|
.information {
|
||||||
cursor: move;
|
cursor: move;
|
||||||
padding-left: 3rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-header {
|
.children-placeholder {
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.children-placeholder{
|
|
||||||
min-height: 20px;
|
min-height: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,5 @@
|
|||||||
.group {
|
|
||||||
[component="groups/members"] {
|
|
||||||
padding: 0;
|
|
||||||
tbody {
|
|
||||||
max-height: 500px;
|
|
||||||
display: block;
|
|
||||||
overflow-y: auto;
|
|
||||||
.member-name {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#group-icon {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.groups {
|
.groups {
|
||||||
#group-search {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.groups-list {
|
.groups-list {
|
||||||
p {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
td {
|
td {
|
||||||
max-width: 350px;
|
max-width: 350px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,12 @@
|
|||||||
.tags {
|
.tags {
|
||||||
.tag-list {
|
.tag-list {
|
||||||
h3 {
|
|
||||||
min-width: 225px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag-row {
|
.tag-row {
|
||||||
padding: 0.5rem;
|
|
||||||
float: left;
|
float: left;
|
||||||
margin-left: 0.5rem;
|
|
||||||
|
|
||||||
.tag-item {
|
|
||||||
cursor: pointer;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.ui-selected {
|
&.ui-selected {
|
||||||
background: lighten($success, 25%);
|
background: lighten($success, 25%);
|
||||||
|
border-radius: $border-radius-sm;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.ui-selecting {
|
&.ui-selecting {
|
||||||
@@ -24,8 +14,4 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag-topic-count {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,191 +1,12 @@
|
|||||||
#mobile-menu {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 991px) {
|
@media (max-width: 991px) {
|
||||||
body {
|
body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
overflow-y: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
#panel {
|
|
||||||
background-color: inherit;
|
|
||||||
min-height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
body, #panel, .slideout-menu {
|
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
height: 58px;
|
|
||||||
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.26);
|
|
||||||
position: fixed;
|
|
||||||
top: 0px;
|
|
||||||
z-index: 5;
|
|
||||||
|
|
||||||
#main-page-title {
|
|
||||||
bottom: -31px;
|
|
||||||
font-size: 20px;
|
|
||||||
color: #FFF;
|
|
||||||
left: 52px;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
#main-menu {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#mobile-menu {
|
|
||||||
width: 22px;
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
margin-right: 10px;
|
|
||||||
margin-left: -5px;
|
|
||||||
outline: none !important;
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
top: 22px;
|
|
||||||
left: 22px;
|
|
||||||
|
|
||||||
.bar {
|
|
||||||
width: 100%;
|
|
||||||
height: 2px;
|
|
||||||
background: #fff;
|
|
||||||
margin-bottom: 3px;
|
|
||||||
border-radius: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#menu {
|
|
||||||
background-color: #1D1F20;
|
|
||||||
background-image: linear-gradient(145deg, #1D1F20, #404348);
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #fff;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-header-title {
|
|
||||||
font-weight: 400;
|
|
||||||
letter-spacing: 0.5px;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-section {
|
|
||||||
margin: 25px 0;
|
|
||||||
|
|
||||||
&.quick-actions {
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
.button-group {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alert {
|
|
||||||
border-radius: 0;
|
|
||||||
|
|
||||||
.span {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-section-title {
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: #85888d;
|
|
||||||
font-weight: 200;
|
|
||||||
font-size: 13px;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
padding: 0 20px;
|
|
||||||
margin:0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-section-list {
|
|
||||||
padding: 0;
|
|
||||||
margin: 10px 0;
|
|
||||||
list-style: none;
|
|
||||||
|
|
||||||
a {
|
|
||||||
display: block;
|
|
||||||
padding: 10px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
background-color: rgba(255, 255, 255, 0.1);
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#panel {
|
|
||||||
background: white;
|
|
||||||
min-height: 100%;
|
|
||||||
padding-top: 80px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slideout-menu {
|
|
||||||
position: fixed;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 0;
|
|
||||||
width: 256px;
|
|
||||||
overflow-y: auto;
|
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.slideout-panel {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slideout-open,
|
|
||||||
.slideout-open body,
|
|
||||||
.slideout-open .slideout-panel {
|
|
||||||
overflow: hidden;
|
|
||||||
overflow-y: hidden !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slideout-open .slideout-menu {
|
|
||||||
display: block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slideout-open {
|
|
||||||
overflow-y: hidden;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
overflow-y: scroll;
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.content-header, .settings-header {
|
|
||||||
font-size: 200%;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
margin-left: -2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.dropdown-menu {
|
|
||||||
margin-top: -35px;
|
|
||||||
margin-right: -2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,9 @@
|
|||||||
#acp-search {
|
.acp-search {
|
||||||
.dropdown-menu {
|
.dropdown-menu {
|
||||||
max-height: 75vh;
|
max-height: 75vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
> li > a {
|
> li > a {
|
||||||
// &.focus {
|
|
||||||
// &:extend(.dropdown-menu>li>a:focus);
|
|
||||||
// }
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|||||||
62
public/scss/admin/overrides.scss
Normal file
62
public/scss/admin/overrides.scss
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
$white: #fff !default;
|
||||||
|
$gray-100: #f8f9fa !default;
|
||||||
|
$gray-200: #e9ecef !default;
|
||||||
|
$gray-300: #dee2e6 !default;
|
||||||
|
$gray-400: #ced4da !default;
|
||||||
|
$gray-500: #adb5bd !default;
|
||||||
|
$gray-600: #6c757d !default;
|
||||||
|
$gray-700: #495057 !default;
|
||||||
|
$gray-800: #343a40 !default;
|
||||||
|
$gray-900: #212529 !default;
|
||||||
|
$black: #000 !default;
|
||||||
|
|
||||||
|
$blue: #0d6efd !default;
|
||||||
|
$red: #dc3545 !default;
|
||||||
|
$yellow: #ffc107 !default;
|
||||||
|
$green: #198754 !default;
|
||||||
|
$cyan: #0dcaf0 !default;
|
||||||
|
|
||||||
|
$body-color: $gray-800;
|
||||||
|
$text-muted: $gray-600 !default;
|
||||||
|
|
||||||
|
// Custom fonts
|
||||||
|
$font-family-sans-serif: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||||
|
|
||||||
|
$font-family-secondary: "Poppins", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !default;
|
||||||
|
$font-weight-semibold: 500 !default;
|
||||||
|
$font-size-base: 1rem !default;
|
||||||
|
|
||||||
|
$link-decoration: none;
|
||||||
|
$link-hover-decoration: underline;
|
||||||
|
|
||||||
|
// options
|
||||||
|
$enable-gradients: false;
|
||||||
|
|
||||||
|
// no caret on dropdown-toggle
|
||||||
|
$enable-caret: false;
|
||||||
|
|
||||||
|
// disable smooth scroll, this makes window.scrollTo(0,0) in ajaxify.js take x milliseconds
|
||||||
|
$enable-smooth-scroll: false;
|
||||||
|
|
||||||
|
$enable-shadows: true;
|
||||||
|
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
$input-btn-padding-y: .4rem !default;
|
||||||
|
$input-btn-padding-x: 1rem !default;
|
||||||
|
|
||||||
|
// Forms
|
||||||
|
|
||||||
|
$input-padding-y: 0.5rem !default;
|
||||||
|
$input-padding-x: 0.75rem !default;
|
||||||
|
// $input-padding-y-sm: 0 !default;
|
||||||
|
// $input-padding-x-sm: 0 !default;
|
||||||
|
// $input-padding-y-lg: ($font-size-base * 1.25) !default;
|
||||||
|
// $input-padding-x-lg: 0 !default;
|
||||||
|
|
||||||
|
$input-btn-focus-color: #c29ffa80 !default;
|
||||||
|
$input-border-radius: 0.25rem !default;
|
||||||
|
$input-focus-border-color: #c29ffa80 !default;
|
||||||
|
// change inset shadow to outset
|
||||||
|
$box-shadow-inset: 0 1px 2px rgba($black, .075) !default;
|
||||||
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
.settings {
|
|
||||||
.section-content {
|
|
||||||
border-left: 3px solid $primary;
|
|
||||||
|
|
||||||
ul {
|
|
||||||
list-style-type: none;
|
|
||||||
font-size: 16px;
|
|
||||||
padding-left: 20px;
|
|
||||||
li:not(:last-child) {
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
&:hover{
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
13
public/scss/admin/sidebar.scss
Normal file
13
public/scss/admin/sidebar.scss
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#sidebar-left, #offcanvas {
|
||||||
|
.btn-ghost, .btn-ghost-sm {
|
||||||
|
i {
|
||||||
|
color: $gray-500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion-body {
|
||||||
|
.btn-ghost-sm {
|
||||||
|
padding-left: 38px!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
// system font family
|
|
||||||
// based on those in [bootstrap@5.0.0-alpha1](https://github.com/twbs/bootstrap/blob/b531bda07cbea2e124194aefe3b8597b3ac2578e/scss/_variables.scss#L386)
|
|
||||||
// and [wordpress admin](https://core.trac.wordpress.org/browser/trunk/src/wp-admin/css/common.css?rev=47835#L220)
|
|
||||||
// system-ui : supported by the latest browsers for this very purpose
|
|
||||||
// apple-system, BlinkMacSystemFont : iOS and MacOS
|
|
||||||
// "Segoe UI" : Windows Vista, 7, 8, 10
|
|
||||||
// Roboto : Android 4.0+
|
|
||||||
// Oxygen-Sans : KDE
|
|
||||||
// Ubuntu : Ubuntu
|
|
||||||
// Cantarell : GNOME
|
|
||||||
// "Helvetica Neue" : Mac OS X
|
|
||||||
// Helvetica : backup, better looking than Arial
|
|
||||||
// Arial : backup
|
|
||||||
// "Noto Sans" : broader language support on Android
|
|
||||||
// sans-serif : whatever the browser can give us
|
|
||||||
// "Apple Color Emoji" : Emoji on iOS and MacOS
|
|
||||||
// "Segoe UI Emoji", "Segoe UI Symbol" : Emoji on Windows
|
|
||||||
// "Noto Color Emoji" : Emoji on Android
|
|
||||||
$font-family-system: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
||||||
$font-family-sans-serif: $font-family-system;
|
|
||||||
$font-size-base: 0.875rem!default;
|
|
||||||
|
|
||||||
$body-color: #666!default;
|
|
||||||
$light: #f5f5f5;
|
|
||||||
|
|
||||||
// options
|
|
||||||
$enable-gradients: false;
|
|
||||||
// no caret on dropdown-toggle
|
|
||||||
$enable-caret: false;
|
|
||||||
|
|
||||||
$font-size-base: 1rem !default;
|
|
||||||
$font-weight-base: 400 !default;
|
|
||||||
|
|
||||||
// Buttons
|
|
||||||
$input-btn-padding-y: .4rem !default;
|
|
||||||
$input-btn-padding-x: 1rem !default;
|
|
||||||
|
|
||||||
// Forms
|
|
||||||
|
|
||||||
$input-padding-y: 0.4rem !default;
|
|
||||||
$input-padding-x: 0 !default;
|
|
||||||
$input-padding-y-sm: 0 !default;
|
|
||||||
$input-padding-x-sm: 0 !default;
|
|
||||||
$input-padding-y-lg: ($font-size-base * 1.25) !default;
|
|
||||||
$input-padding-x-lg: 0 !default;
|
|
||||||
@@ -42,9 +42,17 @@ app.onDomReady();
|
|||||||
}
|
}
|
||||||
|
|
||||||
require(['hooks'], (hooks) => {
|
require(['hooks'], (hooks) => {
|
||||||
hooks.on('action:ajaxify.end', () => {
|
hooks.on('action:ajaxify.end', (data) => {
|
||||||
|
updatePageTitle(data.url);
|
||||||
|
setupRestartLinks();
|
||||||
showCorrectNavTab();
|
showCorrectNavTab();
|
||||||
startLogoutTimer();
|
startLogoutTimer();
|
||||||
|
|
||||||
|
$('[data-bs-toggle="tooltip"]').tooltip({
|
||||||
|
animation: false,
|
||||||
|
container: '#content',
|
||||||
|
});
|
||||||
|
|
||||||
if ($('.settings').length) {
|
if ($('.settings').length) {
|
||||||
require(['admin/settings'], function (Settings) {
|
require(['admin/settings'], function (Settings) {
|
||||||
Settings.prepare();
|
Settings.prepare();
|
||||||
@@ -52,21 +60,35 @@ app.onDomReady();
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
hooks.on('action:ajaxify.start', function () {
|
||||||
|
require(['bootstrap'], function (boostrap) {
|
||||||
|
const offcanvas = boostrap.Offcanvas.getInstance('#offcanvas');
|
||||||
|
if (offcanvas) {
|
||||||
|
offcanvas.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function showCorrectNavTab() {
|
function showCorrectNavTab() {
|
||||||
// show correct tab if url has #
|
const accordionEl = $('[component="acp/accordion"]');
|
||||||
if (window.location.hash) {
|
let pathname = window.location.pathname;
|
||||||
$('.nav-pills a[href="' + window.location.hash + '"]').tab('show');
|
if (pathname === '/admin') {
|
||||||
|
pathname = '/admin/dashboard';
|
||||||
|
}
|
||||||
|
const selectedButton = accordionEl.find(`a[href="${pathname}"]`);
|
||||||
|
if (selectedButton.length) {
|
||||||
|
accordionEl.find('a').removeClass('active');
|
||||||
|
accordionEl.find('.accordion-collapse').removeClass('show');
|
||||||
|
selectedButton.addClass('active');
|
||||||
|
selectedButton.parents('.accordion-collapse').addClass('show');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
if (!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
|
require(['admin/modules/search'], function (search) {
|
||||||
require(['admin/modules/search'], function (search) {
|
search.init();
|
||||||
search.init();
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$('[component="logout"]').on('click', function () {
|
$('[component="logout"]').on('click', function () {
|
||||||
require(['logout'], function (logout) {
|
require(['logout'], function (logout) {
|
||||||
@@ -75,16 +97,25 @@ app.onDomReady();
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
configureSlidemenu();
|
|
||||||
setupNProgress();
|
setupNProgress();
|
||||||
|
fixAccordionIds();
|
||||||
});
|
});
|
||||||
|
|
||||||
$(window).on('action:ajaxify.contentLoaded', function (ev, data) {
|
function fixAccordionIds() {
|
||||||
selectMenuItem(data.url);
|
// fix mobile accordion, so it doesn't have same ids as desktop
|
||||||
setupRestartLinks();
|
// the same accordion partial is used in both places
|
||||||
require('material-design-lite');
|
const offcanvasAccordion = $('#offcanvas #accordionACP');
|
||||||
componentHandler.upgradeDom();
|
offcanvasAccordion.attr('id', 'accordionACP-offcanvas');
|
||||||
});
|
offcanvasAccordion.find('[data-bs-target]').each((i, el) => {
|
||||||
|
$(el).attr('data-bs-target', $(el).attr('data-bs-target') + '-offcanvas');
|
||||||
|
});
|
||||||
|
offcanvasAccordion.find('[data-bs-parent]').each((i, el) => {
|
||||||
|
$(el).attr('data-bs-parent', '#accordionACP-offcanvas');
|
||||||
|
});
|
||||||
|
offcanvasAccordion.find('.accordion-collapse').each((i, el) => {
|
||||||
|
$(el).attr('id', $(el).attr('id') + '-offcanvas');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function setupNProgress() {
|
function setupNProgress() {
|
||||||
require(['nprogress', 'hooks'], function (NProgress, hooks) {
|
require(['nprogress', 'hooks'], function (NProgress, hooks) {
|
||||||
@@ -98,7 +129,7 @@ app.onDomReady();
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectMenuItem(url) {
|
function updatePageTitle(url) {
|
||||||
require(['translator'], function (translator) {
|
require(['translator'], function (translator) {
|
||||||
url = url
|
url = url
|
||||||
.replace(/\/\d+$/, '')
|
.replace(/\/\d+$/, '')
|
||||||
@@ -113,17 +144,8 @@ app.onDomReady();
|
|||||||
url = [config.relative_path, url].join('/');
|
url = [config.relative_path, url].join('/');
|
||||||
let fallback;
|
let fallback;
|
||||||
|
|
||||||
$('#main-menu li').removeClass('active');
|
$(`[component="acp/accordion"] a[href="${url}"]`).each(function () {
|
||||||
$('#main-menu a').removeClass('active').filter('[href="' + url + '"]').each(function () {
|
fallback = $(this).text();
|
||||||
const menu = $(this);
|
|
||||||
if (menu.parent().attr('data-link')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
menu
|
|
||||||
.parent().addClass('active')
|
|
||||||
.parents('.menu-item').addClass('active');
|
|
||||||
fallback = menu.text();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let mainTitle;
|
let mainTitle;
|
||||||
@@ -152,9 +174,6 @@ app.onDomReady();
|
|||||||
translator.translate(pageTitle, function (title) {
|
translator.translate(pageTitle, function (title) {
|
||||||
document.title = title.replace(/>/g, '>');
|
document.title = title.replace(/>/g, '>');
|
||||||
});
|
});
|
||||||
translator.translate(mainTitle, function (text) {
|
|
||||||
$('#main-page-title').text(text);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +183,7 @@ app.onDomReady();
|
|||||||
// otherwise it can be unloaded when rebuild & restart is run
|
// otherwise it can be unloaded when rebuild & restart is run
|
||||||
// the client can't fetch the template file, resulting in an error
|
// the client can't fetch the template file, resulting in an error
|
||||||
benchpress.render('partials/toast', {}).then(function () {
|
benchpress.render('partials/toast', {}).then(function () {
|
||||||
$('.rebuild-and-restart').off('click').on('click', function () {
|
$('[component="rebuild-and-restart"]').off('click').on('click', function () {
|
||||||
bootbox.confirm('[[admin/admin:alert.confirm-rebuild-and-restart]]', function (confirm) {
|
bootbox.confirm('[[admin/admin:alert.confirm-rebuild-and-restart]]', function (confirm) {
|
||||||
if (confirm) {
|
if (confirm) {
|
||||||
instance.rebuildAndRestart();
|
instance.rebuildAndRestart();
|
||||||
@@ -172,7 +191,7 @@ app.onDomReady();
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.restart').off('click').on('click', function () {
|
$('[component="restart"]').off('click').on('click', function () {
|
||||||
bootbox.confirm('[[admin/admin:alert.confirm-restart]]', function (confirm) {
|
bootbox.confirm('[[admin/admin:alert.confirm-restart]]', function (confirm) {
|
||||||
if (confirm) {
|
if (confirm) {
|
||||||
instance.restart();
|
instance.restart();
|
||||||
@@ -182,62 +201,4 @@ app.onDomReady();
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function configureSlidemenu() {
|
|
||||||
require(['slideout'], function (Slideout) {
|
|
||||||
let env = utils.findBootstrapEnvironment();
|
|
||||||
|
|
||||||
const slideout = new Slideout({
|
|
||||||
panel: document.getElementById('panel'),
|
|
||||||
menu: document.getElementById('menu'),
|
|
||||||
padding: 256,
|
|
||||||
tolerance: 70,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (env === 'md' || env === 'lg') {
|
|
||||||
slideout.disableTouch();
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#mobile-menu').on('click', function () {
|
|
||||||
slideout.toggle();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#menu a').on('click', function () {
|
|
||||||
slideout.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
$(window).on('resize', function () {
|
|
||||||
slideout.close();
|
|
||||||
|
|
||||||
env = utils.findBootstrapEnvironment();
|
|
||||||
if (['xxl', 'xl', 'lg'].includes(env)) {
|
|
||||||
slideout.disableTouch();
|
|
||||||
$('#header').css({
|
|
||||||
position: 'relative',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
slideout.enableTouch();
|
|
||||||
$('#header').css({
|
|
||||||
position: 'fixed',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function onOpeningMenu() {
|
|
||||||
$('#header').css({
|
|
||||||
top: ($('#panel').position().top * -1) + 'px',
|
|
||||||
position: 'absolute',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
slideout.on('open', onOpeningMenu);
|
|
||||||
|
|
||||||
slideout.on('close', function () {
|
|
||||||
$('#header').css({
|
|
||||||
top: '0px',
|
|
||||||
position: 'fixed',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}());
|
}());
|
||||||
|
|||||||
@@ -43,10 +43,6 @@ define('admin/dashboard', [
|
|||||||
|
|
||||||
isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
||||||
|
|
||||||
$('[data-bs-toggle="tooltip"]').tooltip({
|
|
||||||
animation: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
setupRealtimeButton();
|
setupRealtimeButton();
|
||||||
setupGraphs(function () {
|
setupGraphs(function () {
|
||||||
socket.emit('admin.rooms.getAll', Admin.updateRoomUsage);
|
socket.emit('admin.rooms.getAll', Admin.updateRoomUsage);
|
||||||
@@ -68,19 +64,19 @@ define('admin/dashboard', [
|
|||||||
|
|
||||||
const html = '<div class="text-center float-start">' +
|
const html = '<div class="text-center float-start">' +
|
||||||
'<span class="formatted-number">' + data.onlineRegisteredCount + '</span>' +
|
'<span class="formatted-number">' + data.onlineRegisteredCount + '</span>' +
|
||||||
'<div class="stat">[[admin/dashboard:active-users.users]]</div>' +
|
'<div class="stat text-nowrap">[[admin/dashboard:active-users.users]]</div>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div class="text-center float-start">' +
|
'<div class="text-center float-start">' +
|
||||||
'<span class="formatted-number">' + data.onlineGuestCount + '</span>' +
|
'<span class="formatted-number">' + data.onlineGuestCount + '</span>' +
|
||||||
'<div class="stat">[[admin/dashboard:active-users.guests]]</div>' +
|
'<div class="stat text-nowrap">[[admin/dashboard:active-users.guests]]</div>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div class="text-center float-start">' +
|
'<div class="text-center float-start">' +
|
||||||
'<span class="formatted-number">' + (data.onlineRegisteredCount + data.onlineGuestCount) + '</span>' +
|
'<span class="formatted-number">' + (data.onlineRegisteredCount + data.onlineGuestCount) + '</span>' +
|
||||||
'<div class="stat">[[admin/dashboard:active-users.total]]</div>' +
|
'<div class="stat text-nowrap">[[admin/dashboard:active-users.total]]</div>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div class="text-center float-start">' +
|
'<div class="text-center float-start">' +
|
||||||
'<span class="formatted-number">' + data.socketCount + '</span>' +
|
'<span class="formatted-number">' + data.socketCount + '</span>' +
|
||||||
'<div class="stat">[[admin/dashboard:active-users.connections]]</div>' +
|
'<div class="stat text-nowrap">[[admin/dashboard:active-users.connections]]</div>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
|
|
||||||
updateRegisteredGraph(data.onlineRegisteredCount, data.onlineGuestCount);
|
updateRegisteredGraph(data.onlineRegisteredCount, data.onlineGuestCount);
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ define('admin/extend/plugins', [
|
|||||||
pluginsList.on('click', 'button[data-action="toggleActive"]', function () {
|
pluginsList.on('click', 'button[data-action="toggleActive"]', function () {
|
||||||
const pluginEl = $(this).parents('li');
|
const pluginEl = $(this).parents('li');
|
||||||
pluginID = pluginEl.attr('data-plugin-id');
|
pluginID = pluginEl.attr('data-plugin-id');
|
||||||
const btn = $('[id="' + pluginID + '"] [data-action="toggleActive"]');
|
// const btn = $('[id="' + pluginID + '"] [data-action="toggleActive"]');
|
||||||
|
const btn = $(this);
|
||||||
|
|
||||||
const pluginData = ajaxify.data.installed[pluginEl.attr('data-plugin-index')];
|
const pluginData = ajaxify.data.installed[pluginEl.attr('data-plugin-index')];
|
||||||
|
|
||||||
@@ -40,30 +41,28 @@ define('admin/extend/plugins', [
|
|||||||
if (err) {
|
if (err) {
|
||||||
return alerts.error(err);
|
return alerts.error(err);
|
||||||
}
|
}
|
||||||
translator.translate('<i class="fa fa-power-off"></i> [[admin/extend/plugins:plugin-item.' + (status.active ? 'deactivate' : 'activate') + ']]', function (buttonText) {
|
btn.siblings('[data-action="toggleActive"]').removeClass('hidden');
|
||||||
btn.html(buttonText);
|
btn.addClass('hidden');
|
||||||
btn.toggleClass('btn-warning', status.active).toggleClass('btn-success', !status.active);
|
|
||||||
|
|
||||||
// clone it to active plugins tab
|
// clone it to active plugins tab
|
||||||
if (status.active && !$('#active [id="' + pluginID + '"]').length) {
|
if (status.active && !$('#active [id="' + pluginID + '"]').length) {
|
||||||
$('#active ul').prepend(pluginEl.clone(true));
|
$('#active ul').prepend(pluginEl.clone(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle active state in template data
|
// Toggle active state in template data
|
||||||
pluginData.active = !pluginData.active;
|
pluginData.active = !pluginData.active;
|
||||||
|
|
||||||
alerts.alert({
|
alerts.alert({
|
||||||
alert_id: 'plugin_toggled',
|
alert_id: 'plugin_toggled',
|
||||||
title: '[[admin/extend/plugins:alert.' + (status.active ? 'enabled' : 'disabled') + ']]',
|
title: '[[admin/extend/plugins:alert.' + (status.active ? 'enabled' : 'disabled') + ']]',
|
||||||
message: '[[admin/extend/plugins:alert.' + (status.active ? 'activate-success' : 'deactivate-success') + ']]',
|
message: '[[admin/extend/plugins:alert.' + (status.active ? 'activate-success' : 'deactivate-success') + ']]',
|
||||||
type: status.active ? 'warning' : 'success',
|
type: status.active ? 'warning' : 'success',
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
clickfn: function () {
|
clickfn: function () {
|
||||||
require(['admin/modules/instance'], function (instance) {
|
require(['admin/modules/instance'], function (instance) {
|
||||||
instance.rebuildAndRestart();
|
instance.rebuildAndRestart();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,16 +95,16 @@ define('admin/extend/rewards', ['alerts'], function (alerts) {
|
|||||||
html += '<label for="' + input.name + '">' + input.label + '<br />';
|
html += '<label for="' + input.name + '">' + input.label + '<br />';
|
||||||
switch (input.type) {
|
switch (input.type) {
|
||||||
case 'select':
|
case 'select':
|
||||||
html += '<select class="form-control" name="' + input.name + '">';
|
html += '<select class="form-select form-select-sm" name="' + input.name + '">';
|
||||||
input.values.forEach(function (value) {
|
input.values.forEach(function (value) {
|
||||||
html += '<option value="' + value.value + '">' + value.name + '</option>';
|
html += '<option value="' + value.value + '">' + value.name + '</option>';
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'text':
|
case 'text':
|
||||||
html += '<input type="text" class="form-control" name="' + input.name + '" />';
|
html += '<input type="text" class="form-control form-control-sm" name="' + input.name + '" />';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
html += '</label><br />';
|
html += '</label>';
|
||||||
});
|
});
|
||||||
|
|
||||||
div.html(html);
|
div.html(html);
|
||||||
|
|||||||
@@ -15,12 +15,14 @@ define('admin/manage/categories', [
|
|||||||
let sortables;
|
let sortables;
|
||||||
|
|
||||||
Categories.init = function () {
|
Categories.init = function () {
|
||||||
categorySelector.init($('.category [component="category-selector"]'), {
|
categorySelector.init($('[component="category-selector"]'), {
|
||||||
parentCid: ajaxify.data.selectedCategory ? ajaxify.data.selectedCategory.cid : 0,
|
parentCid: ajaxify.data.selectedCategory ? ajaxify.data.selectedCategory.cid : 0,
|
||||||
onSelect: function (selectedCategory) {
|
onSelect: function (selectedCategory) {
|
||||||
ajaxify.go('/admin/manage/categories' + (selectedCategory.cid ? '?cid=' + selectedCategory.cid : ''));
|
ajaxify.go('/admin/manage/categories' + (selectedCategory.cid ? '?cid=' + selectedCategory.cid : ''));
|
||||||
},
|
},
|
||||||
|
cacheList: false,
|
||||||
localCategories: [],
|
localCategories: [],
|
||||||
|
template: 'admin/partials/category/selector-dropdown-right',
|
||||||
});
|
});
|
||||||
Categories.render(ajaxify.data.categoriesTree);
|
Categories.render(ajaxify.data.categoriesTree);
|
||||||
|
|
||||||
@@ -74,12 +76,14 @@ define('admin/manage/categories', [
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#collapse-all').on('click', function () {
|
$('#toggle-collapse-all').on('click', function () {
|
||||||
toggleAll(false);
|
const $this = $(this);
|
||||||
});
|
const isCollapsed = parseInt($this.attr('data-collapsed'), 10) === 1;
|
||||||
|
toggleAll(isCollapsed);
|
||||||
$('#expand-all').on('click', function () {
|
$this.attr('data-collapsed', isCollapsed ? 0 : 1)
|
||||||
toggleAll(true);
|
.translateText(isCollapsed ?
|
||||||
|
'[[admin/manage/categories:collapse-all]]' :
|
||||||
|
'[[admin/manage/categories:expand-all]]');
|
||||||
});
|
});
|
||||||
|
|
||||||
function toggleAll(expand) {
|
function toggleAll(expand) {
|
||||||
@@ -96,7 +100,7 @@ define('admin/manage/categories', [
|
|||||||
message: html,
|
message: html,
|
||||||
buttons: {
|
buttons: {
|
||||||
save: {
|
save: {
|
||||||
label: '[[global:save]]',
|
label: '[[global:create]]',
|
||||||
className: 'btn-primary',
|
className: 'btn-primary',
|
||||||
callback: submit,
|
callback: submit,
|
||||||
},
|
},
|
||||||
@@ -110,6 +114,7 @@ define('admin/manage/categories', [
|
|||||||
icon: 'fa-none',
|
icon: 'fa-none',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
template: 'admin/partials/category/selector-dropdown-left',
|
||||||
};
|
};
|
||||||
const parentSelector = categorySelector.init(modal.find('#parentCidGroup [component="category-selector"]'), options);
|
const parentSelector = categorySelector.init(modal.find('#parentCidGroup [component="category-selector"]'), options);
|
||||||
const cloneFromSelector = categorySelector.init(modal.find('#cloneFromCidGroup [component="category-selector"]'), options);
|
const cloneFromSelector = categorySelector.init(modal.find('#cloneFromCidGroup [component="category-selector"]'), options);
|
||||||
@@ -177,7 +182,7 @@ define('admin/manage/categories', [
|
|||||||
};
|
};
|
||||||
|
|
||||||
Categories.toggle = function (cids, disabled) {
|
Categories.toggle = function (cids, disabled) {
|
||||||
const listEl = document.querySelector('.categories ul');
|
const listEl = document.querySelector('.categories [data-cid="0"]');
|
||||||
Promise.all(cids.map(cid => api.put('/categories/' + cid, {
|
Promise.all(cids.map(cid => api.put('/categories/' + cid, {
|
||||||
disabled: disabled ? 1 : 0,
|
disabled: disabled ? 1 : 0,
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
@@ -214,14 +219,14 @@ define('admin/manage/categories', [
|
|||||||
if (oldParentCid !== newParentCid) {
|
if (oldParentCid !== newParentCid) {
|
||||||
const toggle = document.querySelector(`.categories li[data-cid="${newParentCid}"] .toggle`);
|
const toggle = document.querySelector(`.categories li[data-cid="${newParentCid}"] .toggle`);
|
||||||
if (toggle) {
|
if (toggle) {
|
||||||
toggle.classList.toggle('hide', false);
|
toggle.classList.toggle('invisible', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const children = document.querySelectorAll(`.categories li[data-cid="${oldParentCid}"] ul[data-cid] li[data-cid]`);
|
const children = document.querySelectorAll(`.categories li[data-cid="${oldParentCid}"] ul[data-cid] li[data-cid]`);
|
||||||
if (!children.length) {
|
if (!children.length) {
|
||||||
const toggle = document.querySelector(`.categories li[data-cid="${oldParentCid}"] .toggle`);
|
const toggle = document.querySelector(`.categories li[data-cid="${oldParentCid}"] .toggle`);
|
||||||
if (toggle) {
|
if (toggle) {
|
||||||
toggle.classList.toggle('hide', true);
|
toggle.classList.toggle('invisible', true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +283,7 @@ define('admin/manage/categories', [
|
|||||||
// Disable expand toggle
|
// Disable expand toggle
|
||||||
if (!categories.length) {
|
if (!categories.length) {
|
||||||
const toggleEl = container.get(0).querySelector('.toggle');
|
const toggleEl = container.get(0).querySelector('.toggle');
|
||||||
toggleEl.classList.toggle('hide', true);
|
toggleEl.classList.toggle('invisible', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle and children categories in this level have
|
// Handle and children categories in this level have
|
||||||
|
|||||||
@@ -14,23 +14,51 @@ define('admin/manage/category', [
|
|||||||
let updateHash = {};
|
let updateHash = {};
|
||||||
|
|
||||||
Category.init = function () {
|
Category.init = function () {
|
||||||
$('#category-settings select').each(function () {
|
const categorySettings = $('#category-settings');
|
||||||
|
const previewEl = $('[component="category/preview"]');
|
||||||
|
categorySettings.find('select').each(function () {
|
||||||
const $this = $(this);
|
const $this = $(this);
|
||||||
$this.val($this.attr('data-value'));
|
$this.val($this.attr('data-value'));
|
||||||
});
|
});
|
||||||
|
|
||||||
categorySelector.init($('[component="category-selector"]'), {
|
// category switcher
|
||||||
|
categorySelector.init($('[component="settings/main/header"] [component="category-selector"]'), {
|
||||||
onSelect: function (selectedCategory) {
|
onSelect: function (selectedCategory) {
|
||||||
ajaxify.go('admin/manage/categories/' + selectedCategory.cid);
|
ajaxify.go('admin/manage/categories/' + selectedCategory.cid);
|
||||||
},
|
},
|
||||||
|
cacheList: false,
|
||||||
showLinks: true,
|
showLinks: true,
|
||||||
|
template: 'admin/partials/category/selector-dropdown-right',
|
||||||
|
});
|
||||||
|
|
||||||
|
// parent selector
|
||||||
|
categorySelector.init($('#parent-category-selector [component="category-selector"]'), {
|
||||||
|
onSelect: function (selectedCategory) {
|
||||||
|
const parentCidInput = $('#parent-cid');
|
||||||
|
parentCidInput.val(selectedCategory.cid);
|
||||||
|
modified(parentCidInput[0]);
|
||||||
|
},
|
||||||
|
selectedCategory: ajaxify.data.category.parent, // switch selection to parent
|
||||||
|
localCategories: [
|
||||||
|
{
|
||||||
|
cid: 0,
|
||||||
|
name: '[[admin/manage/categories:parent-category-none]]',
|
||||||
|
icon: 'fa-list',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
cacheList: false,
|
||||||
|
showLinks: true,
|
||||||
|
template: 'admin/partials/category/selector-dropdown-right',
|
||||||
});
|
});
|
||||||
|
|
||||||
handleTags();
|
handleTags();
|
||||||
|
|
||||||
$('#category-settings input, #category-settings select, #category-settings textarea').on('change', function (ev) {
|
categorySettings.find('input, select, textarea').on('change', function (ev) {
|
||||||
modified(ev.target);
|
modified(ev.target);
|
||||||
});
|
});
|
||||||
|
$('[type="checkbox"]').on('change', function () {
|
||||||
|
modified($(this));
|
||||||
|
});
|
||||||
|
|
||||||
$('[data-name="imageClass"]').on('change', function () {
|
$('[data-name="imageClass"]').on('change', function () {
|
||||||
$('.category-preview').css('background-size', $(this).val());
|
$('.category-preview').css('background-size', $(this).val());
|
||||||
@@ -38,7 +66,6 @@ define('admin/manage/category', [
|
|||||||
|
|
||||||
$('[data-name="bgColor"], [data-name="color"]').on('input', function () {
|
$('[data-name="bgColor"], [data-name="color"]').on('input', function () {
|
||||||
const $inputEl = $(this);
|
const $inputEl = $(this);
|
||||||
const previewEl = $inputEl.parents('[data-cid]').find('.category-preview');
|
|
||||||
if ($inputEl.attr('data-name') === 'bgColor') {
|
if ($inputEl.attr('data-name') === 'bgColor') {
|
||||||
previewEl.css('background-color', $inputEl.val());
|
previewEl.css('background-color', $inputEl.val());
|
||||||
} else if ($inputEl.attr('data-name') === 'color') {
|
} else if ($inputEl.attr('data-name') === 'color') {
|
||||||
@@ -171,56 +198,41 @@ define('admin/manage/category', [
|
|||||||
params: { cid: cid },
|
params: { cid: cid },
|
||||||
}, function (imageUrlOnServer) {
|
}, function (imageUrlOnServer) {
|
||||||
$('#category-image').val(imageUrlOnServer);
|
$('#category-image').val(imageUrlOnServer);
|
||||||
const previewBox = inputEl.parent().parent().siblings('.category-preview');
|
previewEl.css('background-image', 'url(' + imageUrlOnServer + '?' + new Date().getTime() + ')');
|
||||||
previewBox.css('background', 'url(' + imageUrlOnServer + '?' + new Date().getTime() + ')');
|
|
||||||
|
|
||||||
modified($('#category-image'));
|
modified($('#category-image'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#category-image').on('change', function () {
|
$('#category-image').on('change', function () {
|
||||||
$('.category-preview').css('background-image', $(this).val() ? ('url("' + $(this).val() + '")') : '');
|
previewEl.css('background-image', $(this).val() ? ('url("' + $(this).val() + '")') : '');
|
||||||
modified($('#category-image'));
|
modified($('#category-image'));
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.delete-image').on('click', function (e) {
|
$('.delete-image').on('click', function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const inputEl = $('#category-image');
|
const inputEl = $('#category-image');
|
||||||
const previewBox = $('.category-preview');
|
|
||||||
|
|
||||||
inputEl.val('');
|
inputEl.val('');
|
||||||
previewBox.css('background-image', '');
|
previewEl.css('background-image', '');
|
||||||
modified(inputEl[0]);
|
modified(inputEl[0]);
|
||||||
$(this).parent().addClass('hide').hide();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.category-preview').on('click', function () {
|
previewEl.on('click', function () {
|
||||||
iconSelect.init($(this).find('i'), modified);
|
iconSelect.init($(this).find('i'), modified);
|
||||||
});
|
});
|
||||||
|
|
||||||
$('[type="checkbox"]').on('change', function () {
|
|
||||||
modified($(this));
|
|
||||||
});
|
|
||||||
|
|
||||||
$('button[data-action="setParent"], button[data-action="changeParent"]').on('click', Category.launchParentSelector);
|
|
||||||
$('button[data-action="removeParent"]').on('click', function () {
|
|
||||||
api.put('/categories/' + ajaxify.data.category.cid, {
|
|
||||||
parentCid: 0,
|
|
||||||
}).then(() => {
|
|
||||||
$('button[data-action="removeParent"]').parent().addClass('hide');
|
|
||||||
$('button[data-action="changeParent"]').parent().addClass('hide');
|
|
||||||
$('button[data-action="setParent"]').removeClass('hide');
|
|
||||||
}).catch(alerts.error);
|
|
||||||
});
|
|
||||||
$('button[data-action="toggle"]').on('click', function () {
|
$('button[data-action="toggle"]').on('click', function () {
|
||||||
const $this = $(this);
|
const $this = $(this);
|
||||||
const disabled = $this.attr('data-disabled') === '1';
|
const disabled = $this.attr('data-disabled') === '1';
|
||||||
api.put('/categories/' + ajaxify.data.category.cid, {
|
api.put('/categories/' + ajaxify.data.category.cid, {
|
||||||
disabled: disabled ? 0 : 1,
|
disabled: disabled ? 0 : 1,
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
$this.translateText(!disabled ? '[[admin/manage/categories:enable]]' : '[[admin/manage/categories:disable]]');
|
$this.find('.label').translateText(
|
||||||
$this.toggleClass('btn-primary', !disabled).toggleClass('btn-danger', disabled);
|
!disabled ? '[[admin/manage/categories:enable]]' : '[[admin/manage/categories:disable]]'
|
||||||
|
);
|
||||||
|
$this.find('i')
|
||||||
|
.toggleClass(['fa-check', 'text-success'], !disabled)
|
||||||
|
.toggleClass(['fa-ban', 'text-danger'], disabled);
|
||||||
$this.attr('data-disabled', disabled ? 0 : 1);
|
$this.attr('data-disabled', disabled ? 0 : 1);
|
||||||
}).catch(alerts.error);
|
}).catch(alerts.error);
|
||||||
});
|
});
|
||||||
@@ -276,30 +288,5 @@ define('admin/manage/category', [
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Category.launchParentSelector = function () {
|
|
||||||
categorySelector.modal({
|
|
||||||
onSubmit: function (selectedCategory) {
|
|
||||||
const parentCid = selectedCategory.cid;
|
|
||||||
if (!parentCid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
api.put('/categories/' + ajaxify.data.category.cid, {
|
|
||||||
parentCid: parentCid,
|
|
||||||
}).then(() => {
|
|
||||||
api.get(`/categories/${parentCid}`, {}).then(function (parent) {
|
|
||||||
if (parent && parent.icon && parent.name) {
|
|
||||||
const buttonHtml = '<i class="fa ' + parent.icon + '"></i> ' + parent.name;
|
|
||||||
$('button[data-action="changeParent"]').html(buttonHtml).parent().removeClass('hide');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('button[data-action="removeParent"]').parent().removeClass('hide');
|
|
||||||
$('button[data-action="setParent"]').addClass('hide');
|
|
||||||
}).catch(alerts.error);
|
|
||||||
},
|
|
||||||
showLinks: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return Category;
|
return Category;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ define('admin/manage/group', [
|
|||||||
|
|
||||||
setupGroupMembersMenu();
|
setupGroupMembersMenu();
|
||||||
|
|
||||||
$('#group-icon, #group-icon-label').on('click', function () {
|
$('#group-icon-container').on('click', function () {
|
||||||
const currentIcon = groupIcon.attr('value');
|
const currentIcon = groupIcon.attr('value');
|
||||||
iconSelect.init(groupIcon, function () {
|
iconSelect.init(groupIcon, function () {
|
||||||
let newIcon = groupIcon.attr('value');
|
let newIcon = groupIcon.attr('value');
|
||||||
@@ -77,6 +77,7 @@ define('admin/manage/group', [
|
|||||||
cids = cids.filter((cid, index, array) => array.indexOf(cid) === index);
|
cids = cids.filter((cid, index, array) => array.indexOf(cid) === index);
|
||||||
$('#memberPostCids').val(cids.join(','));
|
$('#memberPostCids').val(cids.join(','));
|
||||||
cidSelector.selectCategory(0);
|
cidSelector.selectCategory(0);
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -87,6 +88,16 @@ define('admin/manage/group', [
|
|||||||
app.flags._unsaved = true;
|
app.flags._unsaved = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('[data-action="delete"]').on('click', function () {
|
||||||
|
bootbox.confirm('[[admin/manage/groups:alerts.confirm-delete]]', function (confirm) {
|
||||||
|
if (confirm) {
|
||||||
|
api.del(`/groups/${slugify(ajaxify.data.group.name)}`, {}).then(() => {
|
||||||
|
ajaxify.go('/admin/managegroups');
|
||||||
|
}).catch(alerts.error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$('#save').on('click', function () {
|
$('#save').on('click', function () {
|
||||||
api.put(`/groups/${slugify(groupName)}`, {
|
api.put(`/groups/${slugify(groupName)}`, {
|
||||||
name: $('#change-group-name').val(),
|
name: $('#change-group-name').val(),
|
||||||
|
|||||||
@@ -30,22 +30,8 @@ define('admin/manage/groups', [
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
enableCategorySelectors();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function enableCategorySelectors() {
|
|
||||||
$('.groups-list [component="category-selector"]').each(function () {
|
|
||||||
const nameEncoded = $(this).parents('[data-name-encoded]').attr('data-name-encoded');
|
|
||||||
categorySelector.init($(this), {
|
|
||||||
onSelect: function (selectedCategory) {
|
|
||||||
ajaxify.go('admin/manage/privileges/' + selectedCategory.cid + '?group=' + nameEncoded);
|
|
||||||
},
|
|
||||||
showLinks: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleCreate() {
|
function handleCreate() {
|
||||||
$('#create').on('click', function () {
|
$('#create').on('click', function () {
|
||||||
app.parseAndTranslate('admin/partials/create_group_modal', {}).then((html) => {
|
app.parseAndTranslate('admin/partials/create_group_modal', {}).then((html) => {
|
||||||
@@ -119,7 +105,6 @@ define('admin/manage/groups', [
|
|||||||
}, function (html) {
|
}, function (html) {
|
||||||
groupsEl.find('[data-groupname]').remove();
|
groupsEl.find('[data-groupname]').remove();
|
||||||
groupsEl.find('tbody').append(html);
|
groupsEl.find('tbody').append(html);
|
||||||
enableCategorySelectors();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ define('admin/modules/search', ['mousetrap', 'alerts'], function (mousetrap, ale
|
|||||||
// and wrap the match in a `.search-match` element
|
// and wrap the match in a `.search-match` element
|
||||||
.replace(
|
.replace(
|
||||||
new RegExp('^[\\s\\S]*?(.{0,25})(' + escaped + ')(.{0,25})[\\s\\S]*?$', 'gmi'),
|
new RegExp('^[\\s\\S]*?(.{0,25})(' + escaped + ')(.{0,25})[\\s\\S]*?$', 'gmi'),
|
||||||
'...$1<span class="search-match">$2</span>$3...<br>'
|
'...$1<span class="search-match fw-bold">$2</span>$3...<br>'
|
||||||
)
|
)
|
||||||
// collapse whitespace
|
// collapse whitespace
|
||||||
.replace(/(?:\n ?)+/g, '\n')
|
.replace(/(?:\n ?)+/g, '\n')
|
||||||
@@ -33,7 +33,7 @@ define('admin/modules/search', ['mousetrap', 'alerts'], function (mousetrap, ale
|
|||||||
);
|
);
|
||||||
|
|
||||||
return '<li role="presentation" class="result">' +
|
return '<li role="presentation" class="result">' +
|
||||||
'<a class="dropdown-item" role="menuitem" href= "' + config.relative_path + '/' + namespace + '" >' +
|
'<a class="dropdown-item rounded-1" role="menuitem" href= "' + config.relative_path + '/' + namespace + '" >' +
|
||||||
title +
|
title +
|
||||||
'<br>' + (!results ? '' :
|
'<br>' + (!results ? '' :
|
||||||
('<small><code>' +
|
('<small><code>' +
|
||||||
@@ -60,11 +60,17 @@ define('admin/modules/search', ['mousetrap', 'alerts'], function (mousetrap, ale
|
|||||||
};
|
};
|
||||||
|
|
||||||
function setupACPSearch(dict) {
|
function setupACPSearch(dict) {
|
||||||
const dropdown = $('#acp-search .dropdown');
|
const searchEls = $('[component="acp/search"]');
|
||||||
const menu = $('#acp-search .dropdown-menu');
|
searchEls.each((index, searchEl) => {
|
||||||
const input = $('#acp-search input');
|
setupSearch(dict, $(searchEl));
|
||||||
const placeholderText = dropdown.attr('data-text');
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupSearch(dict, searchEl) {
|
||||||
|
const dropdown = searchEl.find('.dropdown');
|
||||||
|
const menu = searchEl.find('.dropdown-menu');
|
||||||
|
const input = searchEl.find('input');
|
||||||
|
const placeholderText = dropdown.attr('data-text');
|
||||||
if (!config.searchEnabled) {
|
if (!config.searchEnabled) {
|
||||||
menu.addClass('search-disabled');
|
menu.addClass('search-disabled');
|
||||||
}
|
}
|
||||||
@@ -73,7 +79,7 @@ define('admin/modules/search', ['mousetrap', 'alerts'], function (mousetrap, ale
|
|||||||
dropdown.addClass('open');
|
dropdown.addClass('open');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#acp-search').parents('form').on('submit', function (ev) {
|
searchEl.parents('form').on('submit', function (ev) {
|
||||||
const query = input.val();
|
const query = input.val();
|
||||||
const selected = menu.get(0).querySelector('li.result > a.focus') || menu.get(0).querySelector('li.result > a');
|
const selected = menu.get(0).querySelector('li.result > a.focus') || menu.get(0).querySelector('li.result > a');
|
||||||
const href = selected ? selected.getAttribute('href') : config.relative_path + '/search?in=titlesposts&term=' + escape(query);
|
const href = selected ? selected.getAttribute('href') : config.relative_path + '/search?in=titlesposts&term=' + escape(query);
|
||||||
|
|||||||
@@ -1,29 +1,55 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
define('admin/settings', ['uploader', 'mousetrap', 'hooks', 'alerts', 'settings'], function (uploader, mousetrap, hooks, alerts, settings) {
|
define('admin/settings', [
|
||||||
|
'uploader', 'mousetrap', 'hooks', 'alerts', 'settings', 'bootstrap',
|
||||||
|
], function (uploader, mousetrap, hooks, alerts, settings, bootstrap) {
|
||||||
const Settings = {};
|
const Settings = {};
|
||||||
|
|
||||||
Settings.populateTOC = function () {
|
Settings.populateTOC = function () {
|
||||||
const headers = $('.settings-header');
|
const headers = $('.settings-header');
|
||||||
|
const tocEl = $('[component="settings/toc"]');
|
||||||
|
const tocList = $('[component="settings/toc/list"]');
|
||||||
|
const mainHader = $('[component="settings/main/header"]');
|
||||||
|
|
||||||
if (headers.length > 1) {
|
if (headers.length > 1 && tocList.length) {
|
||||||
headers.each(function () {
|
headers.each(function () {
|
||||||
const header = $(this).text();
|
const header = $(this).text();
|
||||||
const anchor = header.toLowerCase().replace(/ /g, '-').trim();
|
const anchor = header.toLowerCase()
|
||||||
|
.replace(/ /g, '-')
|
||||||
$(this).prepend('<a name="' + anchor + '"></a>');
|
.replace(/&/g, '-')
|
||||||
$('.section-content ul').append('<li><a href="#' + anchor + '">' + header + '</a></li>');
|
.trim();
|
||||||
|
$(this).parent().attr('id', anchor);
|
||||||
|
tocList.append(`<a class="btn-ghost-sm text-xs justify-content-start text-decoration-none" href="#${anchor}">${header}</a>`);
|
||||||
|
});
|
||||||
|
const offset = mainHader.outerHeight(true);
|
||||||
|
// https://stackoverflow.com/a/11814275/583363
|
||||||
|
tocList.find('a').on('click', function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
const href = $(this).attr('href');
|
||||||
|
$(href)[0].scrollIntoView();
|
||||||
|
window.location.hash = href;
|
||||||
|
scrollBy(0, -offset);
|
||||||
|
setTimeout(() => {
|
||||||
|
tocList.find('a').removeClass('active');
|
||||||
|
$(this).addClass('active');
|
||||||
|
}, 10);
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
const scrollTo = $('a[name="' + window.location.hash.replace('#', '') + '"]');
|
new bootstrap.ScrollSpy($('#spy-container')[0], {
|
||||||
|
target: '#settings-navbar',
|
||||||
|
rootMargin: '-10% 0px -70%',
|
||||||
|
smoothScroll: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const scrollTo = $(`${window.location.hash}`);
|
||||||
if (scrollTo.length) {
|
if (scrollTo.length) {
|
||||||
$('html, body').animate({
|
$('html, body').animate({
|
||||||
scrollTop: (scrollTo.offset().top) + 'px',
|
scrollTop: (scrollTo.offset().top - offset) + 'px',
|
||||||
}, 400);
|
}, 400);
|
||||||
}
|
}
|
||||||
} else {
|
tocEl.removeClass('hidden');
|
||||||
$('.content-header').parents('.row').remove();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -117,7 +143,7 @@ define('admin/settings', ['uploader', 'mousetrap', 'hooks', 'alerts', 'settings'
|
|||||||
saveBtnEl.classList.toggle('saved', true);
|
saveBtnEl.classList.toggle('saved', true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
saveBtnEl.classList.toggle('saved', false);
|
saveBtnEl.classList.toggle('saved', false);
|
||||||
}, 5000);
|
}, 2500);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,19 @@ define('admin/settings/general', ['admin/settings'], function () {
|
|||||||
$('button[data-action="removeOgImage"]').on('click', function () {
|
$('button[data-action="removeOgImage"]').on('click', function () {
|
||||||
$('input[data-field="removeOgImage"]').val('');
|
$('input[data-field="removeOgImage"]').val('');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('[data-field="homePageRoute"]').on('change', toggleCustomRoute);
|
||||||
|
|
||||||
|
toggleCustomRoute();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function toggleCustomRoute() {
|
||||||
|
if ($('[data-field="homePageRoute"]').val() === 'custom') {
|
||||||
|
$('#homePageCustom').show();
|
||||||
|
} else {
|
||||||
|
$('#homePageCustom').hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Module;
|
return Module;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
|
|
||||||
define('admin/settings/homepage', ['admin/settings'], function () {
|
|
||||||
function toggleCustomRoute() {
|
|
||||||
if ($('[data-field="homePageRoute"]').val() === 'custom') {
|
|
||||||
$('#homePageCustom').show();
|
|
||||||
} else {
|
|
||||||
$('#homePageCustom').hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Homepage = {};
|
|
||||||
|
|
||||||
Homepage.init = function () {
|
|
||||||
$('[data-field="homePageRoute"]').on('change', toggleCustomRoute);
|
|
||||||
|
|
||||||
toggleCustomRoute();
|
|
||||||
};
|
|
||||||
|
|
||||||
return Homepage;
|
|
||||||
});
|
|
||||||
@@ -163,13 +163,12 @@ define('admin/settings/navigation', [
|
|||||||
|
|
||||||
function toggle() {
|
function toggle() {
|
||||||
const btn = $(this);
|
const btn = $(this);
|
||||||
const disabled = btn.hasClass('btn-success');
|
const disabled = btn.hasClass('enable');
|
||||||
const index = btn.parents('[data-index]').attr('data-index');
|
const index = btn.parents('[data-index]').attr('data-index');
|
||||||
translator.translate(disabled ? '[[admin/settings/navigation:btn.disable]]' : '[[admin/settings/navigation:btn.enable]]', function (html) {
|
btn.siblings('.toggle').removeClass('hidden');
|
||||||
btn.toggleClass('btn-warning').toggleClass('btn-success').html(html);
|
btn.addClass('hidden');
|
||||||
btn.parents('li').find('[name="enabled"]').val(disabled ? 'on' : '');
|
btn.parents('li').find('[name="enabled"]').val(disabled ? 'on' : '');
|
||||||
$('#active-navigation [data-index="' + index + '"] a').toggleClass('text-muted', !disabled);
|
$('#active-navigation [data-index="' + index + '"] a').toggleClass('text-muted', !disabled);
|
||||||
});
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
|
|
||||||
define('admin/settings/social', ['alerts'], function (alerts) {
|
|
||||||
const social = {};
|
|
||||||
|
|
||||||
social.init = function () {
|
|
||||||
$('#save').on('click', function () {
|
|
||||||
const networks = [];
|
|
||||||
$('#postSharingNetworks input[type="checkbox"]').each(function () {
|
|
||||||
if ($(this).prop('checked')) {
|
|
||||||
networks.push($(this).attr('id'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.emit('admin.social.savePostSharingNetworks', networks, function (err) {
|
|
||||||
if (err) {
|
|
||||||
return alerts.error(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
alerts.success('[[admin/settings/social:save-success]]');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return social;
|
|
||||||
});
|
|
||||||
@@ -22,7 +22,8 @@ define('forum/groups/memberlist', ['api', 'bootbox', 'alerts'], function (api, b
|
|||||||
title: '[[groups:details.add-member]]',
|
title: '[[groups:details.add-member]]',
|
||||||
message: html,
|
message: html,
|
||||||
buttons: {
|
buttons: {
|
||||||
ok: {
|
OK: {
|
||||||
|
label: '[[groups:details.add-member]]',
|
||||||
callback: function () {
|
callback: function () {
|
||||||
const users = [];
|
const users = [];
|
||||||
modal.find('[data-uid][data-selected]').each(function (index, el) {
|
modal.find('[data-uid][data-selected]').each(function (index, el) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ define('categoryFilter', ['categorySearch', 'api', 'hooks'], function (categoryS
|
|||||||
}
|
}
|
||||||
options = options || {};
|
options = options || {};
|
||||||
options.states = options.states || ['watching', 'notwatching', 'ignoring'];
|
options.states = options.states || ['watching', 'notwatching', 'ignoring'];
|
||||||
options.template = 'partials/category/filter-dropdown-left';
|
options.template = options.template || 'partials/category/filter-dropdown-left';
|
||||||
|
|
||||||
hooks.fire('action:category.filter.options', { el: el, options: options });
|
hooks.fire('action:category.filter.options', { el: el, options: options });
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ define('categorySearch', ['alerts', 'bootstrap'], function (alerts, bootstrap) {
|
|||||||
options = options || {};
|
options = options || {};
|
||||||
options.privilege = options.privilege || 'topics:read';
|
options.privilege = options.privilege || 'topics:read';
|
||||||
options.states = options.states || ['watching', 'notwatching', 'ignoring'];
|
options.states = options.states || ['watching', 'notwatching', 'ignoring'];
|
||||||
|
options.cacheList = options.hasOwnProperty('cacheList') ? options.cacheList : true;
|
||||||
|
|
||||||
let localCategories = [];
|
let localCategories = [];
|
||||||
if (Array.isArray(options.localCategories)) {
|
if (Array.isArray(options.localCategories)) {
|
||||||
@@ -36,7 +37,7 @@ define('categorySearch', ['alerts', 'bootstrap'], function (alerts, bootstrap) {
|
|||||||
const val = searchEl.find('input').val();
|
const val = searchEl.find('input').val();
|
||||||
if (val.length > 1 || (!val && !categoriesList)) {
|
if (val.length > 1 || (!val && !categoriesList)) {
|
||||||
loadList(val, function (categories) {
|
loadList(val, function (categories) {
|
||||||
categoriesList = categoriesList || categories;
|
categoriesList = options.cacheList && (categoriesList || categories);
|
||||||
renderList(categories);
|
renderList(categories);
|
||||||
});
|
});
|
||||||
} else if (!val && categoriesList) {
|
} else if (!val && categoriesList) {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
define('categorySelector', [
|
define('categorySelector', [
|
||||||
'categorySearch', 'bootbox', 'hooks',
|
'categorySearch', 'bootbox', 'hooks', 'translator',
|
||||||
], function (categorySearch, bootbox, hooks) {
|
], function (categorySearch, bootbox, hooks, translator) {
|
||||||
const categorySelector = {};
|
const categorySelector = {};
|
||||||
|
|
||||||
categorySelector.init = function (el, options) {
|
categorySelector.init = function (el, options) {
|
||||||
@@ -13,7 +13,7 @@ define('categorySelector', [
|
|||||||
const onSelect = options.onSelect || function () {};
|
const onSelect = options.onSelect || function () {};
|
||||||
|
|
||||||
options.states = options.states || ['watching', 'notwatching', 'ignoring'];
|
options.states = options.states || ['watching', 'notwatching', 'ignoring'];
|
||||||
options.template = 'partials/category/selector-dropdown-left';
|
options.template = options.template || 'partials/category/selector-dropdown-left';
|
||||||
hooks.fire('action:category.selector.options', { el: el, options: options });
|
hooks.fire('action:category.selector.options', { el: el, options: options });
|
||||||
|
|
||||||
categorySearch.init(el, options);
|
categorySearch.init(el, options);
|
||||||
@@ -22,15 +22,21 @@ define('categorySelector', [
|
|||||||
el: el,
|
el: el,
|
||||||
selectedCategory: null,
|
selectedCategory: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
el.on('click', '[data-cid]', function () {
|
el.on('click', '[data-cid]', function () {
|
||||||
const categoryEl = $(this);
|
const categoryEl = $(this);
|
||||||
if (categoryEl.hasClass('disabled')) {
|
if (categoryEl.hasClass('disabled')) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
selector.selectCategory(categoryEl.attr('data-cid'));
|
selector.selectCategory(categoryEl.attr('data-cid'));
|
||||||
onSelect(selector.selectedCategory);
|
return onSelect(selector.selectedCategory);
|
||||||
|
});
|
||||||
|
|
||||||
|
let defaultSelectHtml = selector.el.find('[component="category-selector-selected"]').html();
|
||||||
|
|
||||||
|
translator.translate(defaultSelectHtml, (translated) => {
|
||||||
|
defaultSelectHtml = translated;
|
||||||
});
|
});
|
||||||
const defaultSelectHtml = selector.el.find('[component="category-selector-selected"]').html();
|
|
||||||
selector.selectCategory = function (cid) {
|
selector.selectCategory = function (cid) {
|
||||||
const categoryEl = selector.el.find('[data-cid="' + cid + '"]');
|
const categoryEl = selector.el.find('[data-cid="' + cid + '"]');
|
||||||
selector.selectedCategory = {
|
selector.selectedCategory = {
|
||||||
@@ -54,6 +60,14 @@ define('categorySelector', [
|
|||||||
selector.getSelectedCid = function () {
|
selector.getSelectedCid = function () {
|
||||||
return selector.selectedCategory ? selector.selectedCategory.cid : 0;
|
return selector.selectedCategory ? selector.selectedCategory.cid : 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (options.hasOwnProperty('selectedCategory')) {
|
||||||
|
app.parseAndTranslate(options.template, { selectedCategory: options.selectedCategory }, function (html) {
|
||||||
|
selector.el.find('[component="category-selector-selected"]').html(
|
||||||
|
html.find('[component="category-selector-selected"]').html()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
return selector;
|
return selector;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -323,7 +323,7 @@ define('iconSelect', ['benchpress', 'bootbox'], function (Benchpress, bootbox) {
|
|||||||
}
|
}
|
||||||
icons.remove();
|
icons.remove();
|
||||||
iconData.forEach((iconData) => {
|
iconData.forEach((iconData) => {
|
||||||
iconContainer.append($(`<i class="fa fa-xl fa-${iconData.style} fa-${iconData.id}" data-label="${iconData.label}"></i>`));
|
iconContainer.append($(`<i class="fa fa-xl fa-${iconData.style} fa-${iconData.id} rounded-1" data-label="${iconData.label}"></i>`));
|
||||||
});
|
});
|
||||||
icons = modalEl.find('.nbb-fa-icons i');
|
icons = modalEl.find('.nbb-fa-icons i');
|
||||||
changeSelection();
|
changeSelection();
|
||||||
|
|||||||
@@ -364,6 +364,13 @@ Categories.buildForSelectCategories = function (categories, fields, parentCid) {
|
|||||||
|
|
||||||
const rootCategories = categories.filter(category => category && category.parentCid === parentCid);
|
const rootCategories = categories.filter(category => category && category.parentCid === parentCid);
|
||||||
|
|
||||||
|
rootCategories.sort((a, b) => {
|
||||||
|
if (a.order !== b.order) {
|
||||||
|
return a.order - b.order;
|
||||||
|
}
|
||||||
|
return a.cid - b.cid;
|
||||||
|
});
|
||||||
|
|
||||||
rootCategories.forEach(category => recursive(category, categoriesData, '', 0));
|
rootCategories.forEach(category => recursive(category, categoriesData, '', 0));
|
||||||
|
|
||||||
const pickFields = [
|
const pickFields = [
|
||||||
|
|||||||
@@ -60,8 +60,9 @@ categoriesController.getAll = async function (req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fields = [
|
const fields = [
|
||||||
'cid', 'name', 'icon', 'parentCid', 'disabled', 'link', 'order',
|
'cid', 'name', 'icon', 'parentCid', 'disabled', 'link',
|
||||||
'color', 'bgColor', 'backgroundImage', 'imageClass', 'subCategoriesPerPage',
|
'order', 'color', 'bgColor', 'backgroundImage', 'imageClass',
|
||||||
|
'subCategoriesPerPage', 'description',
|
||||||
];
|
];
|
||||||
const categoriesData = await categories.getCategoriesFields(cids, fields);
|
const categoriesData = await categories.getCategoriesFields(cids, fields);
|
||||||
const result = await plugins.hooks.fire('filter:admin.categories.get', { categories: categoriesData, fields: fields });
|
const result = await plugins.hooks.fire('filter:admin.categories.get', { categories: categoriesData, fields: fields });
|
||||||
@@ -101,6 +102,7 @@ categoriesController.getAll = async function (req, res) {
|
|||||||
breadcrumbs: crumbs,
|
breadcrumbs: crumbs,
|
||||||
pagination: pagination.create(page, pageCount, req.query),
|
pagination: pagination.create(page, pageCount, req.query),
|
||||||
categoriesPerPage: meta.config.categoriesPerPage,
|
categoriesPerPage: meta.config.categoriesPerPage,
|
||||||
|
selectCategoryLabel: '[[admin/manage/categories:jump-to]]',
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -18,13 +18,27 @@ const settingsController = module.exports;
|
|||||||
|
|
||||||
settingsController.get = async function (req, res) {
|
settingsController.get = async function (req, res) {
|
||||||
const term = req.params.term || 'general';
|
const term = req.params.term || 'general';
|
||||||
res.render(`admin/settings/${term}`);
|
const payload = {
|
||||||
|
title: `[[admin/menu:settings/${term}]]`,
|
||||||
|
};
|
||||||
|
if (term === 'general') {
|
||||||
|
payload.routes = await helpers.getHomePageRoutes(req.uid);
|
||||||
|
payload.postSharing = await social.getPostSharing();
|
||||||
|
const languageData = await languages.list();
|
||||||
|
languageData.forEach((language) => {
|
||||||
|
language.selected = language.code === meta.config.defaultLang;
|
||||||
|
});
|
||||||
|
payload.languages = languageData;
|
||||||
|
payload.autoDetectLang = meta.config.autoDetectLang;
|
||||||
|
}
|
||||||
|
res.render(`admin/settings/${term}`, payload);
|
||||||
};
|
};
|
||||||
|
|
||||||
settingsController.email = async (req, res) => {
|
settingsController.email = async (req, res) => {
|
||||||
const emails = await emailer.getTemplates(meta.config);
|
const emails = await emailer.getTemplates(meta.config);
|
||||||
|
|
||||||
res.render('admin/settings/email', {
|
res.render('admin/settings/email', {
|
||||||
|
title: '[[admin/menu:settings/email]]',
|
||||||
emails: emails,
|
emails: emails,
|
||||||
sendable: emails.filter(e => !e.path.includes('_plaintext') && !e.path.includes('partials')).map(tpl => tpl.path),
|
sendable: emails.filter(e => !e.path.includes('_plaintext') && !e.path.includes('partials')).map(tpl => tpl.path),
|
||||||
services: emailer.listServices(),
|
services: emailer.listServices(),
|
||||||
@@ -38,6 +52,7 @@ settingsController.user = async (req, res) => {
|
|||||||
label: `[[notifications:${type}]]`,
|
label: `[[notifications:${type}]]`,
|
||||||
}));
|
}));
|
||||||
res.render('admin/settings/user', {
|
res.render('admin/settings/user', {
|
||||||
|
title: '[[admin/menu:settings/user]]',
|
||||||
notificationSettings: notificationSettings,
|
notificationSettings: notificationSettings,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -45,6 +60,7 @@ settingsController.user = async (req, res) => {
|
|||||||
settingsController.post = async (req, res) => {
|
settingsController.post = async (req, res) => {
|
||||||
const groupData = await groups.getNonPrivilegeGroups('groups:createtime', 0, -1);
|
const groupData = await groups.getNonPrivilegeGroups('groups:createtime', 0, -1);
|
||||||
res.render('admin/settings/post', {
|
res.render('admin/settings/post', {
|
||||||
|
title: '[[admin/menu:settings/post]]',
|
||||||
groupsExemptFromPostQueue: groupData,
|
groupsExemptFromPostQueue: groupData,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -52,22 +68,11 @@ settingsController.post = async (req, res) => {
|
|||||||
settingsController.advanced = async (req, res) => {
|
settingsController.advanced = async (req, res) => {
|
||||||
const groupData = await groups.getNonPrivilegeGroups('groups:createtime', 0, -1);
|
const groupData = await groups.getNonPrivilegeGroups('groups:createtime', 0, -1);
|
||||||
res.render('admin/settings/advanced', {
|
res.render('admin/settings/advanced', {
|
||||||
|
title: '[[admin/menu:settings/advanced]]',
|
||||||
groupsExemptFromMaintenanceMode: groupData,
|
groupsExemptFromMaintenanceMode: groupData,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
settingsController.languages = async function (req, res) {
|
|
||||||
const languageData = await languages.list();
|
|
||||||
languageData.forEach((language) => {
|
|
||||||
language.selected = language.code === meta.config.defaultLang;
|
|
||||||
});
|
|
||||||
|
|
||||||
res.render('admin/settings/languages', {
|
|
||||||
languages: languageData,
|
|
||||||
autoDetectLang: meta.config.autoDetectLang,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
settingsController.navigation = async function (req, res) {
|
settingsController.navigation = async function (req, res) {
|
||||||
const [admin, allGroups] = await Promise.all([
|
const [admin, allGroups] = await Promise.all([
|
||||||
navigationAdmin.getAdmin(),
|
navigationAdmin.getAdmin(),
|
||||||
@@ -94,23 +99,14 @@ settingsController.navigation = async function (req, res) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
admin.navigation = admin.enabled.slice();
|
admin.navigation = admin.enabled.slice();
|
||||||
|
admin.title = '[[admin/menu:settings/navigation]]';
|
||||||
res.render('admin/settings/navigation', admin);
|
res.render('admin/settings/navigation', admin);
|
||||||
};
|
};
|
||||||
|
|
||||||
settingsController.homepage = async function (req, res) {
|
|
||||||
const routes = await helpers.getHomePageRoutes(req.uid);
|
|
||||||
res.render('admin/settings/homepage', { routes: routes });
|
|
||||||
};
|
|
||||||
|
|
||||||
settingsController.social = async function (req, res) {
|
|
||||||
const posts = await social.getPostSharing();
|
|
||||||
res.render('admin/settings/social', {
|
|
||||||
posts: posts,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
settingsController.api = async (req, res) => {
|
settingsController.api = async (req, res) => {
|
||||||
const tokens = await api.utils.tokens.list();
|
const tokens = await api.utils.tokens.list();
|
||||||
res.render('admin/settings/api', { tokens });
|
res.render('admin/settings/api', {
|
||||||
|
title: '[[admin/menu:settings/api]]',
|
||||||
|
tokens,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -31,10 +31,8 @@ const buildImports = {
|
|||||||
},
|
},
|
||||||
admin: function (source) {
|
admin: function (source) {
|
||||||
return [
|
return [
|
||||||
'@import "admin/vars";',
|
'@import "admin/overrides";',
|
||||||
'@import "bootswatch/dist/materia/variables";',
|
|
||||||
'@import "bootstrap/scss/bootstrap";',
|
'@import "bootstrap/scss/bootstrap";',
|
||||||
'@import "bootswatch/dist/materia/bootswatch";',
|
|
||||||
'@import "mixins";',
|
'@import "mixins";',
|
||||||
'@import "fontawesome";',
|
'@import "fontawesome";',
|
||||||
'@import "@adactive/bootstrap-tagsinput/src/bootstrap-tagsinput";',
|
'@import "@adactive/bootstrap-tagsinput/src/bootstrap-tagsinput";',
|
||||||
|
|||||||
@@ -83,6 +83,10 @@ JS.buildModules = async function () {
|
|||||||
|
|
||||||
JS.linkStatics = async function () {
|
JS.linkStatics = async function () {
|
||||||
await fs.promises.rm(path.join(__dirname, '../../build/public/plugins'), { recursive: true, force: true });
|
await fs.promises.rm(path.join(__dirname, '../../build/public/plugins'), { recursive: true, force: true });
|
||||||
|
|
||||||
|
plugins.staticDirs['core/inter'] = path.join(basePath, 'node_modules//@fontsource/inter/files');
|
||||||
|
plugins.staticDirs['core/poppins'] = path.join(basePath, 'node_modules//@fontsource/poppins/files');
|
||||||
|
|
||||||
await Promise.all(Object.keys(plugins.staticDirs).map(async (mappedPath) => {
|
await Promise.all(Object.keys(plugins.staticDirs).map(async (mappedPath) => {
|
||||||
const sourceDir = plugins.staticDirs[mappedPath];
|
const sourceDir = plugins.staticDirs[mappedPath];
|
||||||
const destDir = path.join(__dirname, '../../build/public/plugins', mappedPath);
|
const destDir = path.join(__dirname, '../../build/public/plugins', mappedPath);
|
||||||
|
|||||||
@@ -142,6 +142,14 @@ module.exports = function (Posts) {
|
|||||||
filePaths = [filePaths];
|
filePaths = [filePaths];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
// windows path => 'files\\1685368788211-1-profileimg.jpg'
|
||||||
|
// turn it into => 'files/1685368788211-1-profileimg.jpg'
|
||||||
|
filePaths.forEach((file) => {
|
||||||
|
file.path = file.path.split(path.sep).join(path.posix.sep);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const keys = filePaths.map(fileObj => `upload:${md5(fileObj.path.replace('-resized', ''))}:pids`);
|
const keys = filePaths.map(fileObj => `upload:${md5(fileObj.path.replace('-resized', ''))}:pids`);
|
||||||
return await Promise.all(keys.map(k => db.getSortedSetRange(k, 0, -1)));
|
return await Promise.all(keys.map(k => db.getSortedSetRange(k, 0, -1)));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,10 +35,7 @@ module.exports = function (app, name, middleware, controllers) {
|
|||||||
helpers.setupAdminPageRoute(app, `/${name}/settings/user`, middlewares, controllers.admin.settings.user);
|
helpers.setupAdminPageRoute(app, `/${name}/settings/user`, middlewares, controllers.admin.settings.user);
|
||||||
helpers.setupAdminPageRoute(app, `/${name}/settings/post`, middlewares, controllers.admin.settings.post);
|
helpers.setupAdminPageRoute(app, `/${name}/settings/post`, middlewares, controllers.admin.settings.post);
|
||||||
helpers.setupAdminPageRoute(app, `/${name}/settings/advanced`, middlewares, controllers.admin.settings.advanced);
|
helpers.setupAdminPageRoute(app, `/${name}/settings/advanced`, middlewares, controllers.admin.settings.advanced);
|
||||||
helpers.setupAdminPageRoute(app, `/${name}/settings/languages`, middlewares, controllers.admin.settings.languages);
|
|
||||||
helpers.setupAdminPageRoute(app, `/${name}/settings/navigation`, middlewares, controllers.admin.settings.navigation);
|
helpers.setupAdminPageRoute(app, `/${name}/settings/navigation`, middlewares, controllers.admin.settings.navigation);
|
||||||
helpers.setupAdminPageRoute(app, `/${name}/settings/homepage`, middlewares, controllers.admin.settings.homepage);
|
|
||||||
helpers.setupAdminPageRoute(app, `/${name}/settings/social`, middlewares, controllers.admin.settings.social);
|
|
||||||
helpers.setupAdminPageRoute(app, `/${name}/settings/api`, middlewares, controllers.admin.settings.api);
|
helpers.setupAdminPageRoute(app, `/${name}/settings/api`, middlewares, controllers.admin.settings.api);
|
||||||
helpers.setupAdminPageRoute(app, `/${name}/settings/:term?`, middlewares, controllers.admin.settings.get);
|
helpers.setupAdminPageRoute(app, `/${name}/settings/:term?`, middlewares, controllers.admin.settings.get);
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const plugins = require('./plugins');
|
const plugins = require('./plugins');
|
||||||
const db = require('./database');
|
const db = require('./database');
|
||||||
|
const meta = require('./meta');
|
||||||
|
|
||||||
const social = module.exports;
|
const social = module.exports;
|
||||||
|
|
||||||
@@ -26,9 +27,8 @@ social.getPostSharing = async function () {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
networks = await plugins.hooks.fire('filter:social.posts', networks);
|
networks = await plugins.hooks.fire('filter:social.posts', networks);
|
||||||
const activated = await db.getSetMembers('social:posts.activated');
|
|
||||||
networks.forEach((network) => {
|
networks.forEach((network) => {
|
||||||
network.activated = activated.includes(network.id);
|
network.activated = parseInt(meta.config[`post-sharing-${network.id}`], 10) === 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
social.postSharing = networks;
|
social.postSharing = networks;
|
||||||
@@ -41,12 +41,16 @@ social.getActivePostSharing = async function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
social.setActivePostSharingNetworks = async function (networkIDs) {
|
social.setActivePostSharingNetworks = async function (networkIDs) {
|
||||||
|
// keeping for 1.0.0 upgrade script that uses this function
|
||||||
social.postSharing = null;
|
social.postSharing = null;
|
||||||
await db.delete('social:posts.activated');
|
|
||||||
if (!networkIDs.length) {
|
if (!networkIDs.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await db.setAdd('social:posts.activated', networkIDs);
|
const data = {};
|
||||||
|
networkIDs.forEach((id) => {
|
||||||
|
data[`post-sharing-${id}`] = 1;
|
||||||
|
});
|
||||||
|
await db.setObject('config', data);
|
||||||
};
|
};
|
||||||
|
|
||||||
require('./promisify')(social);
|
require('./promisify')(social);
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ SocketAdmin.tags = require('./admin/tags');
|
|||||||
SocketAdmin.rewards = require('./admin/rewards');
|
SocketAdmin.rewards = require('./admin/rewards');
|
||||||
SocketAdmin.navigation = require('./admin/navigation');
|
SocketAdmin.navigation = require('./admin/navigation');
|
||||||
SocketAdmin.rooms = require('./admin/rooms');
|
SocketAdmin.rooms = require('./admin/rooms');
|
||||||
SocketAdmin.social = require('./admin/social');
|
|
||||||
SocketAdmin.themes = require('./admin/themes');
|
SocketAdmin.themes = require('./admin/themes');
|
||||||
SocketAdmin.plugins = require('./admin/plugins');
|
SocketAdmin.plugins = require('./admin/plugins');
|
||||||
SocketAdmin.widgets = require('./admin/widgets');
|
SocketAdmin.widgets = require('./admin/widgets');
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const social = require('../../social');
|
|
||||||
|
|
||||||
const SocketSocial = module.exports;
|
|
||||||
|
|
||||||
SocketSocial.savePostSharingNetworks = async function (socket, data) {
|
|
||||||
await social.setActivePostSharingNetworks(data);
|
|
||||||
};
|
|
||||||
19
src/upgrades/3.2.0/migrate_post_sharing.js
Normal file
19
src/upgrades/3.2.0/migrate_post_sharing.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const db = require('../../database');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: 'Migrate post sharing values to config',
|
||||||
|
timestamp: Date.UTC(2023, 4, 23),
|
||||||
|
method: async () => {
|
||||||
|
const activated = await db.getSetMembers('social:posts.activated');
|
||||||
|
if (activated.length) {
|
||||||
|
const data = {};
|
||||||
|
activated.forEach((id) => {
|
||||||
|
data[`post-sharing-${id}`] = 1;
|
||||||
|
});
|
||||||
|
await db.setObject('config', data);
|
||||||
|
await db.delete('social:posts.activated');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
<!-- IMPORT admin/partials/settings/header.tpl -->
|
|
||||||
<div class="row post-cache">
|
<div class="row post-cache settings px-lg-4">
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{{{each caches}}}
|
{{{each caches}}}
|
||||||
<div class="col-lg-3">
|
<div class="col-xl-3">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">[[admin/advanced/cache:{@key}-cache]]</div>
|
<div class="card-header">[[admin/advanced/cache:{@key}-cache]]</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@@ -52,4 +52,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- IMPORT admin/partials/settings/footer.tpl -->
|
<!-- IMPORT admin/partials/save_button.tpl -->
|
||||||
|
|||||||
@@ -1,146 +1,147 @@
|
|||||||
|
<div class="acp-page-container">
|
||||||
<div class="row database">
|
<div class="row database">
|
||||||
{{{ if mongo }}}
|
{{{ if mongo }}}
|
||||||
<div class="col-lg-6">
|
<div class="{{{ if redis }}}col-lg-6{{{ else }}}col-lg-12{{{ end }}}">
|
||||||
{{{ if mongo.serverStatusError }}}
|
{{{ if mongo.serverStatusError }}}
|
||||||
<div class="alert alert-warning">
|
<div class="alert alert-warning">
|
||||||
{mongo.serverStatusError}
|
{mongo.serverStatusError}
|
||||||
|
</div>
|
||||||
|
{{{ end }}}
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header"><i class="fa fa-hdd-o"></i> [[admin/advanced/database:mongo]]</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="database-info">
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:mongo.version]]</span> <span class="text-end">{mongo.version}</span></div>
|
||||||
|
<hr/>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:uptime-seconds]]</span> <span class="text-end formatted-number">{mongo.uptime}</span></div>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:mongo.storage-engine]]</span> <span class="text-end">{mongo.storageEngine}</span></div>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:mongo.collections]]</span> <span class="text-end formatted-number">{mongo.collections}</span></div>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:mongo.objects]]</span> <span class="text-end formatted-number">{mongo.objects}</span></div>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:mongo.avg-object-size]]</span> <span class="text-end">[[admin/advanced/database:x-b, {mongo.avgObjSize}]]</span></div>
|
||||||
|
<hr/>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:mongo.data-size]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.dataSize}]]</span></div>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:mongo.storage-size]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.storageSize}]]</span></div>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:mongo.index-size]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.indexSize}]]</span></div>
|
||||||
|
{{{ if mongo.fileSize }}}
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:mongo.file-size]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.fileSize}]]</span></div>
|
||||||
|
{{{ end }}}
|
||||||
|
<hr/>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:mongo.resident-memory]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.mem.resident}]]</span></div>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:mongo.virtual-memory]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.mem.virtual}]]</span></div>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:mongo.mapped-memory]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.mem.mapped}]]</span></div>
|
||||||
|
<hr/>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:mongo.bytes-in]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.network.bytesIn}]]</span></div>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:mongo.bytes-out]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.network.bytesOut}]]</span></div>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:mongo.num-requests]]</span> <span class="text-end">{mongo.network.numRequests}</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{{ end }}}
|
{{{ end }}}
|
||||||
<div class="card">
|
|
||||||
<div class="card-header"><i class="fa fa-hdd-o"></i> [[admin/advanced/database:mongo]]</div>
|
{{{ if redis }}}
|
||||||
<div class="card-body">
|
<div class="col-lg-6">
|
||||||
<div class="database-info">
|
<div class="card">
|
||||||
<span>[[admin/advanced/database:mongo.version]]</span> <span class="text-end">{mongo.version}</span><br/>
|
<div class="card-header"><i class="fa fa-hdd-o"></i> [[admin/advanced/database:redis]]</div>
|
||||||
<hr/>
|
<div class="card-body">
|
||||||
<span>[[admin/advanced/database:uptime-seconds]]</span> <span class="text-end formatted-number">{mongo.uptime}</span><br/>
|
<div class="database-info">
|
||||||
<span>[[admin/advanced/database:mongo.storage-engine]]</span> <span class="text-end">{mongo.storageEngine}</span><br/>
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.version]]</span> <span class="text-end">{redis.redis_version}</span></div>
|
||||||
<span>[[admin/advanced/database:mongo.collections]]</span> <span class="text-end formatted-number">{mongo.collections}</span><br/>
|
<hr/>
|
||||||
<span>[[admin/advanced/database:mongo.objects]]</span> <span class="text-end formatted-number">{mongo.objects}</span><br/>
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:uptime-seconds]]</span> <span class="text-end formatted-number">{redis.uptime_in_seconds}</span></div>
|
||||||
<span>[[admin/advanced/database:mongo.avg-object-size]]</span> <span class="text-end">[[admin/advanced/database:x-b, {mongo.avgObjSize}]]</span><br/>
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:uptime-days]]</span> <span class="text-end">{redis.uptime_in_days}</span></div>
|
||||||
<hr/>
|
<hr/>
|
||||||
<span>[[admin/advanced/database:mongo.data-size]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.dataSize}]]</span><br/>
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.keys]]</span> <span class="text-end formatted-number">{redis.keys}</span></div>
|
||||||
<span>[[admin/advanced/database:mongo.storage-size]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.storageSize}]]</span><br/>
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.expires]]</span> <span class="text-end formatted-number">{redis.expires}</span></div>
|
||||||
<span>[[admin/advanced/database:mongo.index-size]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.indexSize}]]</span><br/>
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.avg-ttl]]</span> <span class="text-end formatted-number">{redis.avg_ttl}</span></div>
|
||||||
{{{ if mongo.fileSize }}}
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.connected-clients]]</span> <span class="text-end">{redis.connected_clients}</span></div>
|
||||||
<span>[[admin/advanced/database:mongo.file-size]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.fileSize}]]</span><br/>
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.connected-slaves]]</span> <span class="text-end">{redis.connected_slaves}</span></div>
|
||||||
{{{ end }}}
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.blocked-clients]]</span> <span class="text-end">{redis.blocked_clients}</span></div>
|
||||||
<hr/>
|
<hr/>
|
||||||
<span>[[admin/advanced/database:mongo.resident-memory]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.mem.resident}]]</span><br/>
|
|
||||||
<span>[[admin/advanced/database:mongo.virtual-memory]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.mem.virtual}]]</span><br/>
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.used-memory]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {redis.used_memory_human}]]</span></div>
|
||||||
<span>[[admin/advanced/database:mongo.mapped-memory]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.mem.mapped}]]</span><br/>
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.memory-frag-ratio]]</span> <span class="text-end">{redis.mem_fragmentation_ratio}</span></div>
|
||||||
<hr/>
|
<hr/>
|
||||||
<span>[[admin/advanced/database:mongo.bytes-in]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.network.bytesIn}]]</span><br/>
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.total-connections-recieved]]</span> <span class="text-end formatted-number">{redis.total_connections_received}</span></div>
|
||||||
<span>[[admin/advanced/database:mongo.bytes-out]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {mongo.network.bytesOut}]]</span><br/>
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.total-commands-processed]]</span> <span class="text-end formatted-number">{redis.total_commands_processed}</span></div>
|
||||||
<span>[[admin/advanced/database:mongo.num-requests]]</span> <span class="text-end">{mongo.network.numRequests}</span><br/>
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.iops]]</span> <span class="text-end formatted-number">{redis.instantaneous_ops_per_sec}</span></div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.iinput]]</span> <span class="text-end">[[admin/advanced/database:x-mb, {redis.instantaneous_input}]]</span></div>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.ioutput]]</span> <span class="text-end">[[admin/advanced/database:x-mb, {redis.instantaneous_output}]]</span></div>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.total-input]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {redis.total_net_input}]]</span></div>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.total-output]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {redis.total_net_output}]]</span></div>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.keyspace-hits]]</span> <span class="text-end formatted-number">{redis.keyspace_hits}</span></div>
|
||||||
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:redis.keyspace-misses]]</span> <span class="text-end formatted-number">{redis.keyspace_misses}</span></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{{{ end }}}
|
||||||
{{{ end }}}
|
|
||||||
|
|
||||||
{{{ if redis }}}
|
{{{ if postgres }}}
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header"><i class="fa fa-hdd-o"></i> [[admin/advanced/database:redis]]</div>
|
<div class="card-header"><i class="fa fa-hdd-o"></i> [[admin/advanced/database:postgres]]</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="database-info">
|
<div class="database-info">
|
||||||
<span>[[admin/advanced/database:redis.version]]</span> <span class="text-end">{redis.redis_version}</span><br/>
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:postgres.version]]</span> <span class="text-end">{postgres.version}</span></div>
|
||||||
<hr/>
|
<hr/>
|
||||||
<span>[[admin/advanced/database:uptime-seconds]]</span> <span class="text-end formatted-number">{redis.uptime_in_seconds}</span><br/>
|
<div class="d-flex justify-content-between"><span>[[admin/advanced/database:uptime-seconds]]</span> <span class="text-end formatted-number">{postgres.uptime}</span></div>
|
||||||
<span>[[admin/advanced/database:uptime-days]]</span> <span class="text-end">{redis.uptime_in_days}</span><br/>
|
</div>
|
||||||
<hr/>
|
|
||||||
<span>[[admin/advanced/database:redis.keys]]</span> <span class="text-end formatted-number">{redis.keys}</span><br/>
|
|
||||||
<span>[[admin/advanced/database:redis.expires]]</span> <span class="text-end formatted-number">{redis.expires}</span><br/>
|
|
||||||
<span>[[admin/advanced/database:redis.avg-ttl]]</span> <span class="text-end formatted-number">{redis.avg_ttl}</span><br/>
|
|
||||||
<span>[[admin/advanced/database:redis.connected-clients]]</span> <span class="text-end">{redis.connected_clients}</span><br/>
|
|
||||||
<span>[[admin/advanced/database:redis.connected-slaves]]</span> <span class="text-end">{redis.connected_slaves}</span><br/>
|
|
||||||
<span>[[admin/advanced/database:redis.blocked-clients]]</span> <span class="text-end">{redis.blocked_clients}</span><br/>
|
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<span>[[admin/advanced/database:redis.used-memory]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {redis.used_memory_human}]]</span><br/>
|
|
||||||
<span>[[admin/advanced/database:redis.memory-frag-ratio]]</span> <span class="text-end">{redis.mem_fragmentation_ratio}</span><br/>
|
|
||||||
<hr/>
|
|
||||||
<span>[[admin/advanced/database:redis.total-connections-recieved]]</span> <span class="text-end formatted-number">{redis.total_connections_received}</span><br/>
|
|
||||||
<span>[[admin/advanced/database:redis.total-commands-processed]]</span> <span class="text-end formatted-number">{redis.total_commands_processed}</span><br/>
|
|
||||||
<span>[[admin/advanced/database:redis.iops]]</span> <span class="text-end formatted-number">{redis.instantaneous_ops_per_sec}</span><br/>
|
|
||||||
|
|
||||||
<span>[[admin/advanced/database:redis.iinput]]</span> <span class="text-end">[[admin/advanced/database:x-mb, {redis.instantaneous_input}]]</span><br/>
|
|
||||||
<span>[[admin/advanced/database:redis.ioutput]]</span> <span class="text-end">[[admin/advanced/database:x-mb, {redis.instantaneous_output}]]</span><br/>
|
|
||||||
<span>[[admin/advanced/database:redis.total-input]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {redis.total_net_input}]]</span><br/>
|
|
||||||
<span>[[admin/advanced/database:redis.total-output]]</span> <span class="text-end">[[admin/advanced/database:x-gb, {redis.total_net_output}]]</span><br/>
|
|
||||||
|
|
||||||
<hr/>
|
|
||||||
<span>[[admin/advanced/database:redis.keyspace-hits]]</span> <span class="text-end formatted-number">{redis.keyspace_hits}</span><br/>
|
|
||||||
<span>[[admin/advanced/database:redis.keyspace-misses]]</span> <span class="text-end formatted-number">{redis.keyspace_misses}</span><br/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{{ end }}}
|
||||||
</div>
|
</div>
|
||||||
{{{ end }}}
|
|
||||||
|
|
||||||
{{{ if postgres }}}
|
<div class="row">
|
||||||
<div class="col-lg-6">
|
{{{ if mongo }}}
|
||||||
<div class="card">
|
<div class="{{{ if redis }}}col-lg-6{{{ else }}}col-lg-12{{{ end }}}">
|
||||||
<div class="card-header"><i class="fa fa-hdd-o"></i> [[admin/advanced/database:postgres]]</div>
|
<div class="card">
|
||||||
<div class="card-body">
|
<h5 class="card-header" data-bs-toggle="collapse" data-bs-target=".mongodb-raw">
|
||||||
<div class="database-info">
|
<i class="fa fa-caret-down"></i> [[admin/advanced/database:mongo.raw-info]]
|
||||||
<span>[[admin/advanced/database:postgres.version]]</span> <span class="text-end">{postgres.version}</span><br/>
|
</h5>
|
||||||
<hr/>
|
|
||||||
<span>[[admin/advanced/database:uptime-seconds]]</span> <span class="text-end formatted-number">{postgres.uptime}</span><br/>
|
<div class="card-body mongodb-raw collapse">
|
||||||
|
<div class="highlight">
|
||||||
|
<pre>{mongo.raw}</pre>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{{{ end }}}
|
||||||
{{{ end }}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row database">
|
{{{ if redis }}}
|
||||||
{{{ if mongo }}}
|
<div class="col-lg-6">
|
||||||
<div class="col-lg-6">
|
<div class="card">
|
||||||
<div class="card">
|
<h5 class="card-header" data-bs-toggle="collapse" data-bs-target=".redis-raw">
|
||||||
<h5 class="card-header" data-bs-toggle="collapse" data-bs-target=".mongodb-raw">
|
<i class="fa fa-caret-down"></i> [[admin/advanced/database:redis.raw-info]]
|
||||||
<i class="fa fa-caret-down"></i> [[admin/advanced/database:mongo.raw-info]]
|
</h5>
|
||||||
</h5>
|
|
||||||
|
|
||||||
<div class="card-body mongodb-raw collapse">
|
<div class="card-body redis-raw collapse">
|
||||||
<div class="highlight">
|
<div class="highlight">
|
||||||
<pre>{mongo.raw}</pre>
|
<pre>{redis.raw}</pre>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{{{ end }}}
|
||||||
{{{ end }}}
|
|
||||||
|
|
||||||
{{{ if redis }}}
|
{{{ if postgres }}}
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h5 class="card-header" data-bs-toggle="collapse" data-bs-target=".redis-raw">
|
<h5 class="card-header" data-bs-toggle="collapse" data-bs-target=".postgresql-raw">
|
||||||
<i class="fa fa-caret-down"></i> [[admin/advanced/database:redis.raw-info]]
|
<i class="fa fa-caret-down"></i> [[admin/advanced/database:postgres.raw-info]]
|
||||||
</h5>
|
</h5>
|
||||||
|
|
||||||
<div class="card-body redis-raw collapse">
|
<div class="card-body postgresql-raw collapse">
|
||||||
<div class="highlight">
|
<div class="highlight">
|
||||||
<pre>{redis.raw}</pre>
|
<pre>{postgres.raw}</pre>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{{ end }}}
|
||||||
</div>
|
</div>
|
||||||
{{{ end }}}
|
</div>
|
||||||
|
|
||||||
{{{ if postgres }}}
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<div class="card">
|
|
||||||
<h5 class="card-header" data-bs-toggle="collapse" data-bs-target=".postgresql-raw">
|
|
||||||
<i class="fa fa-caret-down"></i> [[admin/advanced/database:postgres.raw-info]]
|
|
||||||
</h5>
|
|
||||||
|
|
||||||
<div class="card-body postgresql-raw collapse">
|
|
||||||
<div class="highlight">
|
|
||||||
<pre>{postgres.raw}</pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{{ end }}}
|
|
||||||
</div>
|
|
||||||
@@ -1,77 +1,79 @@
|
|||||||
<div class="row">
|
<div class="px-lg-4">
|
||||||
<div class="col-lg-9">
|
<div class="row">
|
||||||
<div class="row">
|
<div class="col-lg-9">
|
||||||
<div class="col-sm-6 text-center">
|
<div class="row">
|
||||||
<div class="card">
|
<div class="col-sm-6 text-center">
|
||||||
<div class="card-body">
|
<div class="card">
|
||||||
<div><canvas id="not-found" height="250"></canvas></div>
|
<div class="card-body">
|
||||||
|
<div><canvas id="not-found" height="250"></canvas></div>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer"><small>
|
||||||
|
<strong>[[admin/advanced/errors:figure-x, 1]]</strong> –
|
||||||
|
[[admin/advanced/errors:error-events-per-day, [[admin/advanced/errors:error.404]]]]
|
||||||
|
</small></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 text-center">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div><canvas id="toobusy" height="250"></canvas></div>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer"><small>
|
||||||
|
<strong>[[admin/advanced/errors:figure-x, 2]]</strong> –
|
||||||
|
[[admin/advanced/errors:error-events-per-day, [[admin/advanced/errors:error.503]]]]
|
||||||
|
</small></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer"><small>
|
|
||||||
<strong>[[admin/advanced/errors:figure-x, 1]]</strong> –
|
|
||||||
[[admin/advanced/errors:error-events-per-day, [[admin/advanced/errors:error.404]]]]
|
|
||||||
</small></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6 text-center">
|
</div>
|
||||||
<div class="card">
|
<div class="col-lg-3 acp-sidebar">
|
||||||
<div class="card-body">
|
<div class="card">
|
||||||
<div><canvas id="toobusy" height="250"></canvas></div>
|
<div class="card-header">[[admin/advanced/errors:manage-error-log]]</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="d-grid gap-2" role="group">
|
||||||
|
<a class="btn btn-info" target="_top" href="{config.relative_path}/admin/advanced/errors/export">
|
||||||
|
<i class="fa fa-download"></i> [[admin/advanced/errors:export-error-log]]
|
||||||
|
</a>
|
||||||
|
<button class="btn btn-danger" data-action="clear">
|
||||||
|
<i class="fa fa-trash"></i> [[admin/advanced/errors:clear-error-log]]
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer"><small>
|
|
||||||
<strong>[[admin/advanced/errors:figure-x, 2]]</strong> –
|
|
||||||
[[admin/advanced/errors:error-events-per-day, [[admin/advanced/errors:error.503]]]]
|
|
||||||
</small></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-3 acp-sidebar">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">[[admin/advanced/errors:manage-error-log]]</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="d-grid gap-2" role="group">
|
|
||||||
<a class="btn btn-info" target="_top" href="{config.relative_path}/admin/advanced/errors/export">
|
|
||||||
<i class="fa fa-download"></i> [[admin/advanced/errors:export-error-log]]
|
|
||||||
</a>
|
|
||||||
<button class="btn btn-danger" data-action="clear">
|
|
||||||
<i class="fa fa-trash"></i> [[admin/advanced/errors:clear-error-log]]
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<i class="fa fa-exclamation-triangle"></i> [[admin/advanced/errors:error.404]]
|
<i class="fa fa-exclamation-triangle"></i> [[admin/advanced/errors:error.404]]
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<table class="table table-striped">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<th>[[admin/advanced/errors:route]]</th>
|
<th>[[admin/advanced/errors:route]]</th>
|
||||||
<th>[[admin/advanced/errors:count]]</th>
|
<th>[[admin/advanced/errors:count]]</th>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{{ each not-found }}}
|
{{{ each not-found }}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{./value}</td>
|
<td>{./value}</td>
|
||||||
<td>{./score}</td>
|
<td>{./score}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{{ end }}}
|
{{{ end }}}
|
||||||
{{{ if !not-found.length }}}
|
{{{ if !not-found.length }}}
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="alert alert-success">
|
<div class="alert alert-success">
|
||||||
[[admin/advanced/errors:no-routes-not-found]]
|
[[admin/advanced/errors:no-routes-not-found]]
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{{ end }}}
|
{{{ end }}}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div class="row events">
|
<div class="row events px-lg-4">
|
||||||
<div class="col-lg-9">
|
<div class="col-lg-9">
|
||||||
<h5><i class="fa fa-calendar-o"></i> [[admin/advanced/events:events]]</h5>
|
<h5><i class="fa fa-calendar-o"></i> [[admin/advanced/events:events]]</h5>
|
||||||
{{{ if !events.length }}}
|
{{{ if !events.length }}}
|
||||||
@@ -6,25 +6,27 @@
|
|||||||
{{{ end }}}
|
{{{ end }}}
|
||||||
<div class="events-list">
|
<div class="events-list">
|
||||||
{{{ each events }}}
|
{{{ each events }}}
|
||||||
<div class="card mb-3">
|
<div class="card mb-3" data-eid="{events.eid}">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div data-eid="{events.eid}">
|
<div class="mb-3 d-flex flex-wrap justify-content-between align-items-center gap-1">
|
||||||
<div class="mb-3">
|
<div>
|
||||||
<span class="badge bg-primary">#{events.eid}</span>
|
<span class="badge bg-primary">#{events.eid}</span>
|
||||||
<span class="badge bg-info">{events.type}</span>
|
<span class="badge bg-info">{events.type}</span>
|
||||||
<span class="badge bg-info">uid {events.uid}</span>
|
<span class="badge bg-info">uid {events.uid}</span>
|
||||||
{{{ if events.ip }}}<span class="badge bg-info">{events.ip}</span>{{{ end }}}
|
{{{ if events.ip }}}<span class="badge bg-info">{events.ip}</span>{{{ end }}}
|
||||||
<a href="{config.relative_path}/user/{events.user.userslug}" target="_blank">{buildAvatar(events.user, "24px", true)}</a>
|
<a href="{config.relative_path}/user/{events.user.userslug}" target="_blank">{buildAvatar(events.user, "24px", true)}</a>
|
||||||
<a href="{config.relative_path}/user/{events.user.userslug}" target="_blank">{events.user.username}</a>
|
<a href="{config.relative_path}/user/{events.user.userslug}" target="_blank">{events.user.username}</a>
|
||||||
<span class="float-end delete-event ms-2 pointer"><i class="fa fa-trash-o"></i></span>
|
<span class="text-xs">{events.timestampISO}</span>
|
||||||
<span class="float-end">{events.timestampISO}</span>
|
</div>
|
||||||
|
<div>
|
||||||
|
<button class="btn btn-light btn-sm delete-event ms-2 pointer"><i class="fa fa-trash-o text-danger"></i></button>
|
||||||
</div>
|
</div>
|
||||||
<pre class="text-bg-light p-3">{events.jsonString}</pre>
|
|
||||||
</div>
|
</div>
|
||||||
|
<pre class="text-bg-light p-3">{events.jsonString}</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{{ end }}}
|
{{{ end }}}
|
||||||
<!-- IMPORT partials/paginator.tpl -->
|
<!-- IMPORT admin/partials/paginator.tpl -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-3 acp-sidebar">
|
<div class="col-lg-3 acp-sidebar">
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<div class="hooks-list panel-group" id="accordion" role="tablist" aria-multiselectable="true">
|
<div class="hooks-list panel-group px-lg-4" id="accordion" role="tablist" aria-multiselectable="true">
|
||||||
{{{ each hooks }}}
|
{{{ each hooks }}}
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header" role="tab">
|
<div class="card-header" role="tab">
|
||||||
<h6 class="mb-0">
|
<h6 class="mb-0">
|
||||||
<a style="text-transform: none;" role="button" data-bs-toggle="collapse" data-bs-parent="#accordion" data-bs-target="#{hooks.index}" aria-expanded="true" aria-controls="{hooks.index}">{hooks.hookName}</a>
|
<a style="text-transform: none;" class="text-reset text-decoration-none" role="button" data-bs-toggle="collapse" data-bs-parent="#accordion" data-bs-target="#{hooks.index}" aria-expanded="true" aria-controls="{hooks.index}">{hooks.hookName}</a>
|
||||||
<span class="float-end">{hooks.count} hooks</span>
|
<span class="float-end">{hooks.count} hooks</span>
|
||||||
</h6>
|
</h6>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div class="row logs">
|
<div class="row logs px-lg-4">
|
||||||
<div class="col-lg-9">
|
<div class="col-lg-9">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header"><i class="fa fa-file-text-o"></i> [[admin/advanced/logs:logs]]</div>
|
<div class="card-header"><i class="fa fa-file-text-o"></i> [[admin/advanced/logs:logs]]</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div id="customise" class="customise">
|
<div id="customise" class="customise px-lg-4">
|
||||||
<ul class="nav nav-pills mb-3">
|
<ul class="nav nav-pills mb-3">
|
||||||
<li class="nav-item"><a class="nav-link active" href="#custom-css" data-bs-toggle="tab">[[admin/appearance/customise:custom-css]]</a></li>
|
<li class="nav-item"><a class="nav-link active" href="#custom-css" data-bs-toggle="tab">[[admin/appearance/customise:custom-css]]</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="#custom-js" data-bs-toggle="tab">[[admin/appearance/customise:custom-js]]</a></li>
|
<li class="nav-item"><a class="nav-link" href="#custom-js" data-bs-toggle="tab">[[admin/appearance/customise:custom-js]]</a></li>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div id="skins" class="skins">
|
<div id="skins" class="skins px-lg-4">
|
||||||
<div class="directory row text-center" id="bootstrap_themes">
|
<div class="directory row text-center" id="bootstrap_themes">
|
||||||
<i class="fa fa-refresh fa-spin"></i> [[admin/appearance/skins:loading]]
|
<i class="fa fa-refresh fa-spin"></i> [[admin/appearance/skins:loading]]
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div id="themes" class="themes">
|
<div id="themes" class="themes px-lg-4">
|
||||||
<div class="directory row text-center" id="installed_themes">
|
<div class="directory row text-center" id="installed_themes">
|
||||||
<i class="fa fa-refresh fa-spin"></i> [[admin/appearance/themes:checking-for-installed]]
|
<i class="fa fa-refresh fa-spin"></i> [[admin/appearance/themes:checking-for-installed]]
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div class="row dashboard">
|
<div class="row dashboard px-lg-4">
|
||||||
<div class="col-lg-9">
|
<div class="col-lg-9">
|
||||||
<!-- IMPORT admin/partials/dashboard/graph.tpl -->
|
<!-- IMPORT admin/partials/dashboard/graph.tpl -->
|
||||||
<!-- IMPORT admin/partials/dashboard/stats.tpl -->
|
<!-- IMPORT admin/partials/dashboard/stats.tpl -->
|
||||||
@@ -70,11 +70,11 @@
|
|||||||
<div class="card-header">[[admin/dashboard:control-panel]]</div>
|
<div class="card-header">[[admin/dashboard:control-panel]]</div>
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
<div class="d-grid gap-2 mb-2">
|
<div class="d-grid gap-2 mb-2">
|
||||||
<button class="btn btn-block btn-warning restart"{{{ if !canRestart }}} disabled{{{ end }}}>[[admin/dashboard:restart]]</button>
|
<button component="restart" class="btn btn-block btn-warning btn-sm"{{{ if !canRestart }}} disabled{{{ end }}}>[[admin/dashboard:restart]]</button>
|
||||||
<button class="btn btn-block btn-danger rebuild-and-restart"{{{ if !canRestart }}} disabled{{{ end }}}>[[admin/dashboard:rebuild-and-restart]]</button>
|
<button component="rebuild-and-restart" class="btn btn-block btn-danger btn-sm"{{{ if !canRestart }}} disabled{{{ end }}}>[[admin/dashboard:rebuild-and-restart]]</button>
|
||||||
</div>
|
</div>
|
||||||
{{{ if lastrestart }}}
|
{{{ if lastrestart }}}
|
||||||
<p>
|
<p class="text-sm">
|
||||||
[[admin/dashboard:last-restarted-by]]<br />
|
[[admin/dashboard:last-restarted-by]]<br />
|
||||||
<a href="{config.relative_path}/uid/{lastrestart.uid}"><span class="badge bg-info">{lastrestart.user.username}</span></a> <span class="timeago" title="{lastrestart.timestampISO}"></span>
|
<a href="{config.relative_path}/uid/{lastrestart.uid}"><span class="badge bg-info">{lastrestart.user.username}</span></a> <span class="timeago" title="{lastrestart.timestampISO}"></span>
|
||||||
</p>
|
</p>
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
{{{ end }}}
|
{{{ end }}}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<a href="{config.relative_path}/admin/settings/advanced" class="btn btn-info btn-block" data-bs-placement="bottom" data-bs-toggle="tooltip" title="[[admin/dashboard:maintenance-mode-title]]">[[admin/dashboard:maintenance-mode]]</a>
|
<a href="{config.relative_path}/admin/settings/advanced" class="btn btn-info btn-block btn-sm" data-bs-placement="bottom" data-bs-toggle="tooltip" title="[[admin/dashboard:maintenance-mode-title]]">[[admin/dashboard:maintenance-mode]]</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
@@ -106,9 +106,9 @@
|
|||||||
<div class="card mb-3">
|
<div class="card mb-3">
|
||||||
<div class="card-header">[[admin/dashboard:updates]]</div>
|
<div class="card-header">[[admin/dashboard:updates]]</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="alert {{{ if lookupFailed }}}alert-danger{{{ else }}}{{{ if upgradeAvailable }}}alert-warning{{{ else }}}{{{ if currentPrerelease }}}alert-info{{{ else }}}alert-success{{{ end }}}{{{ end }}}{{{ end }}} version-check">
|
<div class="text-sm alert {{{ if lookupFailed }}}alert-danger{{{ else }}}{{{ if upgradeAvailable }}}alert-warning{{{ else }}}{{{ if currentPrerelease }}}alert-info{{{ else }}}alert-success{{{ end }}}{{{ end }}}{{{ end }}} version-check">
|
||||||
<p>[[admin/dashboard:running-version, {version}]]</p>
|
<p class="">[[admin/dashboard:running-version, {version}]]</p>
|
||||||
<p>
|
<p class="mb-0">
|
||||||
{{{ if lookupFailed }}}
|
{{{ if lookupFailed }}}
|
||||||
[[admin/dashboard:latest-lookup-failed]]
|
[[admin/dashboard:latest-lookup-failed]]
|
||||||
{{{ else }}}
|
{{{ else }}}
|
||||||
@@ -128,7 +128,7 @@
|
|||||||
{{{ end }}}
|
{{{ end }}}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p class="text-sm">
|
||||||
[[admin/dashboard:keep-updated]]
|
[[admin/dashboard:keep-updated]]
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,15 +1,10 @@
|
|||||||
<div class="row dashboard">
|
<div class="row dashboard px-lg-4">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<a class="btn btn-primary mb-3" href="{config.relative_path}/admin/dashboard">
|
|
||||||
<i class="fa fa-chevron-left"></i>
|
|
||||||
[[admin/dashboard:back-to-dashboard]]
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- IMPORT admin/partials/dashboard/graph.tpl -->
|
<!-- IMPORT admin/partials/dashboard/graph.tpl -->
|
||||||
<!-- IMPORT admin/partials/dashboard/stats.tpl -->
|
<!-- IMPORT admin/partials/dashboard/stats.tpl -->
|
||||||
|
|
||||||
<div class="alert alert-info">[[admin/dashboard:details.logins-static, {loginDays}]]</div>
|
<div class="alert alert-info">[[admin/dashboard:details.logins-static, {loginDays}]]</div>
|
||||||
<table class="table table-striped">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<th class="text-muted">[[admin/manage/users:users.username]]</th>
|
<th class="text-muted">[[admin/manage/users:users.username]]</th>
|
||||||
<th data-sort="joindate">[[admin/dashboard:details.logins-login-time]]</th>
|
<th data-sort="joindate">[[admin/dashboard:details.logins-login-time]]</th>
|
||||||
|
|||||||
@@ -1,26 +1,22 @@
|
|||||||
<div class="row dashboard">
|
<div class="row dashboard px-lg-4">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="d-flex gap-2 mb-3">
|
<div class="d-flex justify-content-end gap-2 mb-3">
|
||||||
<a class="btn btn-primary me-auto align-items-center" href="{config.relative_path}/admin/dashboard">
|
|
||||||
<i class="fa fa-chevron-left"></i>
|
|
||||||
[[admin/dashboard:back-to-dashboard]]
|
|
||||||
</a>
|
|
||||||
<form class="row row-cols-lg-auto g-3 align-items-center" method="GET">
|
<form class="row row-cols-lg-auto g-3 align-items-center" method="GET">
|
||||||
<div class="col-12 d-flex align-items-center gap-2">
|
<div class="col-12 d-flex align-items-center gap-2">
|
||||||
<label class="form-label mb-0" for="start">[[admin/dashboard:start]]</label>
|
<label class="form-label mb-0" for="start">[[admin/dashboard:start]]</label>
|
||||||
<input type="date" class="form-control" id="start" name="start" value="{startDate}">
|
<input type="date" class="form-control form-control-sm" id="start" name="start" value="{startDate}">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 d-flex align-items-center gap-2">
|
<div class="col-12 d-flex align-items-center gap-2">
|
||||||
<label class="form-label mb-0" for="end">[[admin/dashboard:end]]</label>
|
<label class="form-label mb-0" for="end">[[admin/dashboard:end]]</label>
|
||||||
<input type="date" class="form-control" id="end" name="end" value="{endDate}">
|
<input type="date" class="form-control form-control-sm" id="end" name="end" value="{endDate}">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<button onclick="$('form').submit();return false;"class="btn btn-primary" type="submit">Filter</button>
|
<button onclick="$('form').submit();return false;"class="btn btn-primary btn-sm" type="submit">Filter</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class="table table-sm table-striped search-list">
|
<table class="table table-sm search-list">
|
||||||
<thead>
|
<thead>
|
||||||
<th class="text-end">Count</th>
|
<th class="text-end">Count</th>
|
||||||
<th>Term</th>
|
<th>Term</th>
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
<div class="row dashboard">
|
<div class="row dashboard px-lg-4">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<a class="btn btn-primary mb-3" href="{config.relative_path}/admin/dashboard">
|
|
||||||
<i class="fa fa-chevron-left"></i>
|
|
||||||
[[admin/dashboard:back-to-dashboard]]
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- IMPORT admin/partials/dashboard/graph.tpl -->
|
<!-- IMPORT admin/partials/dashboard/graph.tpl -->
|
||||||
<!-- IMPORT admin/partials/dashboard/stats.tpl -->
|
<!-- IMPORT admin/partials/dashboard/stats.tpl -->
|
||||||
|
|
||||||
<table class="table table-striped topics-list">
|
<table class="table topics-list">
|
||||||
<tbody>
|
<tbody>
|
||||||
{{{ if !topics.length}}}
|
{{{ if !topics.length}}}
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
<div class="dashboard">
|
<div class="dashboard px-lg-4">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<a class="btn btn-primary mb-3" href="{config.relative_path}/admin/dashboard">
|
|
||||||
<i class="fa fa-chevron-left"></i>
|
|
||||||
[[admin/dashboard:back-to-dashboard]]
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- IMPORT admin/partials/dashboard/graph.tpl -->
|
<!-- IMPORT admin/partials/dashboard/graph.tpl -->
|
||||||
<!-- IMPORT admin/partials/dashboard/stats.tpl -->
|
<!-- IMPORT admin/partials/dashboard/stats.tpl -->
|
||||||
|
|
||||||
<table class="table table-striped users-list">
|
<table class="table users-list">
|
||||||
<thead>
|
<thead>
|
||||||
<th class="text-muted">[[admin/manage/users:users.uid]]</th>
|
<th class="text-muted">[[admin/manage/users:users.uid]]</th>
|
||||||
<th class="text-muted">[[admin/manage/users:users.username]]</th>
|
<th class="text-muted">[[admin/manage/users:users.username]]</th>
|
||||||
|
|||||||
@@ -7,23 +7,23 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<span>[[admin/development/info:nodes-responded, {nodeCount}, {timeout}]]</span>
|
<span>[[admin/development/info:nodes-responded, {nodeCount}, {timeout}]]</span>
|
||||||
|
|
||||||
<table class="table table-striped">
|
<table class="table table-sm text-sm">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td>[[admin/development/info:host]]</td>
|
<td class="fw-bold">[[admin/development/info:host]]</td>
|
||||||
<td class="text-center">[[admin/development/info:primary]]</td>
|
<td class="fw-bold text-center">[[admin/development/info:primary]]</td>
|
||||||
<td>[[admin/development/info:pid]]</td>
|
<td class="fw-bold">[[admin/development/info:pid]]</td>
|
||||||
<td>[[admin/development/info:nodejs]]</td>
|
<td class="fw-bold">[[admin/development/info:nodejs]]</td>
|
||||||
<td>[[admin/development/info:online]]</td>
|
<td class="fw-bold">[[admin/development/info:online]]</td>
|
||||||
<td>[[admin/development/info:git]]</td>
|
<td class="fw-bold">[[admin/development/info:git]]</td>
|
||||||
<td>[[admin/development/info:cpu-usage]]</td>
|
<td class="fw-bold">[[admin/development/info:cpu-usage]]</td>
|
||||||
<td>[[admin/development/info:process-memory]]</td>
|
<td class="fw-bold">[[admin/development/info:process-memory]]</td>
|
||||||
<td>[[admin/development/info:system-memory]]</td>
|
<td class="fw-bold">[[admin/development/info:system-memory]]</td>
|
||||||
<td>[[admin/development/info:load]]</td>
|
<td class="fw-bold">[[admin/development/info:load]]</td>
|
||||||
<td>[[admin/development/info:uptime]]</td>
|
<td class="fw-bold">[[admin/development/info:uptime]]</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody class="text-xs">
|
||||||
{{{ each info }}}
|
{{{ each info }}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{info.os.hostname}:{info.process.port}</td>
|
<td>{info.os.hostname}:{info.process.port}</td>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<!-- IMPORT admin/partials/settings/header.tpl -->
|
<div class="row logger settings px-lg-4">
|
||||||
<div class="row logger">
|
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">[[admin/development/logger:logger-settings]]</div>
|
<div class="card-header">[[admin/development/logger:logger-settings]]</div>
|
||||||
@@ -34,4 +33,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- IMPORT admin/partials/settings/footer.tpl -->
|
<!-- IMPORT admin/partials/save_button.tpl -->
|
||||||
|
|||||||
@@ -1,141 +1,137 @@
|
|||||||
{{{ if !canChangeState }}}
|
|
||||||
<div class="alert alert-warning">[[error:plugins-set-in-configuration]]</div>
|
|
||||||
{{{ end }}}
|
|
||||||
<ul class="nav nav-pills mb-3">
|
|
||||||
<li class="nav-item">
|
|
||||||
<button class="nav-link" data-bs-target="#trending" data-bs-toggle="tab">
|
|
||||||
[[admin/extend/plugins:trending]]
|
|
||||||
<i class="fa fa-star"></i>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<button class="nav-link active" data-bs-target="#installed" data-bs-toggle="tab">
|
|
||||||
[[admin/extend/plugins:installed]]
|
|
||||||
<span class="badge bg-light">{installedCount}</span>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<button class="nav-link" data-bs-target="#active" data-bs-toggle="tab">
|
|
||||||
[[admin/extend/plugins:active]]
|
|
||||||
<span class="badge bg-light">{activeCount}</span>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<button class="nav-link" data-bs-target="#deactive" data-bs-toggle="tab">
|
|
||||||
[[admin/extend/plugins:inactive]]
|
|
||||||
<span class="badge bg-light">{inactiveCount}</span>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<button class="nav-link" data-bs-target="#upgrade" data-bs-toggle="tab">
|
|
||||||
[[admin/extend/plugins:out-of-date]]
|
|
||||||
<span class="badge bg-light">{upgradeCount}</span>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<button class="nav-link" data-bs-target="#download" data-bs-toggle="tab">[[admin/extend/plugins:find-plugins]]</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<div class="plugins row">
|
<div class="tags d-flex flex-column gap-2 px-lg-4">
|
||||||
<div class="col-lg-9">
|
<div class="d-flex border-bottom py-2 m-0 sticky-top acp-page-main-header align-items-center justify-content-between flex-wrap gap-2">
|
||||||
<div class="tab-content">
|
<div class="">
|
||||||
<div class="tab-pane fade" id="trending">
|
<h4 class="fw-bold tracking-tight mb-0">[[admin/extend/plugins:plugins]]</h4>
|
||||||
<!-- IMPORT admin/partials/plugins/no-plugins.tpl -->
|
</div>
|
||||||
<ul class="trending">
|
<div class="d-flex align-items-center gap-1">
|
||||||
{{{ each trending }}}
|
<input autofocus class="form-control form-control-sm" type="text" id="plugin-search" placeholder="[[admin/extend/plugins:plugin-search-placeholder]]"/><br/>
|
||||||
<!-- IMPORT admin/partials/installed_plugin_item.tpl -->
|
<button class="btn btn-primary btn-sm text-nowrap" id="plugin-order">[[admin/extend/plugins:order-active]]</button>
|
||||||
{{{ end }}}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="tab-pane fade show active" id="installed">
|
|
||||||
<!-- IMPORT admin/partials/plugins/no-plugins.tpl -->
|
|
||||||
<ul class="installed">
|
|
||||||
{{{ each installed }}}
|
|
||||||
<!-- IMPORT admin/partials/installed_plugin_item.tpl -->
|
|
||||||
{{{ end }}}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="tab-pane fade" id="active">
|
|
||||||
<!-- IMPORT admin/partials/plugins/no-plugins.tpl -->
|
|
||||||
<ul class="active"></ul>
|
|
||||||
</div>
|
|
||||||
<div class="tab-pane fade" id="deactive">
|
|
||||||
<!-- IMPORT admin/partials/plugins/no-plugins.tpl -->
|
|
||||||
<ul class="deactive"></ul>
|
|
||||||
</div>
|
|
||||||
<div class="tab-pane fade" id="upgrade">
|
|
||||||
<!-- IMPORT admin/partials/plugins/no-plugins.tpl -->
|
|
||||||
<ul class="upgrade"></ul>
|
|
||||||
</div>
|
|
||||||
<div class="tab-pane fade" id="download">
|
|
||||||
<!-- IMPORT admin/partials/plugins/no-plugins.tpl -->
|
|
||||||
<ul class="download">
|
|
||||||
{{{ each download }}}
|
|
||||||
<!-- IMPORT admin/partials/download_plugin_item.tpl -->
|
|
||||||
{{{ end }}}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="">
|
||||||
|
{{{ if !canChangeState }}}
|
||||||
|
<div class="alert alert-warning">[[error:plugins-set-in-configuration]]</div>
|
||||||
|
{{{ end }}}
|
||||||
|
<ul class="nav nav-pills mb-3">
|
||||||
|
<li class="nav-item">
|
||||||
|
<button class="nav-link" data-bs-target="#trending" data-bs-toggle="tab">
|
||||||
|
[[admin/extend/plugins:trending]]
|
||||||
|
<i class="fa fa-star"></i>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<button class="nav-link active" data-bs-target="#installed" data-bs-toggle="tab">
|
||||||
|
[[admin/extend/plugins:installed]]
|
||||||
|
<span class="badge text-bg-light">{installedCount}</span>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<button class="nav-link" data-bs-target="#active" data-bs-toggle="tab">
|
||||||
|
[[admin/extend/plugins:active]]
|
||||||
|
<span class="badge text-bg-light">{activeCount}</span>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<button class="nav-link" data-bs-target="#deactive" data-bs-toggle="tab">
|
||||||
|
[[admin/extend/plugins:inactive]]
|
||||||
|
<span class="badge text-bg-light">{inactiveCount}</span>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<button class="nav-link" data-bs-target="#upgrade" data-bs-toggle="tab">
|
||||||
|
[[admin/extend/plugins:out-of-date]]
|
||||||
|
<span class="badge text-bg-light">{upgradeCount}</span>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<button class="nav-link" data-bs-target="#download" data-bs-toggle="tab">[[admin/extend/plugins:find-plugins]]</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<div class="acp-sidebar col-lg-3">
|
<div class="plugins row px-2">
|
||||||
<div class="card">
|
<div class="col-lg-9">
|
||||||
<div class="card-header">[[admin/extend/plugins:plugin-search]]</div>
|
<div class="tab-content">
|
||||||
<div class="card-body">
|
<div class="tab-pane fade" id="trending">
|
||||||
<input autofocus class="form-control" type="text" id="plugin-search" placeholder="[[admin/extend/plugins:plugin-search-placeholder]]"/><br/>
|
<!-- IMPORT admin/partials/plugins/no-plugins.tpl -->
|
||||||
</div>
|
<ul class="trending list-unstyled">
|
||||||
</div>
|
{{{ each trending }}}
|
||||||
|
<!-- IMPORT admin/partials/installed_plugin_item.tpl -->
|
||||||
<div class="card">
|
{{{ end }}}
|
||||||
<div class="card-body">
|
</ul>
|
||||||
<div class="form-check">
|
</div>
|
||||||
<input id="plugin-submit-usage" class="form-check-input" type="checkbox" data-field="submitPluginUsage" {{{ if submitPluginUsage }}}checked{{{ end }}}/>
|
<div class="tab-pane fade show active" id="installed">
|
||||||
<label for="plugin-submit-usage" class="form-check-label">[[admin/extend/plugins:submit-anonymous-usage]]</label>
|
<!-- IMPORT admin/partials/plugins/no-plugins.tpl -->
|
||||||
|
<ul class="installed list-unstyled">
|
||||||
|
{{{ each installed }}}
|
||||||
|
<!-- IMPORT admin/partials/installed_plugin_item.tpl -->
|
||||||
|
{{{ end }}}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="tab-pane fade" id="active">
|
||||||
|
<!-- IMPORT admin/partials/plugins/no-plugins.tpl -->
|
||||||
|
<ul class="active list-unstyled"></ul>
|
||||||
|
</div>
|
||||||
|
<div class="tab-pane fade" id="deactive">
|
||||||
|
<!-- IMPORT admin/partials/plugins/no-plugins.tpl -->
|
||||||
|
<ul class="deactive list-unstyled"></ul>
|
||||||
|
</div>
|
||||||
|
<div class="tab-pane fade" id="upgrade">
|
||||||
|
<!-- IMPORT admin/partials/plugins/no-plugins.tpl -->
|
||||||
|
<ul class="upgrade list-unstyled"></ul>
|
||||||
|
</div>
|
||||||
|
<div class="tab-pane fade" id="download">
|
||||||
|
<!-- IMPORT admin/partials/plugins/no-plugins.tpl -->
|
||||||
|
<ul class="download list-unstyled">
|
||||||
|
{{{ each download }}}
|
||||||
|
<!-- IMPORT admin/partials/download_plugin_item.tpl -->
|
||||||
|
{{{ end }}}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card">
|
<div class="acp-sidebar col-lg-3">
|
||||||
<div class="card-header">[[admin/extend/plugins:reorder-plugins]]</div>
|
<div class="card">
|
||||||
<div class="card-body d-grid">
|
<div class="card-body">
|
||||||
<button class="btn btn-outline-secondary" id="plugin-order">[[admin/extend/plugins:order-active]]</button>
|
<div class="form-check form-switch text-sm">
|
||||||
</div>
|
<input id="plugin-submit-usage" class="form-check-input" type="checkbox" data-field="submitPluginUsage" {{{ if submitPluginUsage }}}checked{{{ end }}}/>
|
||||||
</div>
|
<label for="plugin-submit-usage" class="form-check-label">[[admin/extend/plugins:submit-anonymous-usage]]</label>
|
||||||
|
</div>
|
||||||
<div class="card">
|
<hr/>
|
||||||
<div class="card-header">[[admin/extend/plugins:dev-interested]]</div>
|
<div>
|
||||||
<div class="card-body">
|
<div class="fw-semibold text-sm">[[admin/extend/plugins:dev-interested]]</div>
|
||||||
<p>
|
<p class="text-xs text-muted">
|
||||||
[[admin/extend/plugins:docs-info]]
|
[[admin/extend/plugins:docs-info]]
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal fade" id="order-active-plugins-modal">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h4 class="modal-title">[[admin/extend/plugins:order-active]]</h4>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
</div>
|
||||||
<p>
|
|
||||||
[[admin/extend/plugins:order.description]]
|
<div class="modal fade" id="order-active-plugins-modal">
|
||||||
</p>
|
<div class="modal-dialog">
|
||||||
<p>
|
<div class="modal-content">
|
||||||
[[admin/extend/plugins:order.explanation]]
|
<div class="modal-header">
|
||||||
</p>
|
<h4 class="modal-title">[[admin/extend/plugins:order-active]]</h4>
|
||||||
<ul class="plugin-list"></ul>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-body">
|
||||||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">[[global:buttons.close]]</button>
|
<p>
|
||||||
<button type="button" class="btn btn-primary" id="save-plugin-order">[[global:save]]</button>
|
[[admin/extend/plugins:order.description]]
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
[[admin/extend/plugins:order.explanation]]
|
||||||
|
</p>
|
||||||
|
<ul class="plugin-list"></ul>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">[[global:buttons.close]]</button>
|
||||||
|
<button type="button" class="btn btn-primary" id="save-plugin-order">[[global:save]]</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,80 +1,81 @@
|
|||||||
|
|
||||||
<div id="rewards">
|
<div class="tags d-flex flex-column gap-2 px-lg-4">
|
||||||
<ul id="active">
|
<div class="d-flex border-bottom py-2 m-0 sticky-top acp-page-main-header align-items-center justify-content-between flex-wrap gap-2">
|
||||||
{{{ each active }}}
|
<div class="">
|
||||||
<li data-rid="{active.rid}" data-id="{active.id}">
|
<h4 class="fw-bold tracking-tight mb-0">[[admin/extend/rewards:rewards]]</h4>
|
||||||
<div class="row">
|
</div>
|
||||||
<div class="col-12 col-lg-8">
|
<div class="d-flex align-items-center gap-1">
|
||||||
<form class="main d-inline-block">
|
<button id="new" class="btn btn-light btn-sm text-nowrap" type="button">
|
||||||
<div class="card card-body d-inline-block if-block">
|
<i class="fa fa-fw fa-plus"></i> [[admin/extend/rewards:add-reward]]
|
||||||
|
</button>
|
||||||
|
<button id="save" class="btn btn-primary btn-sm fw-semibold ff-secondary w-100 text-center text-nowrap">[[admin/admin:save-changes]]</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="rewards" class="">
|
||||||
|
<ul id="active" class="list-unstyled p-0 m-0">
|
||||||
|
{{{ each active }}}
|
||||||
|
<li data-rid="{active.rid}" data-id="{active.id}">
|
||||||
|
<div class="d-flex gap-1 mb-3 flex-wrap">
|
||||||
|
<form class="main d-flex gap-1">
|
||||||
|
<div class="card card-body m-0 if-block border-info border border-2">
|
||||||
<label class="form-label" for="condition-if-users">[[admin/extend/rewards:condition-if-users]]</label>
|
<label class="form-label" for="condition-if-users">[[admin/extend/rewards:condition-if-users]]</label>
|
||||||
<select id="condition-if-users" class="form-select" name="condition" data-selected="{active.condition}">
|
<select id="condition-if-users" class="form-select form-select-sm" name="condition" data-selected="{active.condition}">
|
||||||
{{{ each conditions }}}
|
{{{ each conditions }}}
|
||||||
<option value="{conditions.condition}">{conditions.name}</option>
|
<option value="{conditions.condition}">{conditions.name}</option>
|
||||||
{{{ end }}}
|
{{{ end }}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="card card-body d-inline-block this-block">
|
<div class="card card-body m-0 this-block border-warning border border-2">
|
||||||
<label class="form-label" for="condition-is">[[admin/extend/rewards:condition-is]]</label>
|
<label class="form-label" for="condition-is">[[admin/extend/rewards:condition-is]]</label>
|
||||||
<div class="row">
|
<div class="d-flex gap-1 flex-nowrap">
|
||||||
<div class="col-4">
|
<select id="condition-is" class="form-select form-select-sm" name="conditional" data-selected="{active.conditional}" style="max-width: 64px;">
|
||||||
<select id="condition-is" class="form-select" name="conditional" data-selected="{active.conditional}">
|
{{{ each conditionals }}}
|
||||||
{{{ each conditionals }}}
|
<option value="{conditionals.conditional}">{conditionals.name}</option>
|
||||||
<option value="{conditionals.conditional}">{conditionals.name}</option>
|
{{{ end }}}
|
||||||
{{{ end }}}
|
</select>
|
||||||
</select>
|
|
||||||
</div>
|
<input class="form-control form-control-sm" type="text" name="value" value="{active.value}" style="max-width: 64px;"/>
|
||||||
<div class="col-8">
|
|
||||||
<input class="form-control" type="text" name="value" value="{active.value}" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card card-body d-inline-block then-block">
|
<div class="card card-body m-0 then-block border-primary border border-2">
|
||||||
<label class="form-label" for="condition-then">[[admin/extend/rewards:condition-then]]</label>
|
<label class="form-label" for="condition-then">[[admin/extend/rewards:condition-then]]</label>
|
||||||
<select id="condition-then" class="form-select" name="rid" data-selected="{active.rid}">
|
<select id="condition-then" class="form-select form-select-sm" name="rid" data-selected="{active.rid}">
|
||||||
{{{ each ../../rewards }}}
|
{{{ each ../../rewards }}}
|
||||||
<option value="{rewards.rid}">{rewards.name}</option>
|
<option value="{rewards.rid}">{rewards.name}</option>
|
||||||
{{{ end }}}
|
{{{ end }}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
<form class="rewards">
|
||||||
<div class="col-12 col-lg-4">
|
<div class="inputs card card-body m-0 h-100 reward-block border-success border border-2"><div class="d-flex h-100 align-items-center">[[admin/extend/rewards:select-reward]]</div></div>
|
||||||
<form class="rewards d-inline-block">
|
|
||||||
<div class="inputs card card-body d-inline-block reward-block"></div>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="float-start">
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
<div class="card-body d-inline-block">
|
<form class="main d-flex gap-1 align-items-start gap-2">
|
||||||
<form class="main">
|
<div class="d-flex flex-column gap-0">
|
||||||
<label class="form-label" for="claimable">[[admin/extend/rewards:max-claims]] <small>[[admin/extend/rewards:zero-infinite]]</small></label>
|
<label class="form-label" for="claimable">[[admin/extend/rewards:max-claims]]</label>
|
||||||
<input id="claimable" class="form-control" type="text" name="claimable" value="{active.claimable}" placeholder="1" />
|
<p class="form-text mb-0">
|
||||||
|
[[admin/extend/rewards:zero-infinite]]
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<input id="claimable" class="form-control form-control-sm" type="text" name="claimable" value="{active.claimable}" placeholder="1" style="max-width: 64px;"/>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
<div class="">
|
||||||
|
|
||||||
|
<button class="btn btn-light btn-sm toggle disable {{{ if active.disabled }}}hidden{{{ end }}}"><i class="fa fa-ban text-danger"></i> [[admin/extend/rewards:disable]]</button>
|
||||||
|
|
||||||
|
<button class="btn btn-light btn-sm toggle enable {{{ if !active.disabled }}}hidden{{{ end }}}"><i class="fa fa-check text-success"></i> [[admin/extend/rewards:enable]]</button>
|
||||||
|
|
||||||
|
<button class="btn btn-light btn-sm delete"><i class="fa fa-trash text-danger"></i> [[admin/extend/rewards:delete]]</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="float-end">
|
<hr/>
|
||||||
<div class="card-body d-inline-block">
|
</li>
|
||||||
<button class="btn btn-danger delete">[[admin/extend/rewards:delete]]</button>
|
{{{ end }}}
|
||||||
{{{ if active.disabled }}}
|
</ul>
|
||||||
<button class="btn btn-success toggle">[[admin/extend/rewards:enable]]</button>
|
</div>
|
||||||
{{{ else }}}
|
|
||||||
<button class="btn btn-warning toggle">[[admin/extend/rewards:disable]]</button>
|
|
||||||
{{{ end }}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="clearfix"></div>
|
|
||||||
</li>
|
|
||||||
{{{ end }}}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="floating-button">
|
|
||||||
<button id="new" class="btn btn-primary position-fixed end-0 px-3 py-2 mb-4 me-4 rounded-circle fs-4" type="button" style="width: 64px; height: 64px;">
|
|
||||||
<i class="fa fa-fw fa-plus"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- IMPORT admin/partials/save_button.tpl -->
|
|
||||||
</div>
|
</div>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user