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
57c9d37f
You need to sign in or sign up before continuing.
Unverified
Commit
57c9d37f
authored
Jun 05, 2023
by
NGPixel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: admin locales UI + auto locales update + auto version check
parent
2587778e
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
90 additions
and
63 deletions
+90
-63
3.0.0.mjs
server/db/migrations/3.0.0.mjs
+3
-1
en.json
server/locales/en.json
+5
-0
check-version.mjs
server/tasks/simple/check-version.mjs
+9
-1
update-locales.mjs
server/tasks/simple/update-locales.mjs
+41
-1
apollo.js
ux/src/boot/apollo.js
+1
-1
AdminLocale.vue
ux/src/pages/AdminLocale.vue
+29
-57
user.js
ux/src/stores/user.js
+2
-2
No files found.
server/db/migrations/3.0.0.mjs
View file @
57c9d37f
...
@@ -514,7 +514,9 @@ export async function up (knex) {
...
@@ -514,7 +514,9 @@ export async function up (knex) {
{
{
key
:
'update'
,
key
:
'update'
,
value
:
{
value
:
{
locales
:
true
lastCheckedAt
:
null
,
version
:
null
,
versionDate
:
null
}
}
},
},
{
{
...
...
server/locales/en.json
View file @
57c9d37f
...
@@ -356,6 +356,7 @@
...
@@ -356,6 +356,7 @@
"admin.instances.lastSeen"
:
"Last Seen"
,
"admin.instances.lastSeen"
:
"Last Seen"
,
"admin.instances.subtitle"
:
"View a list of active instances"
,
"admin.instances.subtitle"
:
"View a list of active instances"
,
"admin.instances.title"
:
"Instances"
,
"admin.instances.title"
:
"Instances"
,
"admin.locale.active"
:
"Active Locales"
,
"admin.locale.activeNamespaces"
:
"Active Namespaces"
,
"admin.locale.activeNamespaces"
:
"Active Namespaces"
,
"admin.locale.autoUpdate.hint"
:
"Automatically download updates to this locale as they become available."
,
"admin.locale.autoUpdate.hint"
:
"Automatically download updates to this locale as they become available."
,
"admin.locale.autoUpdate.hintWithNS"
:
"Automatically download updates to all namespaced locales enabled below."
,
"admin.locale.autoUpdate.hintWithNS"
:
"Automatically download updates to all namespaced locales enabled below."
,
...
@@ -368,6 +369,8 @@
...
@@ -368,6 +369,8 @@
"admin.locale.download"
:
"Download"
,
"admin.locale.download"
:
"Download"
,
"admin.locale.downloadNew"
:
"Install New Locale"
,
"admin.locale.downloadNew"
:
"Install New Locale"
,
"admin.locale.downloadTitle"
:
"Download Locale"
,
"admin.locale.downloadTitle"
:
"Download Locale"
,
"admin.locale.forcePrefix"
:
"Force Locale Prefix"
,
"admin.locale.forcePrefixHint"
:
"Paths without a locale code will always be redirected to the primary locale."
,
"admin.locale.name"
:
"Name"
,
"admin.locale.name"
:
"Name"
,
"admin.locale.namespaces.hint"
:
"Enables multiple language versions of the same page."
,
"admin.locale.namespaces.hint"
:
"Enables multiple language versions of the same page."
,
"admin.locale.namespaces.label"
:
"Multilingual Namespaces"
,
"admin.locale.namespaces.label"
:
"Multilingual Namespaces"
,
...
@@ -375,6 +378,8 @@
...
@@ -375,6 +378,8 @@
"admin.locale.namespacingPrefixWarning.subtitle"
:
"Paths without a locale code will be automatically redirected to the base locale defined above."
,
"admin.locale.namespacingPrefixWarning.subtitle"
:
"Paths without a locale code will be automatically redirected to the base locale defined above."
,
"admin.locale.namespacingPrefixWarning.title"
:
"The locale code will be prefixed to all paths. (e.g. /{langCode}/page-name)"
,
"admin.locale.namespacingPrefixWarning.title"
:
"The locale code will be prefixed to all paths. (e.g. /{langCode}/page-name)"
,
"admin.locale.nativeName"
:
"Native Name"
,
"admin.locale.nativeName"
:
"Native Name"
,
"admin.locale.primary"
:
"Primary Locale"
,
"admin.locale.primaryHint"
:
"The locale to use as default / fallback for this site."
,
"admin.locale.rtl"
:
"RTL"
,
"admin.locale.rtl"
:
"RTL"
,
"admin.locale.settings"
:
"Locale Settings"
,
"admin.locale.settings"
:
"Locale Settings"
,
"admin.locale.sideload"
:
"Sideload Locale Package"
,
"admin.locale.sideload"
:
"Sideload Locale Package"
,
...
...
server/tasks/simple/check-version.mjs
View file @
57c9d37f
...
@@ -2,7 +2,15 @@ export async function task (payload) {
...
@@ -2,7 +2,15 @@ export async function task (payload) {
WIKI
.
logger
.
info
(
'Checking for latest version...'
)
WIKI
.
logger
.
info
(
'Checking for latest version...'
)
try
{
try
{
// TODO: Fetch latest version
const
resp
=
await
fetch
(
'https://api.github.com/repos/requarks/wiki/releases/latest'
).
then
(
r
=>
r
.
json
())
WIKI
.
logger
.
info
(
`Latest version is
${
resp
.
tag_name
}
.`
)
await
WIKI
.
db
.
knex
(
'settings'
).
where
(
'key'
,
'update'
).
update
({
value
:
{
lastCheckedAt
:
(
new
Date
).
toISOString
(),
version
:
resp
.
tag_name
,
versionDate
:
resp
.
published_at
}
})
WIKI
.
logger
.
info
(
'Checked for latest version: [ COMPLETED ]'
)
WIKI
.
logger
.
info
(
'Checked for latest version: [ COMPLETED ]'
)
}
catch
(
err
)
{
}
catch
(
err
)
{
...
...
server/tasks/simple/update-locales.mjs
View file @
57c9d37f
import
{
setTimeout
}
from
'node:timers/promises'
export
async
function
task
(
payload
)
{
export
async
function
task
(
payload
)
{
if
(
WIKI
.
config
.
update
?.
locales
===
false
)
{
return
}
WIKI
.
logger
.
info
(
'Fetching latest localization data...'
)
WIKI
.
logger
.
info
(
'Fetching latest localization data...'
)
try
{
try
{
// TODO: Fetch locale updates
const
metadata
=
await
fetch
(
'https://github.com/requarks/wiki-locales/raw/main/locales/metadata.json'
).
then
(
r
=>
r
.
json
())
for
(
const
lang
of
metadata
.
languages
)
{
// -> Build filename
const
langFilenameParts
=
[
lang
.
language
]
if
(
lang
.
region
)
{
langFilenameParts
.
push
(
lang
.
region
)
}
if
(
lang
.
script
)
{
langFilenameParts
.
push
(
lang
.
script
)
}
const
langFilename
=
langFilenameParts
.
join
(
'-'
)
WIKI
.
logger
.
debug
(
`Fetching updates for language
${
langFilename
}
...`
)
const
strings
=
await
fetch
(
`https://github.com/requarks/wiki-locales/raw/main/locales/
${
langFilename
}
.json`
).
then
(
r
=>
r
.
json
())
if
(
strings
)
{
await
WIKI
.
db
.
knex
(
'locales'
).
insert
({
code
:
langFilename
,
name
:
lang
.
name
,
nativeName
:
lang
.
localizedName
,
language
:
lang
.
language
,
region
:
lang
.
region
,
script
:
lang
.
script
,
isRTL
:
lang
.
isRtl
,
strings
}).
onConflict
(
'code'
).
merge
({
strings
,
updatedAt
:
new
Date
()
})
}
WIKI
.
logger
.
debug
(
`Updated strings for language
${
langFilename
}
.`
)
await
setTimeout
(
100
)
}
WIKI
.
logger
.
info
(
'Fetched latest localization data: [ COMPLETED ]'
)
WIKI
.
logger
.
info
(
'Fetched latest localization data: [ COMPLETED ]'
)
}
catch
(
err
)
{
}
catch
(
err
)
{
...
...
ux/src/boot/apollo.js
View file @
57c9d37f
...
@@ -29,7 +29,7 @@ export default boot(({ app }) => {
...
@@ -29,7 +29,7 @@ export default boot(({ app }) => {
}
}
// -> Refresh Token
// -> Refresh Token
if
(
!
userStore
.
isTokenValid
())
{
if
(
!
userStore
.
isTokenValid
(
{
minutes
:
1
}
))
{
if
(
!
fetching
)
{
if
(
!
fetching
)
{
refreshPromise
=
new
Promise
((
resolve
,
reject
)
=>
{
refreshPromise
=
new
Promise
((
resolve
,
reject
)
=>
{
(
async
()
=>
{
(
async
()
=>
{
...
...
ux/src/pages/AdminLocale.vue
View file @
57c9d37f
...
@@ -7,15 +7,6 @@ q-page.admin-locale
...
@@ -7,15 +7,6 @@ q-page.admin-locale
.text-h5.text-primary.animated.fadeInLeft
{{
t
(
'admin.locale.title'
)
}}
.text-h5.text-primary.animated.fadeInLeft
{{
t
(
'admin.locale.title'
)
}}
.text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s
{{
t
(
'admin.locale.subtitle'
)
}}
.text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s
{{
t
(
'admin.locale.subtitle'
)
}}
.col-auto.flex
.col-auto.flex
q-btn.q-mr-md(
icon='las la-download'
:label='t(`admin.locale.downloadNew`)'
unelevated
color='primary'
:disabled='state.loading > 0'
@click='installNewLocale'
)
q-separator.q-mr-md(vertical)
q-btn.q-mr-sm.acrylic-btn(
q-btn.q-mr-sm.acrylic-btn(
icon='las la-question-circle'
icon='las la-question-circle'
flat
flat
...
@@ -55,73 +46,65 @@ q-page.admin-locale
...
@@ -55,73 +46,65 @@ q-page.admin-locale
q-item
q-item
blueprint-icon(icon='translation')
blueprint-icon(icon='translation')
q-item-section
q-item-section
q-item-label
{{
state
.
namespacing
?
t
(
`admin.locale.base.labelWithNS`
)
:
t
(
`admin.locale.base.label
`
)
}}
q-item-label
{{
t
(
`admin.locale.primary
`
)
}}
q-item-label(caption)
{{
t
(
`admin.locale.
base.h
int`
)
}}
q-item-label(caption)
{{
t
(
`admin.locale.
primaryH
int`
)
}}
q-item-section
q-item-section
q-select(
q-select(
outlined
outlined
v-model='state.primary'
v-model='state.primary'
:options='
installedL
ocales'
:options='
state.l
ocales'
option-value='code'
option-value='code'
option-label='name'
option-label='name'
emit-value
emit-value
map-options
map-options
dense
dense
:aria-label='t(`admin.locale.
base.label
`)'
:aria-label='t(`admin.locale.
primary
`)'
)
)
q-separator.q-my-sm(inset)
q-separator.q-my-sm(inset)
q-item(tag='label')
q-item(tag='label')
blueprint-icon(icon='unit')
blueprint-icon(icon='unit')
q-item-section
q-item-section
q-item-label
{{
t
(
`admin.locale.
namespaces.label
`
)
}}
q-item-label
{{
t
(
`admin.locale.
forcePrefix
`
)
}}
q-item-label(caption)
{{
t
(
`admin.locale.
namespaces.h
int`
)
}}
q-item-label(caption)
{{
t
(
`admin.locale.
forcePrefixH
int`
)
}}
q-item-section(avatar)
q-item-section(avatar)
q-toggle(
q-toggle(
v-model='state.
namespacing
'
v-model='state.
forcePrefix
'
color='primary'
color='primary'
checked-icon='las la-check'
checked-icon='las la-check'
unchecked-icon='las la-times'
unchecked-icon='las la-times'
:aria-label='t(`admin.locale.
namespaces.label
`)'
:aria-label='t(`admin.locale.
forcePrefixHint
`)'
)
)
q-item
q-item-section
q-card.bg-info.text-white.rounded-borders(flat)
q-card-section.items-center(horizontal)
q-card-section.col-auto.q-pr-none
q-icon(name='las la-info-circle', size='sm')
q-card-section
span
{{
t
(
'admin.locale.namespacingPrefixWarning.title'
,
{
langCode
:
state
.
selectedLocale
}
)
}}
.
text
-
caption
.
text
-
yellow
-
1
{{
t
(
'admin.locale.namespacingPrefixWarning.subtitle'
)
}}
.
col
-
12
.
col
-
lg
-
5
//- -----------------------
//- -----------------------
//-
Namespacing
//-
Active Locales
//- -----------------------
//- -----------------------
q
-
card
.
q
-
pb
-
sm
(
v
-
if
=
'state.namespacing'
)
q-card.q-pb-sm
.q-mt-md
q-card-section
q-card-section
.
text
-
subtitle1
{{
t
(
'admin.locale.activeNamespaces'
)
}}
.text-subtitle1
{{
t
(
'admin.locale.active'
)
}}
.text-caption(:class='$q.dark.isActive ? `text-grey-4` : `text-grey-7`') Select the locales that can be used on this site.
q-item(
q-item(
v
-
for
=
'(lc, idx) of
installedL
ocales'
v-for='(lc, idx) of
state.l
ocales'
:key='lc.code'
:key='lc.code'
:tag='lc.code !== state.selectedLocale ? `label` : null'
:tag='lc.code !== state.selectedLocale ? `label` : null'
)
)
blueprint
-
icon
(:
text
=
'lc.
cod
e'
)
blueprint-icon(:text='lc.
languag
e')
q-item-section
q-item-section
q
-
item
-
label
{{
lc
.
name
}}
q-item-label
{{
lc
.
na
tiveNa
me
}}
q
-
item
-
label
(
caption
)
{{
lc
.
na
tiveName
}}
q-item-label(caption)
{{
lc
.
na
me
}}
(
{{
lc
.
code
}}
)
q-item-section(avatar)
q-item-section(avatar)
q-toggle(
q-toggle(
:
disable
=
'lc.code === state.
selectedLocale
'
:disable='lc.code === state.
primary
'
v
-
model
=
'state.
namespaces
'
v-model='state.
active
'
:val='lc.code'
:val='lc.code'
color
=
'primary
'
:color='lc.code === state.primary ? `secondary` : `primary`
'
checked-icon='las la-check'
checked-icon='las la-check'
unchecked-icon='las la-times'
unchecked-icon='las la-times'
:aria-label='lc.name'
:aria-label='lc.name'
)
)
.
q
-
pa
-
md
.
text
-
center
.
gt
-
md
(
v
-
else
)
.col-12.col-lg-5
.q-pa-md.text-center
img(src='/_assets/illustrations/undraw_world.svg', style='width: 80%;')
img(src='/_assets/illustrations/undraw_world.svg', style='width: 80%;')
//- q-separator.q-my-sm(inset)
//- q-separator.q-my-sm(inset)
...
@@ -150,7 +133,7 @@ q-page.admin-locale
...
@@ -150,7 +133,7 @@ q-page.admin-locale
<
script
setup
>
<
script
setup
>
import
gql
from
'graphql-tag'
import
gql
from
'graphql-tag'
import
{
cloneDeep
,
filter
}
from
'lodash-es'
import
{
cloneDeep
,
sortBy
}
from
'lodash-es'
import
LocaleInstallDialog
from
'../components/LocaleInstallDialog.vue'
import
LocaleInstallDialog
from
'../components/LocaleInstallDialog.vue'
...
@@ -186,15 +169,10 @@ const state = reactive({
...
@@ -186,15 +169,10 @@ const state = reactive({
loading
:
0
,
loading
:
0
,
locales
:
[],
locales
:
[],
primary
:
'en'
,
primary
:
'en'
,
forcePrefix
:
false
,
active
:
[]
active
:
[]
})
})
// COMPUTED
const
installedLocales
=
computed
(()
=>
{
return
filter
(
state
.
locales
,
[
'isInstalled'
,
true
])
}
)
// WATCHERS
// WATCHERS
watch
(()
=>
adminStore
.
currentSiteId
,
(
newValue
)
=>
{
watch
(()
=>
adminStore
.
currentSiteId
,
(
newValue
)
=>
{
...
@@ -226,9 +204,8 @@ async function load () {
...
@@ -226,9 +204,8 @@ async function load () {
completeness
completeness
code
code
createdAt
createdAt
isInstalled
installDate
isRTL
isRTL
language
name
name
nativeName
nativeName
region
region
...
@@ -241,7 +218,9 @@ async function load () {
...
@@ -241,7 +218,9 @@ async function load () {
id
id
locales {
locales {
primary
primary
active
active {
code
}
}
}
}
}
}
}
...
@@ -251,9 +230,9 @@ async function load () {
...
@@ -251,9 +230,9 @@ async function load () {
},
},
fetchPolicy
:
'network-only'
fetchPolicy
:
'network-only'
})
})
state
.
locales
=
cloneDeep
(
resp
?.
data
?.
locales
)
state
.
locales
=
sortBy
(
cloneDeep
(
resp
?.
data
?.
locales
),
[
'nativeName'
,
'name'
]
)
state
.
primary
=
cloneDeep
(
resp
?.
data
?.
siteById
?.
locales
?.
primary
)
state
.
primary
=
cloneDeep
(
resp
?.
data
?.
siteById
?.
locales
?.
primary
)
state
.
active
=
cloneDeep
(
resp
?.
data
?.
siteById
?.
locales
?.
active
??
[])
state
.
active
=
cloneDeep
(
resp
?.
data
?.
siteById
?.
locales
?.
active
??
[])
.
map
(
l
=>
l
.
code
)
if
(
!
state
.
active
.
includes
(
state
.
primary
))
{
if
(
!
state
.
active
.
includes
(
state
.
primary
))
{
state
.
active
.
push
(
state
.
primary
)
state
.
active
.
push
(
state
.
primary
)
}
}
...
@@ -337,17 +316,10 @@ async function save () {
...
@@ -337,17 +316,10 @@ async function save () {
})
})
const
resp
=
respRaw
?.
data
?.
localization
?.
updateLocale
?.
responseResult
||
{}
const
resp
=
respRaw
?.
data
?.
localization
?.
updateLocale
?.
responseResult
||
{}
if
(
resp
.
succeeded
)
{
if
(
resp
.
succeeded
)
{
// Change UI language
this
.
$i18n
.
locale
=
state
.
selectedLocale
$q
.
notify
({
$q
.
notify
({
type
:
'positive'
,
type
:
'positive'
,
message
:
'Locale settings updated successfully.'
message
:
'Locale settings updated successfully.'
})
})
setTimeout
(()
=>
{
window
.
location
.
reload
(
true
)
}
,
1000
)
}
else
{
}
else
{
$q
.
notify
({
$q
.
notify
({
type
:
'negative'
,
type
:
'negative'
,
...
...
ux/src/stores/user.js
View file @
57c9d37f
...
@@ -40,8 +40,8 @@ export const useUserStore = defineStore('user', {
...
@@ -40,8 +40,8 @@ export const useUserStore = defineStore('user', {
}
}
},
},
actions
:
{
actions
:
{
isTokenValid
()
{
isTokenValid
(
offset
)
{
return
this
.
exp
&&
this
.
exp
>
DateTime
.
now
(
)
return
this
.
exp
&&
this
.
exp
>
(
offset
?
DateTime
.
now
().
plus
(
offset
)
:
DateTime
.
now
()
)
},
},
loadToken
()
{
loadToken
()
{
if
(
!
this
.
token
)
{
return
}
if
(
!
this
.
token
)
{
return
}
...
...
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