From 598d01719817ef5740ca9bb6ef06d1d516163cb3 Mon Sep 17 00:00:00 2001 From: Ruslan Semak Date: Wed, 23 Apr 2025 12:18:30 +0300 Subject: [PATCH] feat: Added custom mdi icons for pages --- client/components/admin/admin-pages.vue | 66 +++++++++++++++++-- client/graph/admin/pages/update-page-icon.gql | 15 +++++ server/graph/resolvers/page.js | 18 +++++ server/graph/schemas/page.graphql | 5 ++ server/models/pages.js | 15 +++++ 5 files changed, 114 insertions(+), 5 deletions(-) create mode 100644 client/graph/admin/pages/update-page-icon.gql diff --git a/client/components/admin/admin-pages.vue b/client/components/admin/admin-pages.vue index 91a050ab..08b29e2c 100644 --- a/client/components/admin/admin-pages.vue +++ b/client/components/admin/admin-pages.vue @@ -94,9 +94,27 @@ :class="{'drag-over': dragOverIndex === props.index}" ) td.text-xs-right {{ props.item.id }} - td.text-xs-right {{ props.item.icon }} td - v-icon(v-if='props.item.icon') mdi-{{ props.item.icon }} + v-icon mdi-{{props.item.icon}} + td + v-edit-dialog( + :return-value.sync='props.item.icon' + @save='saveIcon(props.item)' + @cancel='cancelIcon' + @open='openIcon(props.item)' + large + ) + div {{ props.item.icon || '—' }} + template(v-slot:input) + v-text-field( + v-model='props.item.icon' + label='Edit icon name' + single-line + counter + autofocus + ) + template(v-slot:append) + v-icon(v-if='props.item.icon') mdi-{{ props.item.icon }} td.text-xs-right {{ props.item.orderPriority }} td .body-2: strong {{ props.item.title }} @@ -115,6 +133,7 @@ import _ from 'lodash' import pagesQuery from 'gql/admin/pages/pages-query-list.gql' import updatePagePriorityMutation from 'gql/admin/pages/update-page-priority.gql' +import updatePageIconMutation from 'gql/admin/pages/update-page-icon.gql' export default { data() { @@ -126,8 +145,8 @@ export default { pageTotal: 0, headers: [ { text: 'ID', value: 'id', width: 80, sortable: true }, - { text: 'Icon name', value: 'icon' }, { text: 'Icon', value: 'icon' }, + { text: 'Icon name', value: 'icon' }, { text: 'Order', value: 'orderPriority', width: 100 }, { text: 'Title', value: 'title' }, { text: 'Path', value: 'path' }, @@ -148,7 +167,10 @@ export default { dragged: false, draggedItem: null, draggedIndex: null, - dragOverIndex: null + dragOverIndex: null, + editedIcon: '', + editDialog: false, + editedItem: null } }, computed: { @@ -177,6 +199,40 @@ export default { } }, methods: { + openIcon(item) { + this.editedItem = item + this.editedIcon = item.icon + }, + async saveIcon(item) { + try { + await this.$apollo.mutate({ + mutation: updatePageIconMutation, + variables: { + id: item.id, + icon: item.icon + } + }) + + this.$store.commit('showNotification', { + message: 'Icon updated successfully', + style: 'success', + icon: 'check' + }) + } catch (error) { + this.$store.commit('showNotification', { + message: 'Failed to update icon', + style: 'error', + icon: 'error' + }) + // Восстановите предыдущее значение в случае ошибки + item.icon = this.editedIcon + } + }, + cancelIcon() { + if (this.editedItem) { + this.editedItem.icon = this.editedIcon + } + }, async saveNewOrder() { try { // Получаем страницы текущей группы @@ -329,7 +385,7 @@ export default { fetchPolicy: 'network-only', update: function (data) { const pages = data.pages.list.map(p => { - p.group = p.path.includes('/') ? p.path.split('/')[0] : null + p.group = `/${p.path.includes('/') ? p.path.split('/')[0] : ''}` return p }) diff --git a/client/graph/admin/pages/update-page-icon.gql b/client/graph/admin/pages/update-page-icon.gql new file mode 100644 index 00000000..1eec0559 --- /dev/null +++ b/client/graph/admin/pages/update-page-icon.gql @@ -0,0 +1,15 @@ +mutation ( + $id: Int! + $icon: String! +) { + pages { + updateIcon( + id: $id + icon: $icon + ) { + responseResult { + succeeded + } + } + } +} diff --git a/server/graph/resolvers/page.js b/server/graph/resolvers/page.js index f8deda94..daf56bf8 100644 --- a/server/graph/resolvers/page.js +++ b/server/graph/resolvers/page.js @@ -446,6 +446,24 @@ module.exports = { } }, + /** + * UPDATE PAGE ICON + */ + async updateIcon(obj, args, context) { + try { + const page = await WIKI.models.pages.updateIcon({ + ...args, + user: context.req.user + }) + return { + responseResult: graphHelper.generateSuccess('Page icon has been updated.'), + page + } + } catch (err) { + return graphHelper.generateError(err) + } + }, + /** * CONVERT PAGE */ diff --git a/server/graph/schemas/page.graphql b/server/graph/schemas/page.graphql index a5fc077d..0f5ba415 100644 --- a/server/graph/schemas/page.graphql +++ b/server/graph/schemas/page.graphql @@ -121,6 +121,11 @@ type PageMutation { pages: [PageOrderInput!]! ): PageResponse @auth(requires: ["write:pages", "manage:pages", "manage:system"]) + updateIcon( + id: Int! + icon: String! + ): PageResponse @auth(requires: ["write:pages", "manage:pages", "manage:system"]) + convert( id: Int! editor: String! diff --git a/server/models/pages.js b/server/models/pages.js index 9aa3f9e4..11786b88 100644 --- a/server/models/pages.js +++ b/server/models/pages.js @@ -556,6 +556,21 @@ module.exports = class Page extends Model { await WIKI.models.pages.rebuildTree() } + /** + * Update an Icon of Existing Page + * @param {Object} opts Page Properties + * @returns {Promise} Promise of the Page Model Instance + */ + static async updateIcon(opts) { + const { id, icon } = opts + + await WIKI.models.pages.query() + .where('id', id) + .patch({ icon }) + + await WIKI.models.pages.rebuildTree() + } + /** * Convert an Existing Page *