From add3631b22b62b87037b1ba649816c692b8005c7 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sun, 3 Sep 2023 22:10:46 +0000 Subject: [PATCH] feat: view page source + download page --- server/db/migrations/3.0.0.mjs | 1 + server/models/pageHistory.mjs | 17 ++- server/models/pages.mjs | 1 + ux/public/_assets/icons/fluent-code.svg | 1 + ux/src/components/HeaderSearch.vue | 2 +- ux/src/components/MainOverlayDialog.vue | 4 + ux/src/components/PageActionsCol.vue | 7 +- ux/src/components/PageSourceOverlay.vue | 161 ++++++++++++++++++++++++ ux/src/css/app.scss | 2 +- ux/src/layouts/AdminLayout.vue | 2 +- ux/src/layouts/MainLayout.vue | 4 +- 11 files changed, 192 insertions(+), 10 deletions(-) create mode 100644 ux/public/_assets/icons/fluent-code.svg create mode 100644 ux/src/components/PageSourceOverlay.vue diff --git a/server/db/migrations/3.0.0.mjs b/server/db/migrations/3.0.0.mjs index a91b216236..2d83c27309 100644 --- a/server/db/migrations/3.0.0.mjs +++ b/server/db/migrations/3.0.0.mjs @@ -186,6 +186,7 @@ export async function up (knex) { table.uuid('id').notNullable().primary().defaultTo(knex.raw('gen_random_uuid()')) table.uuid('pageId').notNullable().index() table.string('action').defaultTo('updated') + table.string('reason') table.jsonb('affectedFields').notNullable().defaultTo('[]') table.string('locale', 10).notNullable().defaultTo('en') table.string('path').notNullable() diff --git a/server/models/pageHistory.mjs b/server/models/pageHistory.mjs index d3bc202b8d..c07006d6bb 100644 --- a/server/models/pageHistory.mjs +++ b/server/models/pageHistory.mjs @@ -77,21 +77,30 @@ export class PageHistory extends Model { */ static async addVersion(opts) { await WIKI.db.pageHistory.query().insert({ - pageId: opts.id, - siteId: opts.siteId, + action: opts.historyData?.action ?? 'updated', + affectedFields: JSON.stringify(opts.historyData?.affectedFields ?? []), + alias: opts.alias, + config: JSON.stringify(opts.config ?? {}), authorId: opts.authorId, content: opts.content, contentType: opts.contentType, description: opts.description, editor: opts.editor, hash: opts.hash, - publishState: opts.publishState, + icon: opts.icon, locale: opts.locale, + pageId: opts.id, path: opts.path, publishEndDate: opts.publishEndDate?.toISO(), publishStartDate: opts.publishStartDate?.toISO(), + publishState: opts.publishState, + reason: opts.historyData?.reason, + relations: JSON.stringify(opts.relations ?? []), + render: opts.render, + scripts: JSON.stringify(opts.scripts ?? {}), + siteId: opts.siteId, title: opts.title, - action: opts.action || 'updated', + toc: JSON.stringify(opts.toc ?? []), versionDate: opts.versionDate }) } diff --git a/server/models/pages.mjs b/server/models/pages.mjs index 14681be9ef..1be210cf2f 100644 --- a/server/models/pages.mjs +++ b/server/models/pages.mjs @@ -428,6 +428,7 @@ export class Page extends Model { const patch = {} const historyData = { action: 'updated', + reason: opts.reasonForChange, affectedFields: [] } let shouldUpdateSearch = false diff --git a/ux/public/_assets/icons/fluent-code.svg b/ux/public/_assets/icons/fluent-code.svg new file mode 100644 index 0000000000..85a9ccc212 --- /dev/null +++ b/ux/public/_assets/icons/fluent-code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ux/src/components/HeaderSearch.vue b/ux/src/components/HeaderSearch.vue index 01fd7d1b06..86ff852561 100644 --- a/ux/src/components/HeaderSearch.vue +++ b/ux/src/components/HeaderSearch.vue @@ -196,7 +196,7 @@ onBeforeUnmount(() => { color: #FFF; padding: .5rem 1rem 1rem; width: 100%; - backdrop-filter: blur(7px); + backdrop-filter: blur(7px) saturate(180%); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 1px 1px rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12); &-header { diff --git a/ux/src/components/MainOverlayDialog.vue b/ux/src/components/MainOverlayDialog.vue index 2d1d67a028..09dcc4cbed 100644 --- a/ux/src/components/MainOverlayDialog.vue +++ b/ux/src/components/MainOverlayDialog.vue @@ -31,6 +31,10 @@ const overlays = { loader: () => import('./NavEditOverlay.vue'), loadingComponent: LoadingGeneric }), + PageSource: defineAsyncComponent({ + loader: () => import('./PageSourceOverlay.vue'), + loadingComponent: LoadingGeneric + }), TableEditor: defineAsyncComponent({ loader: () => import('./TableEditorOverlay.vue'), loadingComponent: LoadingGeneric diff --git a/ux/src/components/PageActionsCol.vue b/ux/src/components/PageActionsCol.vue index 668baebed9..218755d277 100644 --- a/ux/src/components/PageActionsCol.vue +++ b/ux/src/components/PageActionsCol.vue @@ -76,6 +76,7 @@ icon='las la-code' :color='editorStore.isActive ? `white` : `grey`' aria-label='Page Source' + @click='viewPageSource' ) q-tooltip(anchor='center left' self='center right') Page Source template(v-if='!(editorStore.isActive && editorStore.mode === `create`)') @@ -87,7 +88,7 @@ aria-label='Page Actions' ) q-tooltip(anchor='center left' self='center right') Page Actions - q-menu( + q-menu.translucent-menu( anchor='top left' self='top right' auto-close @@ -199,6 +200,10 @@ function togglePageData () { }) } +function viewPageSource () { + siteStore.$patch({ overlay: 'PageSource', overlayOpts: { } }) +} + function duplicatePage () { $q.dialog({ component: defineAsyncComponent(() => import('../components/TreeBrowserDialog.vue')), diff --git a/ux/src/components/PageSourceOverlay.vue b/ux/src/components/PageSourceOverlay.vue new file mode 100644 index 0000000000..62b95a4b97 --- /dev/null +++ b/ux/src/components/PageSourceOverlay.vue @@ -0,0 +1,161 @@ + + + + + diff --git a/ux/src/css/app.scss b/ux/src/css/app.scss index b8c55b0889..b175e480c9 100644 --- a/ux/src/css/app.scss +++ b/ux/src/css/app.scss @@ -228,7 +228,7 @@ body::-webkit-scrollbar-thumb { background-color: rgba($dark,.7); } - backdrop-filter: blur(10px); + backdrop-filter: blur(10px) saturate(180%); > .q-card { background-color: transparent !important; diff --git a/ux/src/layouts/AdminLayout.vue b/ux/src/layouts/AdminLayout.vue index a0e6ae0ea1..c7ed44b395 100644 --- a/ux/src/layouts/AdminLayout.vue +++ b/ux/src/layouts/AdminLayout.vue @@ -394,7 +394,7 @@ onMounted(async () => { .admin-overlay { > .q-dialog__backdrop { background-color: rgba(0,0,0,.6); - backdrop-filter: blur(5px); + backdrop-filter: blur(5px) saturate(180%); } > .q-dialog__inner { padding: 24px 64px; diff --git a/ux/src/layouts/MainLayout.vue b/ux/src/layouts/MainLayout.vue index 9975cef94b..2e9922ce04 100644 --- a/ux/src/layouts/MainLayout.vue +++ b/ux/src/layouts/MainLayout.vue @@ -199,7 +199,7 @@ body.body--dark { .main-overlay { > .q-dialog__backdrop { background-color: rgba(0,0,0,.6); - backdrop-filter: blur(5px); + backdrop-filter: blur(5px) saturate(180%); } > .q-dialog__inner { padding: 24px 64px; @@ -216,7 +216,7 @@ body.body--dark { background-image: linear-gradient(to bottom, $dark-4 10px, $dark-4 11px, $dark-3); } border-radius: 6px; - box-shadow: 0 0 0 1px rgba(0,0,0,.5); + box-shadow: 0 0 30px 0 rgba(0,0,0,.3); } } }