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
bb4a1e6b
Unverified
Commit
bb4a1e6b
authored
Jun 11, 2023
by
NGPixel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: check for updates dialog
parent
57c9d37f
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
95 additions
and
139 deletions
+95
-139
config.mjs
server/core/config.mjs
+1
-1
system.mjs
server/graph/resolvers/system.mjs
+22
-3
system.graphql
server/graph/schemas/system.graphql
+9
-0
en.json
server/locales/en.json
+3
-0
check-version.mjs
server/tasks/simple/check-version.mjs
+7
-7
CheckUpdateDialog.vue
ux/src/components/CheckUpdateDialog.vue
+50
-23
AdminLocale.vue
ux/src/pages/AdminLocale.vue
+0
-22
AdminSystem.vue
ux/src/pages/AdminSystem.vue
+3
-83
No files found.
server/core/config.mjs
View file @
bb4a1e6b
...
@@ -109,7 +109,7 @@ export default {
...
@@ -109,7 +109,7 @@ export default {
*/
*/
async
saveToDb
(
keys
,
propagate
=
true
)
{
async
saveToDb
(
keys
,
propagate
=
true
)
{
try
{
try
{
for
(
le
t
key
of
keys
)
{
for
(
cons
t
key
of
keys
)
{
let
value
=
get
(
WIKI
.
config
,
key
,
null
)
let
value
=
get
(
WIKI
.
config
,
key
,
null
)
if
(
!
isPlainObject
(
value
))
{
if
(
!
isPlainObject
(
value
))
{
value
=
{
v
:
value
}
value
=
{
v
:
value
}
...
...
server/graph/resolvers/system.mjs
View file @
bb4a1e6b
...
@@ -98,6 +98,25 @@ export default {
...
@@ -98,6 +98,25 @@ export default {
return
generateError
(
err
)
return
generateError
(
err
)
}
}
},
},
async
checkForUpdates
(
obj
,
args
,
context
)
{
try
{
const
renderJob
=
await
WIKI
.
scheduler
.
addJob
({
task
:
'checkVersion'
,
maxRetries
:
0
,
promise
:
true
})
await
renderJob
.
promise
return
{
operation
:
generateSuccess
(
'Checked for latest version successfully.'
),
current
:
WIKI
.
version
,
latest
:
WIKI
.
config
.
update
.
version
,
latestDate
:
WIKI
.
config
.
update
.
versionDate
}
}
catch
(
err
)
{
WIKI
.
logger
.
warn
(
err
)
return
generateError
(
err
)
}
},
async
disconnectWS
(
obj
,
args
,
context
)
{
async
disconnectWS
(
obj
,
args
,
context
)
{
WIKI
.
servers
.
ws
.
disconnectSockets
(
true
)
WIKI
.
servers
.
ws
.
disconnectSockets
(
true
)
WIKI
.
logger
.
info
(
'All active websocket connections have been terminated.'
)
WIKI
.
logger
.
info
(
'All active websocket connections have been terminated.'
)
...
@@ -205,13 +224,13 @@ export default {
...
@@ -205,13 +224,13 @@ export default {
return
_
.
toSafeInteger
(
results
?.
total
)
===
0
return
_
.
toSafeInteger
(
results
?.
total
)
===
0
},
},
latestVersion
()
{
latestVersion
()
{
return
WIKI
.
system
.
updates
.
version
return
WIKI
.
config
.
update
.
version
},
},
latestVersionReleaseDate
()
{
latestVersionReleaseDate
()
{
return
DateTime
.
fromISO
(
WIKI
.
system
.
updates
.
release
Date
).
toJSDate
()
return
DateTime
.
fromISO
(
WIKI
.
config
.
update
.
version
Date
).
toJSDate
()
},
},
nodeVersion
()
{
nodeVersion
()
{
return
process
.
version
.
substr
(
1
)
return
process
.
version
.
substr
ing
(
1
)
},
},
async
operatingSystem
()
{
async
operatingSystem
()
{
let
osLabel
=
`
${
os
.
type
()}
(
${
os
.
platform
()}
)
${
os
.
release
()}
${
os
.
arch
()}
`
let
osLabel
=
`
${
os
.
type
()}
(
${
os
.
platform
()}
)
${
os
.
release
()}
${
os
.
arch
()}
`
...
...
server/graph/schemas/system.graphql
View file @
bb4a1e6b
...
@@ -20,6 +20,8 @@ extend type Mutation {
...
@@ -20,6 +20,8 @@ extend type Mutation {
id
:
UUID
!
id
:
UUID
!
):
DefaultResponse
):
DefaultResponse
checkForUpdates
:
SystemCheckUpdateResponse
disconnectWS
:
DefaultResponse
disconnectWS
:
DefaultResponse
installExtension
(
installExtension
(
...
@@ -204,3 +206,10 @@ enum SystemJobState {
...
@@ -204,3 +206,10 @@ enum SystemJobState {
FAILED
FAILED
INTERRUPTED
INTERRUPTED
}
}
type
SystemCheckUpdateResponse
{
operation
:
Operation
current
:
String
latest
:
String
latestDate
:
String
}
server/locales/en.json
View file @
bb4a1e6b
...
@@ -770,17 +770,20 @@
...
@@ -770,17 +770,20 @@
"admin.system.databaseHostHint"
:
"The hostname used to access the database."
,
"admin.system.databaseHostHint"
:
"The hostname used to access the database."
,
"admin.system.dbPartialSupport"
:
"Your database version is not fully supported. Some functionality may be limited or not work as expected."
,
"admin.system.dbPartialSupport"
:
"Your database version is not fully supported. Some functionality may be limited or not work as expected."
,
"admin.system.engines"
:
"Server Engines"
,
"admin.system.engines"
:
"Server Engines"
,
"admin.system.fetchingLatestVersionInfo"
:
"Fetching latest version info..."
,
"admin.system.hostInfo"
:
"Server Host Information"
,
"admin.system.hostInfo"
:
"Server Host Information"
,
"admin.system.hostname"
:
"Hostname"
,
"admin.system.hostname"
:
"Hostname"
,
"admin.system.hostnameHint"
:
"The hostname of the server / container."
,
"admin.system.hostnameHint"
:
"The hostname of the server / container."
,
"admin.system.latestVersion"
:
"Latest Version"
,
"admin.system.latestVersion"
:
"Latest Version"
,
"admin.system.latestVersionHint"
:
"The latest version available to install."
,
"admin.system.latestVersionHint"
:
"The latest version available to install."
,
"admin.system.newVersionAvailable"
:
"A new version is available."
,
"admin.system.nodejsHint"
:
"The version of Node.js installed."
,
"admin.system.nodejsHint"
:
"The version of Node.js installed."
,
"admin.system.os"
:
"Operating System"
,
"admin.system.os"
:
"Operating System"
,
"admin.system.osHint"
:
"The OS Wiki.js is running on."
,
"admin.system.osHint"
:
"The OS Wiki.js is running on."
,
"admin.system.published"
:
"Published"
,
"admin.system.published"
:
"Published"
,
"admin.system.ramUsage"
:
"RAM Usage: {used} / {total}"
,
"admin.system.ramUsage"
:
"RAM Usage: {used} / {total}"
,
"admin.system.refreshSuccess"
:
"System Info has been refreshed."
,
"admin.system.refreshSuccess"
:
"System Info has been refreshed."
,
"admin.system.runningLatestVersion"
:
"You're running the latest version."
,
"admin.system.subtitle"
:
"Information about your server / client"
,
"admin.system.subtitle"
:
"Information about your server / client"
,
"admin.system.title"
:
"System Info"
,
"admin.system.title"
:
"System Info"
,
"admin.system.totalRAM"
:
"Total RAM"
,
"admin.system.totalRAM"
:
"Total RAM"
,
...
...
server/tasks/simple/check-version.mjs
View file @
bb4a1e6b
...
@@ -3,14 +3,14 @@ export async function task (payload) {
...
@@ -3,14 +3,14 @@ export async function task (payload) {
try
{
try
{
const
resp
=
await
fetch
(
'https://api.github.com/repos/requarks/wiki/releases/latest'
).
then
(
r
=>
r
.
json
())
const
resp
=
await
fetch
(
'https://api.github.com/repos/requarks/wiki/releases/latest'
).
then
(
r
=>
r
.
json
())
const
strictVersion
=
resp
.
tag_name
.
indexOf
(
'v'
)
===
0
?
resp
.
tag_name
.
substring
(
1
)
:
resp
.
tag_name
WIKI
.
logger
.
info
(
`Latest version is
${
resp
.
tag_name
}
.`
)
WIKI
.
logger
.
info
(
`Latest version is
${
resp
.
tag_name
}
.`
)
await
WIKI
.
db
.
knex
(
'settings'
).
where
(
'key'
,
'update'
).
update
({
WIKI
.
config
.
update
=
{
value
:
{
lastCheckedAt
:
(
new
Date
).
toISOString
(),
lastCheckedAt
:
(
new
Date
).
toISOString
(),
version
:
strictVersion
,
version
:
resp
.
tag_name
,
versionDate
:
resp
.
published_at
versionDate
:
resp
.
published_at
}
}
await
WIKI
.
config
.
saveToDb
([
'update'
])
})
WIKI
.
logger
.
info
(
'Checked for latest version: [ COMPLETED ]'
)
WIKI
.
logger
.
info
(
'Checked for latest version: [ COMPLETED ]'
)
}
catch
(
err
)
{
}
catch
(
err
)
{
...
...
ux/src/components/CheckUpdateDialog.vue
View file @
bb4a1e6b
...
@@ -7,17 +7,25 @@ q-dialog(ref='dialogRef', @hide='onDialogHide')
...
@@ -7,17 +7,25 @@ q-dialog(ref='dialogRef', @hide='onDialogHide')
q-card-section
q-card-section
.q-pa-md.text-center
.q-pa-md.text-center
img(src='/_assets/illustrations/undraw_going_up.svg', style='width: 150px;')
img(src='/_assets/illustrations/undraw_going_up.svg', style='width: 150px;')
q-linear-progress(
template(v-if='state.isLoading')
indeterminate
q-linear-progress(
size='lg'
indeterminate
rounded
size='lg'
)
rounded
.q-mt-sm.text-center.text-caption Fetching latest version info...
)
.q-mt-sm.text-center.text-caption
{{
$t
(
'admin.system.fetchingLatestVersionInfo'
)
}}
template(v-else)
.text-center
strong.text-positive(v-if='isLatest')
{{
$t
(
'admin.system.runningLatestVersion'
)
}}
strong.text-pink(v-else)
{{
$t
(
'admin.system.newVersionAvailable'
)
}}
.text-body2.q-mt-md Current: #[strong
{{
state
.
current
}}
]
.text-body2 Latest: #[strong
{{
state
.
latest
}}
]
.text-body2 Release Date: #[strong
{{
state
.
latestDate
}}
]
q-card-actions.card-actions
q-card-actions.card-actions
q-space
q-space
q-btn.acrylic-btn(
q-btn.acrylic-btn(
flat
flat
:label='
t(`common.actions.cancel
`)'
:label='
state.isLoading ? t(`common.actions.cancel`) : t(`common.actions.close
`)'
color='grey'
color='grey'
padding='xs md'
padding='xs md'
@click='onDialogCancel'
@click='onDialogCancel'
...
@@ -37,7 +45,10 @@ q-dialog(ref='dialogRef', @hide='onDialogHide')
...
@@ -37,7 +45,10 @@ q-dialog(ref='dialogRef', @hide='onDialogHide')
import
gql
from
'graphql-tag'
import
gql
from
'graphql-tag'
import
{
useI18n
}
from
'vue-i18n'
import
{
useI18n
}
from
'vue-i18n'
import
{
useDialogPluginComponent
,
useQuasar
}
from
'quasar'
import
{
useDialogPluginComponent
,
useQuasar
}
from
'quasar'
import
{
reactive
}
from
'vue'
import
{
computed
,
onMounted
,
reactive
}
from
'vue'
import
{
DateTime
}
from
'luxon'
import
{
useUserStore
}
from
'src/stores/user'
// EMITS
// EMITS
...
@@ -50,6 +61,10 @@ defineEmits([
...
@@ -50,6 +61,10 @@ defineEmits([
const
{
dialogRef
,
onDialogHide
,
onDialogOK
,
onDialogCancel
}
=
useDialogPluginComponent
()
const
{
dialogRef
,
onDialogHide
,
onDialogOK
,
onDialogCancel
}
=
useDialogPluginComponent
()
const
$q
=
useQuasar
()
const
$q
=
useQuasar
()
// STORES
const
userStore
=
useUserStore
()
// I18N
// I18N
const
{
t
}
=
useI18n
()
const
{
t
}
=
useI18n
()
...
@@ -58,44 +73,56 @@ const { t } = useI18n()
...
@@ -58,44 +73,56 @@ const { t } = useI18n()
const
state
=
reactive
({
const
state
=
reactive
({
isLoading
:
false
,
isLoading
:
false
,
canUpgrade
:
false
canUpgrade
:
false
,
current
:
''
,
latest
:
''
,
latestDate
:
''
})
const
isLatest
=
computed
(()
=>
{
return
true
})
})
// METHODS
// METHODS
async
function
upgrade
()
{
async
function
check
()
{
state
.
isLoading
=
true
state
.
isLoading
=
true
try
{
try
{
const
resp
=
await
APOLLO_CLIENT
.
mutate
({
const
resp
=
await
APOLLO_CLIENT
.
mutate
({
mutation
:
gql
`
mutation
:
gql
`
mutation
deleteHook ($id: UUID!)
{
mutation
checkForUpdates
{
deleteHook(id: $id)
{
checkForUpdates
{
operation {
operation {
succeeded
succeeded
message
message
}
}
current
latest
latestDate
}
}
}
}
`
,
`
variables
:
{
id
:
0
}
})
})
if
(
resp
?.
data
?.
deleteHook
?.
operation
?.
succeeded
)
{
if
(
resp
?.
data
?.
checkForUpdates
?.
operation
?.
succeeded
)
{
$q
.
notify
({
state
.
current
=
resp
?.
data
?.
checkForUpdates
?.
current
type
:
'positive'
,
state
.
latest
=
resp
?.
data
?.
checkForUpdates
?.
latest
message
:
t
(
'admin.webhooks.deleteSuccess'
)
state
.
latestDate
=
DateTime
.
fromISO
(
resp
?.
data
?.
checkForUpdates
?.
latestDate
).
toFormat
(
userStore
.
preferredDateFormat
)
})
onDialogOK
()
}
else
{
}
else
{
throw
new
Error
(
resp
?.
data
?.
deleteHook
?.
operation
?.
message
||
'An unexpected error occured.'
)
throw
new
Error
(
resp
?.
data
?.
checkForUpdates
?.
operation
?.
message
||
'An unexpected error occured.'
)
}
}
}
catch
(
err
)
{
}
catch
(
err
)
{
$q
.
notify
({
$q
.
notify
({
type
:
'negative'
,
type
:
'negative'
,
message
:
err
.
message
message
:
err
.
message
})
})
onDialogCancel
()
}
}
state
.
isLoading
=
false
state
.
isLoading
=
false
}
}
// MOUNTED
onMounted
(()
=>
{
check
()
})
</
script
>
</
script
>
ux/src/pages/AdminLocale.vue
View file @
bb4a1e6b
...
@@ -107,28 +107,6 @@ q-page.admin-locale
...
@@ -107,28 +107,6 @@ q-page.admin-locale
.q-pa-md.text-center
.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-item
//- blueprint-icon(icon='test-passed')
//- q-item-section
//- q-item-label
{{
t
(
`admin.locale.activeNamespaces.label`
)
}}
//- q-item-label(caption)
{{
t
(
`admin.locale.activeNamespaces.hint`
)
}}
//- q-item-section
//- q-select(
//- outlined
//- :disable='!namespacing'
//- v-model='namespaces'
//- :options='installedLocales'
//- multiple
//- use-chips
//- option-value='code'
//- option-label='name'
//- emit-value
//- map-options
//- dense
//- :aria-label='t(`admin.locale.activeNamespaces.label`)'
//- )
</
template
>
</
template
>
<
script
setup
>
<
script
setup
>
...
...
ux/src/pages/AdminSystem.vue
View file @
bb4a1e6b
...
@@ -60,7 +60,7 @@ q-page.admin-system
...
@@ -60,7 +60,7 @@ q-page.admin-system
q-item-section
q-item-section
.row.q-col-gutter-sm
.row.q-col-gutter-sm
.col
.col
.
dark-value(caption)
{{
state
.
info
.
latestVersion
}}
.
text-caption.dark-value
{{
state
.
info
.
latestVersion
}}
.col-auto
.col-auto
q-btn.acrylic-btn(
q-btn.acrylic-btn(
flat
flat
...
@@ -200,43 +200,6 @@ q-page.admin-system
...
@@ -200,43 +200,6 @@ q-page.admin-system
q-item-label(caption)
{{
t
(
'admin.system.configFileHint'
)
}}
q-item-label(caption)
{{
t
(
'admin.system.configFileHint'
)
}}
q-item-section
q-item-section
q-item-label.dark-value(caption)
{{
state
.
info
.
configFile
}}
q-item-label.dark-value(caption)
{{
state
.
info
.
configFile
}}
//- v-list-item-action-text
{{
t
(
'admin.system.published'
)
}}
{{
state
.
info
.
latestVersionReleaseDate
|
moment
(
'from'
)
}}
//- v-card-actions(v-if='info.upgradeCapable && !isLatestVersion && info.platform === `docker`', :class='$vuetify.theme.dark ? `grey darken-3-d5` : `indigo lighten-5`')
//- .caption.indigo--text.pl-3(:class='$vuetify.theme.dark ? `text--lighten-4` : ``') Wiki.js can perform the upgrade to the latest version for you.
//- v-spacer
//- v-btn.px-3(
//- color='indigo'
//- dark
//- @click='performUpgrade'
//- )
//- v-icon(left) mdi-upload
//- span Perform Upgrade
//- v-dialog(
//- v-model='isUpgrading'
//- persistent
//- width='450'
//- )
//- v-card.blue.darken-5(dark)
//- v-card-text.text-center.pa-10
//- self-building-square-spinner(
//- :animation-duration='4000'
//- :size='40'
//- color='#FFF'
//- style='margin: 0 auto;'
//- )
//- .body-2.mt-5.blue--text.text--lighten-4 Your Wiki.js container is being upgraded...
//- .caption.blue--text.text--lighten-2 Please wait
//- v-progress-linear.mt-5(
//- color='blue lighten-2'
//- :value='upgradeProgress'
//- :buffer-value='upgradeProgress'
//- rounded
//- :stream='isUpgradingStarted'
//- query
//- :indeterminate='!isUpgradingStarted'
//- )
</
template
>
</
template
>
<
script
setup
>
<
script
setup
>
...
@@ -309,9 +272,6 @@ const platformLogo = computed(() => {
...
@@ -309,9 +272,6 @@ const platformLogo = computed(() => {
return
'washing-machine'
return
'washing-machine'
}
}
})
})
const
isLatestVersion
=
computed
(()
=>
{
return
state
.
info
.
currentVersion
===
state
.
info
.
latestVersion
})
const
clientBrowser
=
computed
(()
=>
{
const
clientBrowser
=
computed
(()
=>
{
return
!
import
.
meta
.
env
.
SSR
?
navigator
.
userAgent
:
''
return
!
import
.
meta
.
env
.
SSR
?
navigator
.
userAgent
:
''
})
})
...
@@ -364,51 +324,11 @@ async function load () {
...
@@ -364,51 +324,11 @@ async function load () {
function
checkForUpdates
()
{
function
checkForUpdates
()
{
$q
.
dialog
({
$q
.
dialog
({
component
:
CheckUpdateDialog
component
:
CheckUpdateDialog
}).
onDismiss
(()
=>
{
load
()
})
})
}
}
// async function performUpgrade () {
// state.isUpgrading = true
// state.isUpgradingStarted = false
// state.upgradeProgress = 0
// this.$store.commit('loadingStart', 'admin-system-upgrade')
// try {
// const respRaw = await APOLLO_CLIENT.mutate({
// mutation: gql`
// mutation performUpdate {
// system {
// performUpgrade {
// responseResult {
// succeeded
// errorCode
// slug
// message
// }
// }
// }
// }
// `
// })
// const resp = _get(respRaw, 'data.system.performUpgrade.responseResult', {})
// if (resp.succeeded) {
// this.isUpgradingStarted = true
// const progressInterval = setInterval(() => {
// this.upgradeProgress += 0.83
// }, 500)
// setTimeout(() => {
// clearInterval(progressInterval)
// window.location.reload(true)
// }, 60000)
// } else {
// throw new Error(resp.message)
// }
// } catch (err) {
// this.$store.commit('pushGraphError', err)
// this.$store.commit('loadingStop', 'admin-system-upgrade')
// this.isUpgrading = false
// }
// }
// MOUNTED
// MOUNTED
onMounted
(()
=>
{
onMounted
(()
=>
{
...
...
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