diff --git a/server/db/migrations/3.0.0.mjs b/server/db/migrations/3.0.0.mjs
index a91b2162..2d83c273 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 d3bc202b..c07006d6 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 14681be9..1be210cf 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 00000000..85a9ccc2
--- /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 01fd7d1b..86ff8525 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 2d1d67a0..09dcc4cb 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 668baebe..218755d2 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 00000000..62b95a4b
--- /dev/null
+++ b/ux/src/components/PageSourceOverlay.vue
@@ -0,0 +1,161 @@
+
+q-layout(view='hHh lpR fFf', container)
+ q-header.card-header.q-px-md.q-py-sm
+ q-icon(name='img:/_assets/icons/fluent-code.svg', left, size='md')
+ span Page Source
+ q-space
+ transition(name='syncing')
+ q-spinner-tail.q-mr-sm(
+ v-show='state.loading > 0'
+ color='accent'
+ size='24px'
+ )
+ q-btn.q-mr-md(
+ icon='las la-download'
+ color='teal-3'
+ dense
+ flat
+ @click='download'
+ )
+ q-tooltip(anchor='bottom middle', self='top middle') {{t(`common.actions.download`)}}
+ q-btn(
+ icon='las la-times'
+ color='pink-2'
+ dense
+ flat
+ @click='close'
+ )
+ q-tooltip(anchor='bottom middle', self='top middle') {{t(`common.actions.close`)}}
+
+ q-page-container
+ q-page.bg-dark-6.text-white.font-robotomono.pagesource
+ q-scroll-area(
+ :thumb-style='thumb'
+ :bar-style='bar'
+ :horizontal-thumb-style='{ height: `5px` }'
+ style="width: 100%; height: calc(100vh - 100px);"
+ )
+ pre.q-px-md(v-text='state.content')
+
+
+
+
+
diff --git a/ux/src/css/app.scss b/ux/src/css/app.scss
index b8c55b08..b175e480 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 a0e6ae0e..c7ed44b3 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 9975cef9..2e9922ce 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);
}
}
}