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
cbbc10da
Unverified
Commit
cbbc10da
authored
Jul 04, 2023
by
NGPixel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: admin search
parent
a806aa34
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
260 additions
and
10 deletions
+260
-10
db.mjs
server/core/db.mjs
+2
-2
3.0.0.mjs
server/db/migrations/3.0.0.mjs
+8
-0
system.mjs
server/graph/resolvers/system.mjs
+11
-0
system.graphql
server/graph/schemas/system.graphql
+11
-0
en.json
server/locales/en.json
+5
-0
fluent-find-and-replace.svg
ux/public/_assets/icons/fluent-find-and-replace.svg
+2
-0
undraw_file_searching.svg
ux/public/_assets/illustrations/undraw_file_searching.svg
+0
-0
HeaderNav.vue
ux/src/components/HeaderNav.vue
+12
-2
AdminLayout.vue
ux/src/layouts/AdminLayout.vue
+4
-0
AdminSearch.vue
ux/src/pages/AdminSearch.vue
+193
-0
Search.vue
ux/src/pages/Search.vue
+11
-3
routes.js
ux/src/router/routes.js
+1
-0
site.js
ux/src/stores/site.js
+0
-3
No files found.
server/core/db.mjs
View file @
cbbc10da
...
...
@@ -116,8 +116,8 @@ export default {
const
dbVersion
=
semver
.
coerce
(
resVersion
.
rows
[
0
].
server_version
,
{
loose
:
true
})
this
.
VERSION
=
dbVersion
.
version
this
.
LEGACY
=
dbVersion
.
major
<
16
if
(
dbVersion
.
major
<
1
1
)
{
WIKI
.
logger
.
error
(
'Your PostgreSQL database version is too old and unsupported by Wiki.js. Exiting...'
)
if
(
dbVersion
.
major
<
1
2
)
{
WIKI
.
logger
.
error
(
`Your PostgreSQL database version (
${
dbVersion
.
major
}
) is too old and unsupported by Wiki.js. Requires >= 12. Exiting...`
)
process
.
exit
(
1
)
}
WIKI
.
logger
.
info
(
`PostgreSQL
${
dbVersion
.
version
}
[
${
this
.
LEGACY
?
'LEGACY MODE'
:
'OK'
}
]`
)
...
...
server/db/migrations/3.0.0.mjs
View file @
cbbc10da
...
...
@@ -228,6 +228,7 @@ export async function up (knex) {
table
.
jsonb
(
'relations'
).
notNullable
().
defaultTo
(
'[]'
)
table
.
text
(
'content'
)
table
.
text
(
'render'
)
table
.
specificType
(
'ts'
,
'tsvector'
).
index
(
'ts_idx'
,
{
indexType
:
'GIN'
})
table
.
jsonb
(
'toc'
)
table
.
string
(
'editor'
).
notNullable
()
table
.
string
(
'contentType'
).
notNullable
()
...
...
@@ -489,6 +490,13 @@ export async function up (knex) {
}
},
{
key
:
'search'
,
value
:
{
termHighlighting
:
true
,
dictOverrides
:
[]
}
},
{
key
:
'security'
,
value
:
{
corsConfig
:
''
,
...
...
server/graph/resolvers/system.mjs
View file @
cbbc10da
...
...
@@ -76,6 +76,9 @@ export default {
{
column
:
'waitUntil'
,
order
:
'asc'
,
nulls
:
'first'
},
{
column
:
'createdAt'
,
order
:
'asc'
}
])
},
systemSearch
()
{
return
WIKI
.
config
.
search
}
},
Mutation
:
{
...
...
@@ -179,6 +182,14 @@ export default {
operation
:
generateSuccess
(
'System Flags applied successfully'
)
}
},
async
updateSystemSearch
(
obj
,
args
,
context
)
{
WIKI
.
config
.
search
=
_
.
defaultsDeep
(
_
.
omit
(
args
,
[
'__typename'
]),
WIKI
.
config
.
search
)
// TODO: broadcast config update
await
WIKI
.
configSvc
.
saveToDb
([
'search'
])
return
{
operation
:
generateSuccess
(
'System Search configuration applied successfully'
)
}
},
async
updateSystemSecurity
(
obj
,
args
,
context
)
{
WIKI
.
config
.
security
=
_
.
defaultsDeep
(
_
.
omit
(
args
,
[
'__typename'
]),
WIKI
.
config
.
security
)
// TODO: broadcast config update
...
...
server/graph/schemas/system.graphql
View file @
cbbc10da
...
...
@@ -13,6 +13,7 @@ extend type Query {
):
[
SystemJob
]
systemJobsScheduled
:
[
SystemJobScheduled
]
systemJobsUpcoming
:
[
SystemJobUpcoming
]
systemSearch
:
SystemSearch
}
extend
type
Mutation
{
...
...
@@ -32,6 +33,11 @@ extend type Mutation {
id
:
UUID
!
):
DefaultResponse
updateSystemSearch
(
termHighlighting
:
Boolean
dictOverrides
:
String
):
DefaultResponse
updateSystemFlags
(
flags
:
JSON
!
):
DefaultResponse
...
...
@@ -213,3 +219,8 @@ type SystemCheckUpdateResponse {
latest
:
String
latestDate
:
String
}
type
SystemSearch
{
termHighlighting
:
Boolean
dictOverrides
:
String
}
server/locales/en.json
View file @
cbbc10da
...
...
@@ -524,11 +524,16 @@
"admin.scheduler.useWorker"
:
"Execution Mode"
,
"admin.scheduler.waitUntil"
:
"Start"
,
"admin.search.configSaveSuccess"
:
"Search engine configuration saved successfully."
,
"admin.search.dictOverrides"
:
"PostgreSQL Dictionary Mapping Overrides"
,
"admin.search.dictOverridesHint"
:
"One override per line, in the format: en=english"
,
"admin.search.engineConfig"
:
"Engine Configuration"
,
"admin.search.engineNoConfig"
:
"This engine has no configuration options you can modify."
,
"admin.search.highlighting"
:
"Enable Term Highlighting"
,
"admin.search.highlightingHint"
:
"Whether to show the highlighted terms in search results. There is a slight performance impact when enabled."
,
"admin.search.indexRebuildSuccess"
:
"Index rebuilt successfully."
,
"admin.search.listRefreshSuccess"
:
"List of search engines has been refreshed."
,
"admin.search.rebuildIndex"
:
"Rebuild Index"
,
"admin.search.saveSuccess"
:
"Search engine configuration saved successfully"
,
"admin.search.searchEngine"
:
"Search Engine"
,
"admin.search.subtitle"
:
"Configure the search capabilities of your wiki"
,
"admin.search.title"
:
"Search Engine"
,
...
...
ux/public/_assets/icons/fluent-find-and-replace.svg
0 → 100644
View file @
cbbc10da
<svg
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 48 48"
width=
"96px"
height=
"96px"
><path
fill=
"#199be2"
d=
"M22.436,42.965l0.403-2.973c0.074-0.548-0.31-1.051-0.857-1.125 c-0.547-0.074-1.051,0.309-1.125,0.857l-0.403,2.973c-0.074,0.548,0.31,1.051,0.857,1.125S22.362,43.513,22.436,42.965z"
/><path
fill=
"#199be2"
d=
"M17.554,41.905l1.163-2.765c0.214-0.51-0.025-1.095-0.534-1.309 c-0.509-0.214-1.095,0.024-1.309,0.534l-1.163,2.765c-0.214,0.51,0.025,1.095,0.534,1.309 C16.754,42.653,17.34,42.415,17.554,41.905z"
/><path
fill=
"#199be2"
d=
"M25.922,38.878c-0.547,0.071-0.934,0.572-0.864,1.12l0.385,2.975 c0.071,0.548,0.572,0.934,1.12,0.864s0.934-0.572,0.864-1.12l-0.385-2.975C26.971,39.193,26.47,38.807,25.922,38.878z"
/><path
fill=
"#199be2"
d=
"M29.686,37.882c-0.511,0.209-0.756,0.793-0.546,1.304l1.137,2.776 c0.21,0.512,0.794,0.756,1.304,0.546c0.511-0.209,0.756-0.793,0.546-1.304l-1.137-2.776C30.781,37.917,30.197,37.673,29.686,37.882 z"
/><path
fill=
"#199be2"
d=
"M25.564,5.043l-0.403,2.973c-0.074,0.548,0.31,1.051,0.857,1.125 c0.547,0.074,1.051-0.309,1.125-0.857l0.403-2.973c0.074-0.548-0.31-1.051-0.857-1.125S25.638,4.495,25.564,5.043z"
/><path
fill=
"#199be2"
d=
"M30.446,6.103l-1.163,2.765c-0.214,0.51,0.025,1.095,0.534,1.309 c0.509,0.214,1.095-0.024,1.309-0.534l1.163-2.765c0.214-0.51-0.025-1.095-0.534-1.309C31.246,5.355,30.66,5.593,30.446,6.103z"
/><path
fill=
"#199be2"
d=
"M22.078,9.13c0.547-0.071,0.934-0.572,0.864-1.12l-0.385-2.975c-0.071-0.548-0.572-0.934-1.12-0.864 s-0.934,0.572-0.864,1.12l0.385,2.975C21.028,8.815,21.53,9.201,22.078,9.13z"
/><path
fill=
"#199be2"
d=
"M18.314,10.126c0.511-0.209,0.756-0.793,0.546-1.304l-1.137-2.776 c-0.21-0.512-0.794-0.756-1.304-0.546c-0.511,0.209-0.756,0.793-0.546,1.304L17.01,9.58C17.219,10.091,17.803,10.335,18.314,10.126 z"
/><path
fill=
"#199be2"
d=
"M33.55,35.722c0.018-0.018,0.037-0.036,0.057-0.052c6.186-5.085,7.33-14.153,2.555-20.631 c0.021-0.005,0.041-0.006,0.063-0.011c1.606-0.379,2.99-1.282,4.201-2.4c5.963,8.602,4.295,20.397-3.906,26.971 c-0.221,0.177-0.547,0.134-0.719-0.092c0,0-2.319-3.047-2.322-3.051C33.294,36.216,33.353,35.922,33.55,35.722z"
/><path
fill=
"#199be2"
d=
"M35.796,11.445l-0.881,6.486c-0.058,0.427,0.43,0.711,0.773,0.45l7.913-6.021 c0.342-0.26,0.198-0.806-0.229-0.864l-6.486-0.881C36.356,10.544,35.868,10.915,35.796,11.445z"
/><path
fill=
"#199be2"
d=
"M14.44,12.291c-0.019,0.017-0.039,0.034-0.058,0.051c-6.186,5.085-7.33,14.153-2.555,20.631 c-0.021,0.005-0.041,0.006-0.063,0.011c-1.606,0.379-2.99,1.282-4.201,2.4c-5.963-8.602-4.295-20.397,3.906-26.971 c0.221-0.177,0.547-0.134,0.719,0.092l2.322,3.051c0.084,0.133,0.146,0.265,0.119,0.426C14.608,12.11,14.532,12.207,14.44,12.291z"
/><path
fill=
"#199be2"
d=
"M12.192,36.568l0.881-6.486c0.058-0.427-0.43-0.711-0.773-0.45l-7.913,6.021 c-0.342,0.26-0.198,0.806,0.229,0.864l6.486,0.881C11.632,37.468,12.12,37.098,12.192,36.568z"
/><path
fill=
"#199be2"
d=
"M33.371,35.865c-0.468,0.429-0.486,1.161-0.039,1.613l10.133,10.229c0.391,0.391,1.024,0.391,1.414,0 l2.828-2.828c0.391-0.391,0.391-1.024,0-1.414L36.936,32.596L33.371,35.865z"
/></svg>
\ No newline at end of file
ux/public/_assets/illustrations/undraw_file_searching.svg
0 → 100644
View file @
cbbc10da
This diff is collapsed.
Click to expand it.
ux/src/components/HeaderNav.vue
View file @
cbbc10da
...
...
@@ -43,7 +43,14 @@ q-header.bg-header.text-white.site-header(
@blur='state.searchKbdShortcutShown = true'
)
template(v-slot:prepend)
q-icon(name='las la-search')
q-circular-progress.q-mr-xs(
v-if='siteStore.searchIsLoading'
indeterminate
rounded
color='primary'
size='20px'
)
q-icon(v-else, name='las la-search')
template(v-slot:append)
q-badge.q-mr-sm(
v-if='state.searchKbdShortcutShown'
...
...
@@ -176,7 +183,10 @@ function handleKeyPress (ev) {
}
function
onSearchEnter
()
{
if
(
!
route
.
path
.
startsWith
(
'/_search'
))
{
if
(
route
.
path
===
'/_search'
)
{
router
.
replace
({
path
:
'/_search'
,
query
:
{
q
:
siteStore
.
search
}
})
}
else
{
siteStore
.
searchIsLoading
=
true
router
.
push
({
path
:
'/_search'
,
query
:
{
q
:
siteStore
.
search
}
})
}
}
...
...
ux/src/layouts/AdminLayout.vue
View file @
cbbc10da
...
...
@@ -187,6 +187,10 @@ q-layout.admin(view='hHh Lpr lff')
q-item-section
{{
t
(
'admin.scheduler.title'
)
}}
q-item-section(side)
status-light(:color='adminStore.info.isSchedulerHealthy ? `positive` : `warning`', :pulse='!adminStore.info.isSchedulerHealthy')
q-item(to='/_admin/search', v-ripple, active-class='bg-primary text-white')
q-item-section(avatar)
q-icon(name='img:/_assets/icons/fluent-find-and-replace.svg')
q-item-section
{{
t
(
'admin.search.title'
)
}}
q-item(to='/_admin/security', v-ripple, active-class='bg-primary text-white')
q-item-section(avatar)
q-icon(name='img:/_assets/icons/fluent-protect.svg')
...
...
ux/src/pages/AdminSearch.vue
0 → 100644
View file @
cbbc10da
<
template
lang=
'pug'
>
q-page.admin-flags
.row.q-pa-md.items-center
.col-auto
img.admin-icon.animated.fadeInLeft(src='/_assets/icons/fluent-find-and-replace.svg')
.col.q-pl-md
.text-h5.text-primary.animated.fadeInLeft
{{
t
(
'admin.search.title'
)
}}
.text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s
{{
t
(
'admin.search.subtitle'
)
}}
.col-auto
q-btn.q-mr-sm.acrylic-btn(
icon='las la-question-circle'
flat
color='grey'
:aria-label='t(`common.actions.viewDocs`)'
:href='siteStore.docsBase + `/system/search`'
target='_blank'
type='a'
)
q-tooltip
{{
t
(
`common.actions.viewDocs`
)
}}
q-btn.q-mr-sm.acrylic-btn(
icon='las la-redo-alt'
flat
color='secondary'
:loading='state.loading > 0'
:aria-label='t(`common.actions.refresh`)'
@click='load'
)
q-tooltip
{{
t
(
`common.actions.refresh`
)
}}
q-btn(
unelevated
icon='mdi-check'
:label='t(`common.actions.apply`)'
color='secondary'
@click='save'
:loading='state.loading > 0'
)
q-separator(inset)
.row.q-pa-md.q-col-gutter-md
.col-12.col-lg-7
q-card.q-py-sm
q-item(tag='label')
blueprint-icon(icon='search')
q-item-section
q-item-label
{{
t
(
`admin.search.highlighting`
)
}}
q-item-label(caption)
{{
t
(
`admin.search.highlightingHint`
)
}}
q-item-section(avatar)
q-toggle(
v-model='state.config.termHighlighting'
color='primary'
checked-icon='las la-check'
unchecked-icon='las la-times'
:aria-label='t(`admin.search.highlighting`)'
)
q-separator.q-my-sm(inset)
q-item
blueprint-icon.self-start(icon='search')
q-item-section
q-item-label
{{
t
(
`admin.search.dictOverrides`
)
}}
q-input.q-mt-sm(
type='textarea'
v-model='state.config.dictOverrides'
outlined
:aria-label='t(`admin.search.dictOverrides`)'
:hint='t(`admin.search.dictOverridesHint`)'
input-style='min-height: 200px;'
)
.col-12.col-lg-5.gt-md
.q-pa-md.text-center
img(src='/_assets/illustrations/undraw_file_searching.svg', style='width: 80%;')
</
template
>
<
script
setup
>
import
gql
from
'graphql-tag'
import
{
onMounted
,
reactive
,
ref
}
from
'vue'
import
{
cloneDeep
,
omit
}
from
'lodash-es'
import
{
useMeta
,
useQuasar
}
from
'quasar'
import
{
useI18n
}
from
'vue-i18n'
import
{
useSiteStore
}
from
'src/stores/site'
import
{
useFlagsStore
}
from
'src/stores/flags'
// QUASAR
const
$q
=
useQuasar
()
// STORES
const
flagsStore
=
useFlagsStore
()
const
siteStore
=
useSiteStore
()
// I18N
const
{
t
}
=
useI18n
()
// META
useMeta
({
title
:
t
(
'admin.flags.title'
)
})
// DATA
const
state
=
reactive
({
loading
:
0
,
config
:
{
termHighlighting
:
false
,
dictOverrides
:
''
}
})
// METHODS
async
function
load
()
{
state
.
loading
++
$q
.
loading
.
show
()
try
{
const
resp
=
await
APOLLO_CLIENT
.
query
({
query
:
gql
`
query getSearchConfig {
systemSearch {
termHighlighting
dictOverrides
}
}
`
,
fetchPolicy
:
'network-only'
})
state
.
config
=
cloneDeep
(
resp
?.
data
?.
systemSearch
)
}
catch
(
err
)
{
$q
.
notify
({
type
:
'negative'
,
message
:
'Failed to load search config'
,
caption
:
err
.
message
})
}
$q
.
loading
.
hide
()
state
.
loading
--
}
async
function
save
()
{
state
.
loading
++
try
{
const
respRaw
=
await
APOLLO_CLIENT
.
mutate
({
mutation
:
gql
`
mutation saveSearchConfig (
$termHighlighting: Boolean
$dictOverrides: String
) {
updateSystemSearch(
termHighlighting: $termHighlighting
dictOverrides: $dictOverrides
) {
operation {
succeeded
slug
message
}
}
}
`
,
variables
:
state
.
config
})
const
resp
=
respRaw
?.
data
?.
updateSystemSearch
?.
operation
||
{}
if
(
resp
.
succeeded
)
{
$q
.
notify
({
type
:
'positive'
,
message
:
t
(
'admin.search.saveSuccess'
)
})
}
else
{
throw
new
Error
(
resp
.
message
)
}
}
catch
(
err
)
{
$q
.
notify
({
type
:
'negative'
,
message
:
'Failed to save search config'
,
caption
:
err
.
message
})
}
state
.
loading
--
}
// MOUNTED
onMounted
(
async
()
=>
{
load
()
})
</
script
>
<
style
lang=
'scss'
>
</
style
>
ux/src/pages/Search.vue
View file @
cbbc10da
...
...
@@ -94,9 +94,9 @@ q-layout(view='hHh Lpr lff')
.text-header.flex
span
{{
t
(
'search.results'
)
}}
q-space
span.text-caption #[strong
12
] results
span.text-caption #[strong
{{
state
.
items
}}
] results
q-list(separator, padding)
q-item(v-for='item of
12
', clickable)
q-item(v-for='item of
state.items
', clickable)
q-item-section(avatar)
q-avatar(color='primary' text-color='white' rounded icon='las la-file-alt')
q-item-section
...
...
@@ -169,7 +169,8 @@ const state = reactive({
filterTags
:
[],
filterLocale
:
[
'en'
],
filterEditor
:
''
,
filterPublishState
:
''
filterPublishState
:
''
,
items
:
25
})
const
editors
=
computed
(()
=>
{
...
...
@@ -205,6 +206,13 @@ function pageStyle (offset, height) {
'min-height'
:
`
${
height
-
100
-
offset
}
px`
}
}
// MOUNTED
onMounted
(()
=>
{
siteStore
.
searchIsLoading
=
false
})
</
script
>
<
style
lang=
"scss"
>
...
...
ux/src/router/routes.js
View file @
cbbc10da
...
...
@@ -63,6 +63,7 @@ const routes = [
{
path
:
'mail'
,
component
:
()
=>
import
(
'pages/AdminMail.vue'
)
},
{
path
:
'rendering'
,
component
:
()
=>
import
(
'pages/AdminRendering.vue'
)
},
{
path
:
'scheduler'
,
component
:
()
=>
import
(
'pages/AdminScheduler.vue'
)
},
{
path
:
'search'
,
component
:
()
=>
import
(
'pages/AdminSearch.vue'
)
},
{
path
:
'security'
,
component
:
()
=>
import
(
'pages/AdminSecurity.vue'
)
},
{
path
:
'system'
,
component
:
()
=>
import
(
'pages/AdminSystem.vue'
)
},
{
path
:
'terminal'
,
component
:
()
=>
import
(
'pages/AdminTerminal.vue'
)
},
...
...
ux/src/stores/site.js
View file @
cbbc10da
...
...
@@ -16,10 +16,7 @@ export const useSiteStore = defineStore('site', {
description
:
''
,
logoText
:
true
,
search
:
''
,
searchIsFocused
:
false
,
searchIsLoading
:
false
,
searchRestrictLocale
:
false
,
searchRestrictPath
:
false
,
printView
:
false
,
pageDataTemplates
:
[],
showSideNav
:
true
,
...
...
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