Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wiki-js
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
wiki-js
Commits
add3631b
Unverified
Commit
add3631b
authored
Sep 03, 2023
by
NGPixel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: view page source + download page
parent
5a60fb11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
193 additions
and
10 deletions
+193
-10
3.0.0.mjs
server/db/migrations/3.0.0.mjs
+1
-0
pageHistory.mjs
server/models/pageHistory.mjs
+13
-4
pages.mjs
server/models/pages.mjs
+1
-0
fluent-code.svg
ux/public/_assets/icons/fluent-code.svg
+2
-0
HeaderSearch.vue
ux/src/components/HeaderSearch.vue
+1
-1
MainOverlayDialog.vue
ux/src/components/MainOverlayDialog.vue
+4
-0
PageActionsCol.vue
ux/src/components/PageActionsCol.vue
+6
-1
PageSourceOverlay.vue
ux/src/components/PageSourceOverlay.vue
+161
-0
app.scss
ux/src/css/app.scss
+1
-1
AdminLayout.vue
ux/src/layouts/AdminLayout.vue
+1
-1
MainLayout.vue
ux/src/layouts/MainLayout.vue
+2
-2
No files found.
server/db/migrations/3.0.0.mjs
View file @
add3631b
...
...
@@ -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
()
...
...
server/models/pageHistory.mjs
View file @
add3631b
...
...
@@ -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
})
}
...
...
server/models/pages.mjs
View file @
add3631b
...
...
@@ -428,6 +428,7 @@ export class Page extends Model {
const
patch
=
{}
const
historyData
=
{
action
:
'updated'
,
reason
:
opts
.
reasonForChange
,
affectedFields
:
[]
}
let
shouldUpdateSearch
=
false
...
...
ux/public/_assets/icons/fluent-code.svg
0 → 100644
View file @
add3631b
<svg
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 48 48"
width=
"96px"
height=
"96px"
><linearGradient
id=
"AkEixl0fFF2Red42g8M2Fa"
x1=
"12.727"
x2=
"4.186"
y1=
"33.727"
y2=
"25.186"
gradientUnits=
"userSpaceOnUse"
><stop
offset=
".365"
stop-color=
"#199ae0"
/><stop
offset=
".699"
stop-color=
"#1898de"
/><stop
offset=
".819"
stop-color=
"#1691d8"
/><stop
offset=
".905"
stop-color=
"#1186cc"
/><stop
offset=
".974"
stop-color=
"#0a75bc"
/><stop
offset=
"1"
stop-color=
"#076cb3"
/></linearGradient><path
fill=
"url(#AkEixl0fFF2Red42g8M2Fa)"
d=
"M0.29,24.701l9.509,9.509c0.387,0.387,1.014,0.387,1.401,0l2.009-2.009 c0.387-0.387,0.387-1.014,0-1.401L3.701,21.29c-0.387-0.387-1.014-0.387-1.401,0L0.29,23.299 C-0.097,23.686-0.097,24.314,0.29,24.701z"
/><linearGradient
id=
"AkEixl0fFF2Red42g8M2Fb"
x1=
"1.359"
x2=
"12.357"
y1=
"25.641"
y2=
"14.643"
gradientUnits=
"userSpaceOnUse"
><stop
offset=
"0"
stop-color=
"#32bdef"
/><stop
offset=
"1"
stop-color=
"#1ea2e4"
/></linearGradient><path
fill=
"url(#AkEixl0fFF2Red42g8M2Fb)"
d=
"M3.701,26.71l9.509-9.509c0.387-0.387,0.387-1.014,0-1.401l-2.009-2.009 c-0.387-0.387-1.014-0.387-1.401,0L0.29,23.299c-0.387,0.387-0.387,1.014,0,1.401l2.009,2.009 C2.686,27.097,3.314,27.097,3.701,26.71z"
/><linearGradient
id=
"AkEixl0fFF2Red42g8M2Fc"
x1=
"689.727"
x2=
"681.186"
y1=
"33.727"
y2=
"25.186"
gradientTransform=
"matrix(-1 0 0 1 725 0)"
gradientUnits=
"userSpaceOnUse"
><stop
offset=
".365"
stop-color=
"#199ae0"
/><stop
offset=
".699"
stop-color=
"#1898de"
/><stop
offset=
".819"
stop-color=
"#1691d8"
/><stop
offset=
".905"
stop-color=
"#1186cc"
/><stop
offset=
".974"
stop-color=
"#0a75bc"
/><stop
offset=
"1"
stop-color=
"#076cb3"
/></linearGradient><path
fill=
"url(#AkEixl0fFF2Red42g8M2Fc)"
d=
"M47.71,24.701l-9.509,9.509c-0.387,0.387-1.014,0.387-1.401,0l-2.009-2.009 c-0.387-0.387-0.387-1.014,0-1.401l9.509-9.509c0.387-0.387,1.014-0.387,1.401,0l2.009,2.009 C48.097,23.686,48.097,24.314,47.71,24.701z"
/><linearGradient
id=
"AkEixl0fFF2Red42g8M2Fd"
x1=
"678.359"
x2=
"689.357"
y1=
"25.641"
y2=
"14.643"
gradientTransform=
"matrix(-1 0 0 1 725 0)"
gradientUnits=
"userSpaceOnUse"
><stop
offset=
"0"
stop-color=
"#32bdef"
/><stop
offset=
"1"
stop-color=
"#1ea2e4"
/></linearGradient><path
fill=
"url(#AkEixl0fFF2Red42g8M2Fd)"
d=
"M44.299,26.71l-9.509-9.509c-0.387-0.387-0.387-1.014,0-1.401l2.009-2.009 c0.387-0.387,1.014-0.387,1.401,0l9.509,9.509c0.387,0.387,0.387,1.014,0,1.401l-2.009,2.009 C45.314,27.097,44.686,27.097,44.299,26.71z"
/><path
fill=
"#0078d4"
d=
"M30.25,2.5h-3.61c-0.473,0-0.882,0.332-0.979,0.795l-8.644,41.301 c-0.098,0.466,0.258,0.904,0.734,0.904h3.61c0.473,0,0.882-0.332,0.979-0.795l8.644-41.301C31.081,2.938,30.726,2.5,30.25,2.5z"
/></svg>
\ No newline at end of file
ux/src/components/HeaderSearch.vue
View file @
add3631b
...
...
@@ -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
{
...
...
ux/src/components/MainOverlayDialog.vue
View file @
add3631b
...
...
@@ -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
...
...
ux/src/components/PageActionsCol.vue
View file @
add3631b
...
...
@@ -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'
)),
...
...
ux/src/components/PageSourceOverlay.vue
0 → 100644
View file @
add3631b
<
template
lang=
"pug"
>
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')
</
template
>
<
script
setup
>
import
{
useI18n
}
from
'vue-i18n'
import
{
exportFile
,
useQuasar
}
from
'quasar'
import
{
onBeforeUnmount
,
onMounted
,
reactive
,
ref
}
from
'vue'
import
gql
from
'graphql-tag'
import
{
cloneDeep
}
from
'lodash-es'
import
{
usePageStore
}
from
'src/stores/page'
import
{
useSiteStore
}
from
'src/stores/site'
// QUASAR
const
$q
=
useQuasar
()
// STORES
const
pageStore
=
usePageStore
()
const
siteStore
=
useSiteStore
()
// I18N
const
{
t
}
=
useI18n
()
// DATA
const
state
=
reactive
({
loading
:
0
,
content
:
''
})
const
thumb
=
{
right
:
'2px'
,
borderRadius
:
'5px'
,
backgroundColor
:
'#FFF'
,
width
:
'5px'
,
opacity
:
0.25
}
const
bar
=
{
backgroundColor
:
'#000'
,
width
:
'9px'
,
opacity
:
0.25
}
const
contentTypes
=
{
markdown
:
{
ext
:
'md'
,
mime
:
'text/markdown'
},
html
:
{
ext
:
'html'
,
mime
:
'text/html'
}
}
// METHODS
function
download
()
{
const
fileType
=
contentTypes
[
state
.
contentType
]
??
{
ext
:
'txt'
,
mime
:
'text/plain'
}
exportFile
(
`page.
${
fileType
.
ext
}
`
,
state
.
content
,
{
mimeType
:
`
${
fileType
.
mime
}
;charset=UTF-8`
})
}
function
close
()
{
siteStore
.
$patch
({
overlay
:
''
})
}
async
function
load
()
{
state
.
loading
++
$q
.
loading
.
show
()
try
{
const
resp
=
await
APOLLO_CLIENT
.
query
({
query
:
gql
`
query loadPageSource (
$id: UUID!
) {
pageById(
id: $id
) {
id
content
contentType
}
}
`
,
variables
:
{
id
:
pageStore
.
id
},
fetchPolicy
:
'network-only'
})
const
pageData
=
cloneDeep
(
resp
?.
data
?.
pageById
??
{})
if
(
!
pageData
?.
id
)
{
throw
new
Error
(
'ERR_PAGE_NOT_FOUND'
)
}
state
.
content
=
pageData
.
content
state
.
contentType
=
pageData
.
contentType
}
catch
(
err
)
{
$q
.
notify
({
type
:
'negative'
,
message
:
err
.
message
})
}
$q
.
loading
.
hide
()
state
.
loading
--
}
onMounted
(()
=>
{
load
()
})
onBeforeUnmount
(()
=>
{
siteStore
.
overlayOpts
=
{}
})
</
script
>
<
style
lang=
"scss"
scoped
>
.pagesource
{
>
pre
{
margin
:
0
;
overflow-x
:
auto
;
}
}
</
style
>
ux/src/css/app.scss
View file @
add3631b
...
...
@@ -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
;
...
...
ux/src/layouts/AdminLayout.vue
View file @
add3631b
...
...
@@ -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
;
...
...
ux/src/layouts/MainLayout.vue
View file @
add3631b
...
...
@@ -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
);
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment