From 4a84db5b08c1faa59c3c3184a645d171ae962822 Mon Sep 17 00:00:00 2001 From: Ruslan Semak Date: Fri, 25 Apr 2025 16:05:55 +0300 Subject: [PATCH] feat: Added content page updating --- client/components/common/nav-header.vue | 28 ++++ .../common-pages-mutation-update-content.gql | 9 ++ server/graph/resolvers/page.js | 132 +++++++++++++++++- server/graph/schemas/page.graphql | 2 + server/models/pages.js | 15 -- 5 files changed, 165 insertions(+), 21 deletions(-) create mode 100644 client/graph/common/common-pages-mutation-update-content.gql diff --git a/client/components/common/nav-header.vue b/client/components/common/nav-header.vue index 0c34270c..9a64e526 100644 --- a/client/components/common/nav-header.vue +++ b/client/components/common/nav-header.vue @@ -188,6 +188,16 @@ span {{$t('common:actions.exit')}} v-divider(vertical) + //- Update Content + + template(v-if='isAuthenticated && isAdmin') + v-tooltip(bottom, v-if='mode !== `admin`') + template(v-slot:activator='{ on }') + v-btn(icon, tile, height='64', v-on='on', @click="updateContent") + v-icon(color='grey') mdi-file-document-refresh + span {{'Обновить Content'}} + v-divider(vertical) + //- ACCOUNT v-menu(v-if='isAuthenticated', offset-y, bottom, min-width='300', transition='slide-y-transition', left) @@ -254,6 +264,7 @@ import { get, sync } from 'vuex-pathify' import _ from 'lodash' import movePageMutation from 'gql/common/common-pages-mutation-move.gql' +import updateContentPageMutation from 'gql/common/common-pages-mutation-update-content.gql' /* global siteConfig, siteLangs */ @@ -372,6 +383,23 @@ export default { this.isDevMode = siteConfig.devMode === true }, methods: { + async updateContent() { + try { + await this.$apollo.mutate({ mutation: updateContentPageMutation }) + + this.$store.commit('showNotification', { + message: 'Content page updated successfully', + style: 'success', + icon: 'check' + }) + } catch (err) { + this.$store.commit('showNotification', { + message: 'Failed to update content page', + style: 'error', + icon: 'error' + }) + } + }, searchFocus () { this.searchIsFocused = true }, diff --git a/client/graph/common/common-pages-mutation-update-content.gql b/client/graph/common/common-pages-mutation-update-content.gql new file mode 100644 index 00000000..22b7e12a --- /dev/null +++ b/client/graph/common/common-pages-mutation-update-content.gql @@ -0,0 +1,9 @@ +mutation { + pages { + updateContent { + responseResult { + succeeded + } + } + } +} diff --git a/server/graph/resolvers/page.js b/server/graph/resolvers/page.js index daf56bf8..566e8315 100644 --- a/server/graph/resolvers/page.js +++ b/server/graph/resolvers/page.js @@ -1,5 +1,6 @@ const _ = require('lodash') const graphHelper = require('../../helpers/graph') +const moment = require('moment') /* global WIKI */ @@ -451,13 +452,132 @@ module.exports = { */ async updateIcon(obj, args, context) { try { - const page = await WIKI.models.pages.updateIcon({ - ...args, - user: context.req.user - }) + const { id, icon } = args + + await WIKI.models.pages.query() + .where('id', id) + .patch({ icon }) + + await WIKI.models.pages.rebuildTree() + return { - responseResult: graphHelper.generateSuccess('Page icon has been updated.'), - page + responseResult: graphHelper.generateSuccess('Page icon has been updated.') + } + } catch (err) { + return graphHelper.generateError(err) + } + }, + + /** + * UPDATE CONTENT PAGE + */ + async updateContent(obj, args, context) { + try { + const openTag = '\n' + const nbsp = '

 

\n' + const header = `

⛔️ Технический раздел! Обновление от ${moment().format('DD.MM.YYYY HH:mm')}

\n` + + const contentPageId = 232 + const planPageId = 2 + + const [page] = await WIKI.models.pages.query() + .select() + .where('id', contentPageId) + + if (!page) { + throw Error('Content page not found') + } + + const [planPage] = await WIKI.models.pages.query() + .select() + .where('id', planPageId) + + let pages = await WIKI.models.pages.query() + .select('id', 'path', 'orderPriority', 'title') + .orderBy(['localeCode', 'path']) + + /** + * Sorting order: + * Every not custom path without "/" + * Every not custom path with "/" + * Custom order for paths with "/" + */ + const customSortingOrder = [ + 'Intro', + 'WebStorm', + 'Git', + 'Software', + 'JavaScript', + 'TypeScript', + 'Backend-1', + 'Backend-2' + ] + pages = pages + .filter(({ path }) => !path.startsWith('Users')) + .sort((a, b) => { + const aHasSlash = a.path.includes('/') + const bHasSlash = b.path.includes('/') + + if (aHasSlash !== bHasSlash) { + return aHasSlash ? 1 : -1 + } + + const [aPathPart] = a.path.split('/') + const [bPathPart] = b.path.split('/') + + const aPriority = customSortingOrder.indexOf(aPathPart) + const bPriority = customSortingOrder.indexOf(bPathPart) + + if (aPriority !== bPriority) { + return aPriority > bPriority ? 1 : -1 + } + + const pathComparison = aPathPart.localeCompare(bPathPart) + + if (pathComparison !== 0) { + return pathComparison + } + + return a.orderPriority - b.orderPriority + }) + + let { content } = pages.reduce( + (acc, page) => { + const mentionedInPlan = planPage.content.includes(`data-page-id="${page.id}"`) + + const li = `
  • ` + const [section] = page.path.split('/') + + if (section !== acc.previousSection) { + if (acc.previousSection !== '') { + acc.content += closeTag + } + + acc.previousSection = section + + acc.content += nbsp + acc.content += `

    ${section}

    \n` + acc.content += openTag + } + + acc.content += li + + return acc + }, + { content: header, previousSection: '' } + ) + + content += closeTag + + await WIKI.models.pages.query() + .where('id', contentPageId) + .patch({ content }) + + await WIKI.models.pages.renderPage(page) + + return { + responseResult: graphHelper.generateSuccess('Page has been updated.') } } catch (err) { return graphHelper.generateError(err) diff --git a/server/graph/schemas/page.graphql b/server/graph/schemas/page.graphql index 0f5ba415..3bc0faec 100644 --- a/server/graph/schemas/page.graphql +++ b/server/graph/schemas/page.graphql @@ -126,6 +126,8 @@ type PageMutation { icon: String! ): PageResponse @auth(requires: ["write:pages", "manage:pages", "manage:system"]) + updateContent: DefaultResponse @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 a29c61fa..c2ebcb39 100644 --- a/server/models/pages.js +++ b/server/models/pages.js @@ -559,21 +559,6 @@ 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 *