misc: migrate to vuetify 2.0 (wip)

pull/948/head
NGPixel 5 years ago
parent e77037e161
commit eccf1a1b19

@ -19,53 +19,9 @@
"@babel/plugin-proposal-throw-expressions",
[
"prismjs", {
"languages": [
"markup",
"css",
"clike",
"javascript",
"c",
"bash",
"basic",
"cpp",
"csharp",
"arduino",
"ruby",
"elixir",
"fsharp",
"go",
"graphql",
"handlebars",
"haskell",
"ini",
"java",
"json",
"kotlin",
"latex",
"less",
"makefile",
"markdown",
"matlab",
"nginx",
"objectivec",
"perl",
"php",
"powershell",
"pug",
"python",
"typescript",
"rust",
"scss",
"scala",
"smalltalk",
"sql",
"stylus",
"swift",
"vbnet",
"yaml"
],
"plugins": ["line-numbers"],
"theme": "dark",
"languages": ["clike", "markup"],
"plugins": ["line-numbers", "autoloader", "normalize-whitespace"],
"theme": "twilight",
"css": true
}
]

4
.gitattributes vendored

@ -1,5 +1,5 @@
# Auto detect text files and perform LF normalization
* text=auto
* text eol=lf
# Custom for Visual Studio
*.cs diff=csharp
@ -14,4 +14,4 @@
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
*.RTF diff=astextplain

@ -12,7 +12,7 @@ import { ErrorLink } from 'apollo-link-error'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { getMainDefinition } from 'apollo-utilities'
import VueApollo from 'vue-apollo'
import Vuetify from 'vuetify'
import Vuetify from 'vuetify/lib'
import Velocity from 'velocity-animate'
import Vuescroll from 'vuescroll/dist/vuescroll-native'
import Hammer from 'hammerjs'
@ -138,10 +138,8 @@ Vue.use(VueApollo)
Vue.use(VueClipboards)
Vue.use(localization.VueI18Next)
Vue.use(helpers)
Vue.use(VeeValidate, { events: '' })
Vue.use(Vuetify, {
rtl: siteConfig.rtl
})
Vue.use(VeeValidate, { mode: 'eager' })
Vue.use(Vuetify)
Vue.use(VueMoment, { moment })
Vue.use(Vuescroll)
Vue.use(VueTour)
@ -194,7 +192,10 @@ let bootstrap = () => {
mixins: [helpers],
apolloProvider,
store,
i18n
i18n,
vuetify: new Vuetify({
rtl: siteConfig.rtl
})
})
// ----------------------------------
@ -208,14 +209,6 @@ let bootstrap = () => {
// ====================================
import(/* webpackChunkName: "theme-page" */ './themes/' + process.env.CURRENT_THEME + '/js/app.js')
// ====================================
// Load Icons
// ====================================
// import(/* webpackChunkName: "icons" */ './svg/icons.svg').then(icons => {
// document.body.insertAdjacentHTML('beforeend', icons.default)
// })
}
window.boot.onDOMReady(bootstrap)

@ -1,6 +1,6 @@
/* eslint-disable import/first */
import Vue from 'vue'
import Vuetify from 'vuetify'
import Vuetify from 'vuetify/lib'
import VeeValidate from 'vee-validate'
import boot from './modules/boot'
/* eslint-enable import/first */
@ -15,15 +15,8 @@ Vue.component('setup', () => import(/* webpackMode: "eager" */ './components/set
let bootstrap = () => {
window.WIKI = new Vue({
el: '#root'
})
// ====================================
// Load Icons
// ====================================
import(/* webpackChunkName: "icons" */ './svg/icons.svg').then(icons => {
document.body.insertAdjacentHTML('beforeend', icons.default)
el: '#root',
vuetify: new Vuetify()
})
}

@ -3,114 +3,114 @@
nav-header(hide-search)
template(slot='mid')
v-spacer
.subheading.grey--text {{$t('admin:adminArea')}}
.overline.grey--text {{$t('admin:adminArea')}}
v-spacer
v-navigation-drawer.pb-0.admin-sidebar(v-model='adminDrawerShown', app, fixed, clipped, :right='$vuetify.rtl', permanent)
v-navigation-drawer.pb-0.admin-sidebar(v-model='adminDrawerShown', app, fixed, clipped, :right='$vuetify.rtl', permanent, width='300')
vue-scroll(:ops='scrollStyle')
v-list(dense)
v-list-tile.pt-2(to='/dashboard')
v-list-tile-avatar: v-icon dashboard
v-list-tile-title {{ $t('admin:dashboard.title') }}
v-list(dense, nav)
v-list-item(to='/dashboard')
v-list-item-avatar(size='24'): v-icon mdi-view-dashboard-variant
v-list-item-title {{ $t('admin:dashboard.title') }}
template(v-if='hasPermission([`manage:system`, `manage:navigation`, `write:pages`, `manage:pages`, `delete:pages`])')
v-divider.my-2
v-subheader.pl-4 {{ $t('admin:nav.site') }}
v-list-tile(to='/general', v-if='hasPermission(`manage:system`)')
v-list-tile-avatar: v-icon widgets
v-list-tile-title {{ $t('admin:general.title') }}
v-list-tile(to='/locale', v-if='hasPermission(`manage:system`)')
v-list-tile-avatar: v-icon language
v-list-tile-title {{ $t('admin:locale.title') }}
v-list-tile(to='/navigation', v-if='hasPermission([`manage:system`, `manage:navigation`])')
v-list-tile-avatar: v-icon near_me
v-list-tile-title {{ $t('admin:navigation.title') }}
v-list-tile(to='/pages', v-if='hasPermission([`manage:system`, `write:pages`, `manage:pages`, `delete:pages`])')
v-list-tile-avatar: v-icon insert_drive_file
v-list-tile-title {{ $t('admin:pages.title') }}
v-list-tile-action
v-chip(small, disabled, :color='darkMode ? `grey darken-3-d4` : `grey lighten-4`')
v-list-item(to='/general', v-if='hasPermission(`manage:system`)')
v-list-item-avatar(size='24'): v-icon mdi-widgets
v-list-item-title {{ $t('admin:general.title') }}
v-list-item(to='/locale', v-if='hasPermission(`manage:system`)')
v-list-item-avatar(size='24'): v-icon mdi-web
v-list-item-title {{ $t('admin:locale.title') }}
v-list-item(to='/navigation', v-if='hasPermission([`manage:system`, `manage:navigation`])')
v-list-item-avatar(size='24'): v-icon mdi-near-me
v-list-item-title {{ $t('admin:navigation.title') }}
v-list-item(to='/pages', v-if='hasPermission([`manage:system`, `write:pages`, `manage:pages`, `delete:pages`])')
v-list-item-avatar(size='24'): v-icon mdi-file-document-outline
v-list-item-title {{ $t('admin:pages.title') }}
v-list-item-action
v-chip(x-small, disabled, :color='darkMode ? `grey darken-3-d4` : `grey lighten-4`')
.caption.grey--text {{ info.pagesTotal }}
v-list-tile(to='/theme', v-if='hasPermission([`manage:system`, `manage:theme`])')
v-list-tile-avatar: v-icon palette
v-list-tile-title {{ $t('admin:theme.title') }}
v-list-item(to='/theme', v-if='hasPermission([`manage:system`, `manage:theme`])')
v-list-item-avatar(size='24'): v-icon mdi-palette-outline
v-list-item-title {{ $t('admin:theme.title') }}
template(v-if='hasPermission([`manage:system`, `manage:groups`, `write:groups`, `manage:users`, `write:users`])')
v-divider.my-2
v-subheader.pl-4 {{ $t('admin:nav.users') }}
v-list-tile(to='/groups', v-if='hasPermission([`manage:system`, `manage:groups`, `write:groups`])')
v-list-tile-avatar: v-icon people
v-list-tile-title {{ $t('admin:groups.title') }}
v-list-tile-action
v-chip(small, disabled, :color='darkMode ? `grey darken-3-d4` : `grey lighten-4`')
v-list-item(to='/groups', v-if='hasPermission([`manage:system`, `manage:groups`, `write:groups`])')
v-list-item-avatar(size='24'): v-icon mdi-account-group
v-list-item-title {{ $t('admin:groups.title') }}
v-list-item-action
v-chip(x-small, disabled, :color='darkMode ? `grey darken-3-d4` : `grey lighten-4`')
.caption.grey--text {{ info.groupsTotal }}
v-list-tile(to='/users', v-if='hasPermission([`manage:system`, `manage:groups`, `write:groups`, `manage:users`, `write:users`])')
v-list-tile-avatar: v-icon perm_identity
v-list-tile-title {{ $t('admin:users.title') }}
v-list-tile-action
v-chip(small, disabled, :color='darkMode ? `grey darken-3-d4` : `grey lighten-4`')
v-list-item(to='/users', v-if='hasPermission([`manage:system`, `manage:groups`, `write:groups`, `manage:users`, `write:users`])')
v-list-item-avatar(size='24'): v-icon mdi-account-box
v-list-item-title {{ $t('admin:users.title') }}
v-list-item-action
v-chip(x-small, disabled, :color='darkMode ? `grey darken-3-d4` : `grey lighten-4`')
.caption.grey--text {{ info.usersTotal }}
template(v-if='hasPermission(`manage:system`)')
v-divider.my-2
v-subheader.pl-4 {{ $t('admin:nav.modules') }}
v-list-tile(to='/analytics')
v-list-tile-avatar: v-icon timeline
v-list-tile-title {{ $t('admin:analytics.title') }}
v-list-tile(to='/auth')
v-list-tile-avatar: v-icon lock_outline
v-list-tile-title {{ $t('admin:auth.title') }}
v-list-tile(to='/comments', disabled)
v-list-tile-avatar: v-icon(color='grey lighten-2') comment
v-list-tile-title {{ $t('admin:comments.title') }}
v-list-tile(to='/editor', disabled)
v-list-tile-avatar: v-icon(color='grey lighten-2') transform
v-list-tile-title {{ $t('admin:editor.title') }}
v-list-tile(to='/logging', disabled)
v-list-tile-avatar: v-icon(color='grey lighten-2') graphic_eq
v-list-tile-title {{ $t('admin:logging.title') }}
v-list-tile(to='/rendering')
v-list-tile-avatar: v-icon system_update_alt
v-list-tile-title {{ $t('admin:rendering.title') }}
v-list-tile(to='/search')
v-list-tile-avatar: v-icon search
v-list-tile-title {{ $t('admin:search.title') }}
v-list-tile(to='/storage')
v-list-tile-avatar: v-icon storage
v-list-tile-title {{ $t('admin:storage.title') }}
v-list-item(to='/analytics')
v-list-item-avatar(size='24'): v-icon mdi-chart-timeline-variant
v-list-item-title {{ $t('admin:analytics.title') }}
v-list-item(to='/auth')
v-list-item-avatar(size='24'): v-icon mdi-lock-outline
v-list-item-title {{ $t('admin:auth.title') }}
v-list-item(to='/comments', disabled)
v-list-item-avatar(size='24'): v-icon(color='grey lighten-2') mdi-comment-text-outline
v-list-item-title {{ $t('admin:comments.title') }}
v-list-item(to='/editor', disabled)
v-list-item-avatar(size='24'): v-icon(color='grey lighten-2') mdi-playlist-edit
v-list-item-title {{ $t('admin:editor.title') }}
v-list-item(to='/logging', disabled)
v-list-item-avatar(size='24'): v-icon(color='grey lighten-2') mdi-script-text-outline
v-list-item-title {{ $t('admin:logging.title') }}
v-list-item(to='/rendering')
v-list-item-avatar(size='24'): v-icon mdi-cogs
v-list-item-title {{ $t('admin:rendering.title') }}
v-list-item(to='/search')
v-list-item-avatar(size='24'): v-icon mdi-cloud-search-outline
v-list-item-title {{ $t('admin:search.title') }}
v-list-item(to='/storage')
v-list-item-avatar(size='24'): v-icon mdi-harddisk
v-list-item-title {{ $t('admin:storage.title') }}
template(v-if='hasPermission([`manage:system`, `manage:api`])')
v-divider.my-2
v-subheader.pl-4 {{ $t('admin:nav.system') }}
v-list-tile(to='/api', v-if='hasPermission([`manage:system`, `manage:api`])', disabled)
v-list-tile-avatar: v-icon(color='grey lighten-2') call_split
v-list-tile-title {{ $t('admin:api.title') }}
v-list-tile(to='/mail', v-if='hasPermission(`manage:system`)')
v-list-tile-avatar: v-icon email
v-list-tile-title {{ $t('admin:mail.title') }}
v-list-tile(to='/system', v-if='hasPermission(`manage:system`)')
v-list-tile-avatar: v-icon tune
v-list-tile-title {{ $t('admin:system.title') }}
v-list-tile(to='/utilities', v-if='hasPermission(`manage:system`)')
v-list-tile-avatar: v-icon build
v-list-tile-title {{ $t('admin:utilities.title') }}
v-list-tile(to='/webhooks', v-if='hasPermission(`manage:system`)', disabled)
v-list-tile-avatar: v-icon(color='grey lighten-2') ac_unit
v-list-tile-title {{ $t('admin:webhooks.title') }}
v-list-item(to='/api', v-if='hasPermission([`manage:system`, `manage:api`])', disabled)
v-list-item-avatar(size='24'): v-icon(color='grey lighten-2') mdi-call-split
v-list-item-title {{ $t('admin:api.title') }}
v-list-item(to='/mail', v-if='hasPermission(`manage:system`)')
v-list-item-avatar(size='24'): v-icon mdi-email-multiple-outline
v-list-item-title {{ $t('admin:mail.title') }}
v-list-item(to='/system', v-if='hasPermission(`manage:system`)')
v-list-item-avatar(size='24'): v-icon mdi-tune
v-list-item-title {{ $t('admin:system.title') }}
v-list-item(to='/utilities', v-if='hasPermission(`manage:system`)')
v-list-item-avatar(size='24'): v-icon mdi-wrench-outline
v-list-item-title {{ $t('admin:utilities.title') }}
v-list-item(to='/webhooks', v-if='hasPermission(`manage:system`)', disabled)
v-list-item-avatar(size='24'): v-icon(color='grey lighten-2') mdi-webhook
v-list-item-title {{ $t('admin:webhooks.title') }}
v-list-group(
to='/dev'
no-action
v-if='hasPermission([`manage:system`, `manage:api`])'
)
v-list-tile(slot='activator')
v-list-tile-avatar: v-icon weekend
v-list-tile-title {{ $t('admin:dev.title') }}
v-list-item(slot='activator')
v-list-item-avatar(size='24'): v-icon mdi-dev-to
v-list-item-title {{ $t('admin:dev.title') }}
v-list-tile(to='/dev-flags')
v-list-tile-title {{ $t('admin:dev.flags.title') }}
v-list-tile(to='/dev-graphiql')
v-list-tile-title {{ $t('admin:dev.graphiql.title') }}
v-list-tile(to='/dev-voyager')
v-list-tile-title {{ $t('admin:dev.voyager.title') }}
v-list-item(to='/dev-flags')
v-list-item-title {{ $t('admin:dev.flags.title') }}
v-list-item(to='/dev-graphiql')
v-list-item-title {{ $t('admin:dev.graphiql.title') }}
v-list-item(to='/dev-voyager')
v-list-item-title {{ $t('admin:dev.voyager.title') }}
v-divider.my-2
v-list-tile(to='/contribute')
v-list-tile-avatar: v-icon favorite
v-list-tile-title {{ $t('admin:contribute.title') }}
v-list-item(to='/contribute')
v-list-item-avatar(size='24'): v-icon mdi-heart-outline
v-list-item-title {{ $t('admin:contribute.title') }}
v-content(:class='darkMode ? "grey darken-4" : ""')
transition(name='admin-router')

@ -8,10 +8,10 @@
.headline.primary--text.animated.fadeInLeft {{ $t('admin:analytics.title') }}
.subheading.grey--text.animated.fadeInLeft.wait-p4s {{ $t('admin:analytics.subtitle') }}
v-spacer
v-btn.animated.fadeInDown.wait-p2s(outline, color='grey', @click='refresh', large)
v-icon refresh
v-btn.animated.fadeInDown.wait-p2s.mr-3(outlined, color='grey', @click='refresh', large)
v-icon mdi-refresh
v-btn.animated.fadeInDown(color='success', @click='save', depressed, large)
v-icon(left) check
v-icon(left) mdi-check
span {{$t('common:actions.apply')}}
v-flex(lg3, xs12)
@ -20,21 +20,21 @@
.subheading {{$t('admin:analytics.providers')}}
v-list(two-line, dense).py-0
template(v-for='(str, idx) in providers')
v-list-tile(:key='str.key', @click='selectedProvider = str.key', :disabled='!str.isAvailable')
v-list-tile-avatar
v-icon(color='grey', v-if='!str.isAvailable') indeterminate_check_box
v-icon(color='primary', v-else-if='str.isEnabled', v-ripple, @click='str.isEnabled = false') check_box
v-icon(color='grey', v-else, v-ripple, @click='str.isEnabled = true') check_box_outline_blank
v-list-tile-content
v-list-tile-title.body-2(:class='!str.isAvailable ? `grey--text` : (selectedProvider === str.key ? `primary--text` : ``)') {{ str.title }}
v-list-tile-sub-title.caption(:class='!str.isAvailable ? `grey--text text--lighten-1` : (selectedProvider === str.key ? `blue--text ` : ``)') {{ str.description }}
v-list-tile-avatar(v-if='selectedProvider === str.key')
v-icon.animated.fadeInLeft(color='primary') arrow_forward_ios
v-list-item(:key='str.key', @click='selectedProvider = str.key', :disabled='!str.isAvailable')
v-list-item-avatar(size='24')
v-icon(color='grey', v-if='!str.isAvailable') mdi-minus-box-outline
v-icon(color='primary', v-else-if='str.isEnabled', v-ripple, @click='str.isEnabled = false') mdi-checkbox-marked-outline
v-icon(color='grey', v-else, v-ripple, @click='str.isEnabled = true') mdi-checkbox-blank-outline
v-list-item-content
v-list-item-title.body-2(:class='!str.isAvailable ? `grey--text` : (selectedProvider === str.key ? `primary--text` : ``)') {{ str.title }}
v-list-item-subtitle: .caption(:class='!str.isAvailable ? `grey--text text--lighten-1` : (selectedProvider === str.key ? `blue--text ` : ``)') {{ str.description }}
v-list-item-avatar(v-if='selectedProvider === str.key', size='24')
v-icon.animated.fadeInLeft(color='primary', large) mdi-chevron-right
v-divider(v-if='idx < providers.length - 1')
v-flex(xs12, lg9)
v-card.wiki-form.animated.fadeInUp.wait-p2s
v-card.animated.fadeInUp.wait-p2s
v-toolbar(color='primary', dense, flat, dark)
.subheading {{provider.title}}
v-card-text
@ -44,18 +44,17 @@
.caption.pt-3 {{provider.description}}
.caption.pb-3: a(:href='provider.website') {{provider.website}}
v-divider.mt-3
v-subheader.pl-0 {{$t('admin:analytics.providerConfiguration')}}
.overline.py-4 {{$t('admin:analytics.providerConfiguration')}}
.body-1.ml-3(v-if='!provider.config || provider.config.length < 1'): em {{$t('admin:analytics.providerNoConfiguration')}}
template(v-else, v-for='cfg in provider.config')
v-select(
v-if='cfg.value.type === "string" && cfg.value.enum'
outline
background-color='grey lighten-2'
outlined
:items='cfg.value.enum'
:key='cfg.key'
:label='cfg.value.title'
v-model='cfg.value.value'
prepend-icon='settings_applications'
prepend-icon='mdi-settings-box'
:hint='cfg.value.hint ? cfg.value.hint : ""'
persistent-hint
:class='cfg.value.hint ? "mb-2" : ""'
@ -66,30 +65,28 @@
:label='cfg.value.title'
v-model='cfg.value.value'
color='primary'
prepend-icon='settings_applications'
prepend-icon='mdi-settings-box'
:hint='cfg.value.hint ? cfg.value.hint : ""'
persistent-hint
)
v-textarea(
v-else-if='cfg.value.type === "string" && cfg.value.multiline'
outline
background-color='grey lighten-2'
outlined
:key='cfg.key'
:label='cfg.value.title'
v-model='cfg.value.value'
prepend-icon='settings_applications'
prepend-icon='mdi-settings-box'
:hint='cfg.value.hint ? cfg.value.hint : ""'
persistent-hint
:class='cfg.value.hint ? "mb-2" : ""'
)
v-text-field(
v-else
outline
background-color='grey lighten-2'
outlined
:key='cfg.key'
:label='cfg.value.title'
v-model='cfg.value.value'
prepend-icon='settings_applications'
prepend-icon='mdi-settings-box'
:hint='cfg.value.hint ? cfg.value.hint : ""'
persistent-hint
:class='cfg.value.hint ? "mb-2" : ""'

@ -8,7 +8,7 @@
.headline.primary--text.animated.fadeInLeft {{ $t('admin:auth.title') }}
.subheading.grey--text.animated.fadeInLeft.wait-p4s {{ $t('admin:auth.subtitle') }}
v-spacer
v-btn.animated.fadeInDown.wait-p2s(outline, color='grey', @click='refresh', large)
v-btn.animated.fadeInDown.wait-p2s.mr-3(outlined, color='grey', @click='refresh', large)
v-icon refresh
v-btn.animated.fadeInDown(color='success', @click='save', depressed, large)
v-icon(left) check
@ -20,16 +20,16 @@
.subheading {{$t('admin:auth.strategies')}}
v-list(two-line, dense).py-0
template(v-for='(str, idx) in strategies')
v-list-tile(:key='str.key', @click='selectedStrategy = str.key', :disabled='!str.isAvailable')
v-list-tile-avatar
v-list-item(:key='str.key', @click='selectedStrategy = str.key', :disabled='!str.isAvailable')
v-list-item-avatar
v-icon(color='grey', v-if='!str.isAvailable') indeterminate_check_box
v-icon(color='primary', v-else-if='str.isEnabled && str.key !== `local`', v-ripple, @click='str.isEnabled = false') check_box
v-icon(color='primary', v-else-if='str.isEnabled && str.key === `local`') check_box
v-icon(color='grey', v-else, v-ripple, @click='str.isEnabled = true') check_box_outline_blank
v-list-tile-content
v-list-tile-title.body-2(:class='!str.isAvailable ? `grey--text` : (selectedStrategy === str.key ? `primary--text` : ``)') {{ str.title }}
v-list-tile-sub-title.caption(:class='!str.isAvailable ? `grey--text text--lighten-1` : (selectedStrategy === str.key ? `blue--text ` : ``)') {{ str.description }}
v-list-tile-avatar(v-if='selectedStrategy === str.key')
v-list-item-content
v-list-item-title.body-2(:class='!str.isAvailable ? `grey--text` : (selectedStrategy === str.key ? `primary--text` : ``)') {{ str.title }}
v-list-item-sub-title.caption(:class='!str.isAvailable ? `grey--text text--lighten-1` : (selectedStrategy === str.key ? `blue--text ` : ``)') {{ str.description }}
v-list-item-avatar(v-if='selectedStrategy === str.key')
v-icon.animated.fadeInLeft(color='primary') arrow_forward_ios
v-divider(v-if='idx < strategies.length - 1')
@ -39,7 +39,7 @@
v-card-text
v-text-field.md2(
v-model='jwtAudience'
outline
outlined
prepend-icon='account_balance'
:label='$t(`admin:auth.jwtAudience`)'
:hint='$t(`admin:auth.jwtAudienceHint`)'
@ -47,7 +47,7 @@
)
v-text-field.mt-3.md2(
v-model='jwtExpiration'
outline
outlined
prepend-icon='schedule'
:label='$t(`admin:auth.tokenExpiration`)'
:hint='$t(`admin:auth.tokenExpirationHint`)'
@ -55,7 +55,7 @@
)
v-text-field.mt-3.md2(
v-model='jwtRenewablePeriod'
outline
outlined
prepend-icon='update'
:label='$t(`admin:auth.tokenRenewalPeriod`)'
:hint='$t(`admin:auth.tokenRenewalPeriodHint`)'
@ -85,8 +85,7 @@
template(v-else, v-for='cfg in strategy.config')
v-select(
v-if='cfg.value.type === "string" && cfg.value.enum'
outline
background-color='grey lighten-2'
outlined
:items='cfg.value.enum'
:key='cfg.key'
:label='cfg.value.title'
@ -108,8 +107,7 @@
)
v-textarea(
v-else-if='cfg.value.type === "string" && cfg.value.multiline'
outline
background-color='grey lighten-2'
outlined
:key='cfg.key'
:label='cfg.value.title'
v-model='cfg.value.value'
@ -120,8 +118,7 @@
)
v-text-field(
v-else
outline
background-color='grey lighten-2'
outlined
:key='cfg.key'
:label='cfg.value.title'
v-model='cfg.value.value'
@ -153,7 +150,7 @@
:label='$t(`admin:auth.domainsWhitelist`)'
v-model='strategy.domainWhitelist'
prepend-icon='mail_outline'
outline
outlined
:disabled='!strategy.selfRegistration'
:hint='$t(`admin:auth.domainsWhitelistHint`)'
persistent-hint
@ -164,7 +161,7 @@
chips
)
v-autocomplete.mt-3.ml-3(
outline
outlined
:disabled='!strategy.selfRegistration'
:items='groups'
item-text='name'

@ -91,18 +91,18 @@
v-btn(outline, small, href='https://opencollective.com/wikijs/order/1273') Become a Sponsor
v-list(two-line)
template(v-for='(sponsor, idx) in sponsors')
v-list-tile(:key='sponsor.id')
v-list-tile-avatar
v-list-item(:key='sponsor.id')
v-list-item-avatar
img(v-if='sponsor.image', :src='sponsor.image')
v-avatar(v-else, color='teal', size='40')
span.white--text.subheading {{sponsor.name[0].toUpperCase()}}
v-list-tile-content
v-list-tile-title {{sponsor.name}}
v-list-tile-sub-title {{sponsor.description}}
v-list-tile-action(v-if='sponsor.twitter')
v-list-item-content
v-list-item-title {{sponsor.name}}
v-list-item-sub-title {{sponsor.description}}
v-list-item-action(v-if='sponsor.twitter')
v-btn(icon, :href='sponsor.twitter', target='_blank')
icon-twitter(fillColor='#9e9e9e')
v-list-tile-action(v-if='sponsor.website')
v-list-item-action(v-if='sponsor.website')
v-btn(icon, :href='sponsor.website', target='_blank')
v-icon(color='grey') public
v-divider(v-if='idx < sponsors.length - 1')
@ -112,91 +112,91 @@
v-btn(outline, small, href='https://opencollective.com/wikijs/order/1272') Become a Backer
v-list(two-line, dense)
template(v-for='(backer, idx) in backers')
v-list-tile(:key='backer.id')
v-list-tile-avatar
v-list-item(:key='backer.id')
v-list-item-avatar
img(v-if='backer.image', :src='backer.image')
v-avatar(v-else, color='blue-grey', size='40')
span.white--text.subheading {{backer.name[0].toUpperCase()}}
v-list-tile-content
v-list-tile-title {{backer.name}}
v-list-tile-sub-title {{backer.description}}
v-list-tile-action(v-if='backer.twitter')
v-list-item-content
v-list-item-title {{backer.name}}
v-list-item-sub-title {{backer.description}}
v-list-item-action(v-if='backer.twitter')
v-btn(icon, :href='backer.twitter', target='_blank')
icon-twitter(fillColor='#9e9e9e')
v-list-tile-action(v-if='backer.website')
v-list-item-action(v-if='backer.website')
v-btn(icon, :href='backer.website', target='_blank')
v-icon(color='grey') public
v-divider(v-if='idx < backers.length - 1')
v-toolbar(color='primary', dense, dark)
.subheading Special Thanks
v-list(two-line)
v-list-tile
v-list-tile-avatar
v-list-item
v-list-item-avatar
img(src='https://static.requarks.io/logo/algolia.svg', alt='Algolia')
v-list-tile-content
v-list-tile-title Algolia
v-list-tile-sub-title Algolia is a powerful search-as-a-service solution, made easy to use with API clients, UI libraries, and pre-built integrations.
v-list-tile-action
v-list-item-content
v-list-item-title Algolia
v-list-item-sub-title Algolia is a powerful search-as-a-service solution, made easy to use with API clients, UI libraries, and pre-built integrations.
v-list-item-action
v-btn(icon, href='https://www.algolia.com/', target='_blank')
v-icon(color='grey') public
v-divider
v-list-tile
v-list-tile-avatar
v-list-item
v-list-item-avatar
img(src='https://static.requarks.io/logo/browserstack.svg', alt='Browserstack')
v-list-tile-content
v-list-tile-title BrowserStack
v-list-tile-sub-title BrowserStack is a cloud web and mobile testing platform that enables developers to test their websites and mobile applications.
v-list-tile-action
v-list-item-content
v-list-item-title BrowserStack
v-list-item-sub-title BrowserStack is a cloud web and mobile testing platform that enables developers to test their websites and mobile applications.
v-list-item-action
v-btn(icon, href='https://www.browserstack.com/', target='_blank')
v-icon(color='grey') public
v-divider
v-list-tile
v-list-tile-avatar
v-list-item
v-list-item-avatar
img(src='https://static.requarks.io/logo/cloudflare.svg', alt='Cloudflare')
v-list-tile-content
v-list-tile-title Cloudflare
v-list-tile-sub-title Providing content delivery network services, DDoS mitigation, Internet security and distributed domain name server services.
v-list-tile-action
v-list-item-content
v-list-item-title Cloudflare
v-list-item-sub-title Providing content delivery network services, DDoS mitigation, Internet security and distributed domain name server services.
v-list-item-action
v-btn(icon, href='https://www.cloudflare.com/', target='_blank')
v-icon(color='grey') public
v-divider
v-list-tile
v-list-tile-avatar
v-list-item
v-list-item-avatar
img(src='https://static.requarks.io/logo/digitalocean.svg', alt='DigitalOcean')
v-list-tile-content
v-list-tile-title DigitalOcean
v-list-tile-sub-title Providing developers and businesses a reliable, easy-to-use cloud computing platform of virtual servers (Droplets), object storage (Spaces), and more.
v-list-tile-action
v-list-item-content
v-list-item-title DigitalOcean
v-list-item-sub-title Providing developers and businesses a reliable, easy-to-use cloud computing platform of virtual servers (Droplets), object storage (Spaces), and more.
v-list-item-action
v-btn(icon, href='https://m.do.co/c/5f7445bfa4d0', target='_blank')
v-icon(color='grey') public
v-divider
v-list-tile
v-list-tile-avatar(tile)
v-list-item
v-list-item-avatar(tile)
img(src='/svg/logo-icons8.svg', alt='Icons8')
v-list-tile-content
v-list-tile-title Icons8
v-list-tile-sub-title All the Icons You Need. Guaranteed.
v-list-tile-action
v-list-item-content
v-list-item-title Icons8
v-list-item-sub-title All the Icons You Need. Guaranteed.
v-list-item-action
v-btn(icon, href='https://icons8.com', target='_blank')
v-icon(color='grey') public
v-divider
v-list-tile
v-list-tile-avatar(tile)
v-list-item
v-list-item-avatar(tile)
img(src='https://static.requarks.io/logo/lokalise.png', alt='Lokalise')
v-list-tile-content
v-list-tile-title Lokalise
v-list-tile-sub-title Lokalise is a translation management system built for agile teams who want to automate their localization process.
v-list-tile-action
v-list-item-content
v-list-item-title Lokalise
v-list-item-sub-title Lokalise is a translation management system built for agile teams who want to automate their localization process.
v-list-item-action
v-btn(icon, href='https://lokalise.co', target='_blank')
v-icon(color='grey') public
v-divider
v-list-tile
v-list-tile-avatar(tile)
v-list-item
v-list-item-avatar(tile)
img(src='https://static.requarks.io/logo/netlify.svg', alt='Netlify')
v-list-tile-content
v-list-tile-title Netlify
v-list-tile-sub-title Deploy modern static websites with Netlify. Get CDN, Continuous deployment, 1-click HTTPS, and all the services you need.
v-list-tile-action
v-list-item-content
v-list-item-title Netlify
v-list-item-sub-title Deploy modern static websites with Netlify. Get CDN, Continuous deployment, 1-click HTTPS, and all the services you need.
v-list-item-action
v-btn(icon, href='https://wwwnetlify.com', target='_blank')
v-icon(color='grey') public

@ -10,8 +10,8 @@
v-flex(xs12 md6 lg4 xl3 d-flex)
v-card.primary.dashboard-card.animated.fadeInUp(dark)
v-card-text
v-icon.dashboard-icon insert_drive_file
.subheading {{$t('admin:dashboard.pages')}}
v-icon.dashboard-icon mdi-file-document-outline
.overline {{$t('admin:dashboard.pages')}}
animated-number.display-1(
:value='info.pagesTotal'
:duration='2000'
@ -21,8 +21,8 @@
v-flex(xs12 md6 lg4 xl3 d-flex)
v-card.indigo.lighten-1.dashboard-card.animated.fadeInUp.wait-p2s(dark)
v-card-text
v-icon.dashboard-icon person
.subheading {{$t('admin:dashboard.users')}}
v-icon.dashboard-icon mdi-account
.overline {{$t('admin:dashboard.users')}}
animated-number.display-1(
:value='info.usersTotal'
:duration='2000'
@ -32,8 +32,8 @@
v-flex(xs12 md6 lg4 xl3 d-flex)
v-card.indigo.lighten-2.dashboard-card.animated.fadeInUp.wait-p4s(dark)
v-card-text
v-icon.dashboard-icon people
.subheading {{$t('admin:dashboard.groups')}}
v-icon.dashboard-icon mdi-account-group
.overline {{$t('admin:dashboard.groups')}}
animated-number.display-1(
:value='info.groupsTotal'
:duration='2000'
@ -46,19 +46,19 @@
dark
)
v-btn.btn-animate-wrench(fab, absolute, right, top, small, light, to='system', v-if='hasPermission(`manage:system`)')
v-icon(:color='isLatestVersion ? `teal` : `red darken-4`') build
v-icon(:color='isLatestVersion ? `teal` : `red darken-4`', small) mdi-wrench
v-card-text
v-icon.dashboard-icon blur_on
v-icon.dashboard-icon mdi-blur
.subheading Wiki.js {{info.currentVersion}}
.body-2(v-if='isLatestVersion') {{$t('admin:dashboard.versionLatest')}}
.body-2(v-else) {{$t('admin:dashboard.versionNew', { version: info.latestVersion })}}
v-flex(xs12, xl6)
v-card.radius-7.animated.fadeInUp.wait-p2s
v-card-title.subheading(:class='$vuetify.dark ? `grey darken-2` : `grey lighten-5`') Recent Pages
v-card-title.subtitle-1(:class='$vuetify.dark ? `grey darken-2` : `grey lighten-5`') Recent Pages
v-data-table.pb-2(
:items='recentPages'
hide-actions
hide-headers
hide-default-footer
hide-default-header
)
template(slot='items' slot-scope='props')
td(width='20', style='padding-right: 0;'): v-icon insert_drive_file
@ -71,11 +71,11 @@
.caption Created {{ props.item.createdAt | moment('calendar') }}
v-flex(xs12, xl6)
v-card.radius-7.animated.fadeInUp.wait-p4s
v-card-title.subheading(:class='$vuetify.dark ? `grey darken-2` : `grey lighten-5`') Most Popular Pages
v-card-title.subtitle-1(:class='$vuetify.dark ? `grey darken-2` : `grey lighten-5`') Most Popular Pages
v-data-table.pb-2(
:items='popularPages'
hide-actions
hide-headers
hide-default-footer
hide-default-header
)
template(slot='items' slot-scope='props')
td(width='20', style='padding-right: 0;'): v-icon insert_drive_file
@ -91,11 +91,12 @@
v-card.dashboard-contribute.animated.fadeInUp.wait-p4s
v-card-text
img(src='/svg/icon-heart-health.svg', alt='Contribute', style='height: 80px;')
.pl-3
.subheading {{$t('admin:contribute.title')}}
.body-2.pt-2 {{$t('admin:dashboard.contributeSubtitle')}}
.body-1 {{$t('admin:dashboard.contributeHelp')}}
v-btn.mx-0.mt-2(:color='$vuetify.dark ? `indigo lighten-3` : `indigo`', outline, small, to='/contribute') {{$t('admin:dashboard.contributeLearnMore')}}
.pl-5
.subtitle-1 {{$t('admin:contribute.title')}}
.body-2.mt-3: strong {{$t('admin:dashboard.contributeSubtitle')}}
.body-2 {{$t('admin:dashboard.contributeHelp')}}
v-btn.mx-0.mt-4(:color='$vuetify.dark ? `indigo lighten-3` : `indigo`', outlined, small, to='/contribute')
.caption: strong {{$t('admin:dashboard.contributeLearnMore')}}
</template>
@ -140,6 +141,7 @@ export default {
.dashboard-card {
display: flex;
width: 100%;
border-radius: 7px;
.v-card__text {
@ -161,10 +163,10 @@ export default {
.v-card__text {
display: flex;
align-items: center;
color: mc('indigo', '500');
color: mc('indigo', '500') !important;
@at-root .theme--dark & {
color: mc('grey', '300');
color: mc('grey', '300') !important;
}
}
}
@ -173,7 +175,7 @@ export default {
position: absolute;
right: 0;
top: 12px;
font-size: 120px;
font-size: 120px !important;
opacity: .25;
}

@ -9,61 +9,60 @@
.subheading.grey--text.animated.fadeInLeft {{ $t('admin:general.subtitle') }}
v-spacer
v-btn.animated.fadeInDown(color='success', depressed, @click='save', large)
v-icon(left) check
v-icon(left) mdi-check
span {{$t('common:actions.apply')}}
v-form.pt-3
v-layout(row wrap)
v-flex(lg6 xs12)
v-form
v-card.wiki-form.animated.fadeInUp
v-card.animated.fadeInUp
v-toolbar(color='primary', dark, dense, flat)
v-toolbar-title
.subheading {{ $t('admin:general.siteInfo') }}
v-toolbar-title.subtitle-1 {{ $t('admin:general.siteInfo') }}
v-subheader {{$t('admin:general.general')}}
.px-3.pb-3
v-text-field(
outline
outlined
:label='$t(`admin:general.siteUrl`)'
required
:counter='255'
v-model='config.host'
prepend-icon='label_important'
prepend-icon='mdi-label-variant-outline'
:hint='$t(`admin:general.siteUrlHint`)'
persistent-hint
)
v-text-field.mt-2(
outline
v-text-field.mt-3(
outlined
:label='$t(`admin:general.siteTitle`)'
required
:counter='50'
v-model='config.title'
prepend-icon='public'
prepend-icon='mdi-earth'
:hint='$t(`admin:general.siteTitleHint`)'
persistent-hint
)
v-divider
v-subheader {{$t('admin:general.logo')}} #[v-chip.ml-2(label, color='grey', small, outline) coming soon]
v-subheader {{$t('admin:general.logo')}} #[v-chip.ml-2(label, color='grey', small, outlined) coming soon]
v-card-text.pb-4.pl-5
v-layout.px-3(row, align-center)
v-avatar(size='100', :color='$vuetify.dark ? `grey darken-2` : `grey lighten-3`', :tile='config.logoIsSquare')
.ml-4
v-btn.mx-0(color='teal', depressed, disabled)
v-icon(left) cloud_upload
v-btn.mr-3(color='teal', depressed, disabled)
v-icon(left) mdi-cloud-upload
span {{$t('admin:general.uploadLogo')}}
v-btn(color='teal', depressed, disabled)
v-icon(left) clear
v-icon(left) mdi-close
span {{$t('admin:general.uploadClear')}}
.caption.grey--text {{$t('admin:general.uploadSizeHint', { size: '120x120' })}}
.caption.mt-3.grey--text {{$t('admin:general.uploadSizeHint', { size: '120x120' })}}
.caption.grey--text {{$t('admin:general.uploadTypesHint', { typeList: 'SVG, PNG', lastType: 'JPG' })}}.
v-divider
v-subheader {{$t('admin:general.footerCopyright')}}
.px-3.pb-3
v-text-field(
outline
outlined
:label='$t(`admin:general.companyName`)'
v-model='config.company'
:counter='255'
prepend-icon='business'
prepend-icon='mdi-domain'
persistent-hint
:hint='$t(`admin:general.companyNameHint`)'
)
@ -71,31 +70,30 @@
v-subheader SEO
.px-3.pb-3
v-text-field(
outline
outlined
:label='$t(`admin:general.siteDescription`)'
:counter='255'
v-model='config.description'
prepend-icon='explore'
prepend-icon='mdi-compass'
:hint='$t(`admin:general.siteDescriptionHint`)'
persistent-hint
)
v-select.mt-2(
outline
v-select.mt-3(
outlined
:label='$t(`admin:general.metaRobots`)'
multiple
:items='metaRobots'
v-model='config.robots'
prepend-icon='explore'
prepend-icon='mdi-compass'
:return-object='false'
:hint='$t(`admin:general.metaRobotsHint`)'
persistent-hint
)
v-flex(lg6 xs12)
v-card.wiki-form.animated.fadeInUp.wait-p4s
v-card.animated.fadeInUp.wait-p4s
v-toolbar(color='primary', dark, dense, flat)
v-toolbar-title
.subheading Features
v-toolbar-title.subtitle-1 Features
v-spacer
v-chip(label, color='white', small).primary--text coming soon
v-card-text
@ -108,11 +106,11 @@
disabled
)
v-text-field.mt-3(
outline
outlined
label='TinyPNG API Key'
:counter='255'
v-model='config.description'
prepend-icon='subdirectory_arrow_right'
prepend-icon='mdi-subdirectory-arrow-right'
hint='Get your API key at https://tinypng.com/developers'
persistent-hint
disabled

@ -29,25 +29,25 @@
v-btn.is-icon(slot='activator', flat, outline, color='primary')
v-icon more_horiz
v-list(dense)
v-list-tile(@click='comingSoon')
v-list-tile-avatar
v-list-item(@click='comingSoon')
v-list-item-avatar
v-icon keyboard_capslock
v-list-tile-title Load Preset
v-list-item-title Load Preset
v-divider
v-list-tile(@click='comingSoon')
v-list-tile-avatar
v-list-item(@click='comingSoon')
v-list-item-avatar
v-icon publish
v-list-tile-title Save As Preset
v-list-item-title Save As Preset
v-divider
v-list-tile(@click='comingSoon')
v-list-tile-avatar
v-list-item(@click='comingSoon')
v-list-item-avatar
v-icon cloud_upload
v-list-tile-title Import Rules
v-list-item-title Import Rules
v-divider
v-list-tile(@click='comingSoon')
v-list-tile-avatar
v-list-item(@click='comingSoon')
v-list-item-avatar
v-icon cloud_download
v-list-tile-title Export Rules
v-list-item-title Export Rules
v-card-text(:class='$vuetify.dark ? `grey darken-4-l5` : `white`')
.rules
.caption(v-if='group.pageRules.length === 0')
@ -81,15 +81,15 @@
v-chip.white--text.ml-0(v-if='index <= 1', small, label, :color='rule.deny ? `red` : `green`').caption {{ item.value }}
v-chip.white--text.ml-0(v-if='index === 2', small, label, :color='rule.deny ? `red lighten-2` : `green lighten-2`').caption + {{ rule.roles.length - 2 }} more
template(slot='item', slot-scope='props')
v-list-tile-action(style='min-width: 30px;')
v-list-item-action(style='min-width: 30px;')
v-checkbox(
v-model='props.tile.props.value'
hide-details
color='primary'
)
v-icon.mr-2(:color='rule.deny ? `red` : `green`') {{props.item.icon}}
v-list-tile-content
v-list-tile-title.body-2 {{props.item.text}}
v-list-item-content
v-list-item-title.body-2 {{props.item.text}}
v-chip.mr-2.grey--text(label, small, :color='$vuetify.dark ? `grey darken-4` : `grey lighten-4`').caption {{props.item.value}}
//- Match
@ -105,10 +105,10 @@
template(slot='selection', slot-scope='{ item, index }')
.body-1 {{item.text}}
template(slot='item', slot-scope='data')
v-list-tile-avatar
v-list-item-avatar
v-avatar.white--text.radius-4(color='blue', size='30', tile) {{ data.item.icon }}
v-list-tile-content
v-list-tile-title(v-html='data.item.text')
v-list-item-content
v-list-item-title(v-html='data.item.text')
//- Locales
v-select.mr-1(
:background-color='$vuetify.dark ? `grey darken-3-d5` : `blue-grey lighten-5`'
@ -125,8 +125,8 @@
template(slot='selection', slot-scope='{ item, index }')
v-chip.white--text.ml-0(v-if='rule.locales.length === 1', small, label, :color='rule.deny ? `red` : `green`').caption {{ item.value.toUpperCase() }}
v-chip.white--text.ml-0(v-else-if='index === 0', small, label, :color='rule.deny ? `red` : `green`').caption {{ rule.locales.length }} locales
v-list-tile(slot='prepend-item', @click='rule.locales = []')
v-list-tile-action(style='min-width: 30px;')
v-list-item(slot='prepend-item', @click='rule.locales = []')
v-list-item-action(style='min-width: 30px;')
v-checkbox(
:input-value='rule.locales.length === 0'
hide-details
@ -134,19 +134,19 @@
readonly
)
v-icon.mr-2(:color='rule.deny ? `red` : `green`') public
v-list-tile-content
v-list-tile-title.body-2 Any Locale
v-list-item-content
v-list-item-title.body-2 Any Locale
v-divider(slot='prepend-item')
template(slot='item', slot-scope='props')
v-list-tile-action(style='min-width: 30px;')
v-list-item-action(style='min-width: 30px;')
v-checkbox(
v-model='props.tile.props.value'
hide-details
color='primary'
)
v-icon.mr-2(:color='rule.deny ? `red` : `green`') language
v-list-tile-content
v-list-tile-title.body-2 {{props.item.text}}
v-list-item-content
v-list-item-title.body-2 {{props.item.text}}
v-chip.mr-2.grey--text(label, small, :color='$vuetify.dark ? `grey darken-4` : `grey lighten-4`').caption {{props.item.value.toUpperCase()}}
//- Path

@ -30,16 +30,16 @@
v-menu(bottom, right, min-width='200')
v-btn(icon, slot='activator'): v-icon.grey--text.text--darken-1 more_horiz
v-list
v-list-tile(:to='`/users/` + props.item.id')
v-list-tile-action: v-icon(color='primary') person
v-list-tile-content
v-list-tile-title View User Profile
v-list-item(:to='`/users/` + props.item.id')
v-list-item-action: v-icon(color='primary') person
v-list-item-content
v-list-item-title View User Profile
template(v-if='props.item.id !== 2')
v-divider
v-list-tile(@click='unassignUser(props.item.id)')
v-list-tile-action: v-icon(color='orange') highlight_off
v-list-tile-content
v-list-tile-title Unassign
v-list-item(@click='unassignUser(props.item.id)')
v-list-item-action: v-icon(color='orange') highlight_off
v-list-item-content
v-list-item-title Unassign
template(slot='no-data')
v-alert.ma-3(icon='warning', :value='true', outline) No users to display.
.text-xs-center.py-2(v-if='group.users.length > 15')

@ -8,19 +8,19 @@
.headline.blue--text.text--darken-2.animated.fadeInLeft Groups
.subheading.grey--text.animated.fadeInLeft.wait-p4s Manage groups and their permissions
v-spacer
v-btn.animated.fadeInDown.wait-p2s(color='grey', outline, @click='refresh', large)
v-icon refresh
v-btn.animated.fadeInDown.wait-p2s.mr-3(color='grey', outlined, @click='refresh', large)
v-icon mdi-refresh
v-dialog(v-model='newGroupDialog', max-width='500')
v-btn.animated.fadeInDown(color='primary', depressed, slot='activator', large)
v-icon(left) add
span New Group
v-card.wiki-form
template(v-slot:activator='{ on }')
v-btn.animated.fadeInDown(color='primary', depressed, v-on='on', large)
v-icon(left) mdi-plus
span New Group
v-card
.dialog-header.is-short New Group
v-card-text
v-text-field.md2(
outline
background-color='grey lighten-3'
prepend-icon='people'
outlined
prepend-icon='mdi-account-group'
v-model='newGroupName'
label='Group Name'
counter='255'
@ -30,7 +30,7 @@
)
v-card-chin
v-spacer
v-btn(flat, @click='newGroupDialog = false') Cancel
v-btn(text, @click='newGroupDialog = false') Cancel
v-btn(color='primary', @click='createGroup') Create
v-card.mt-3.animated.fadeInUp
v-data-table(

@ -9,20 +9,19 @@
.subheading.grey--text.animated.fadeInLeft.wait-p4s {{ $t('admin:locale.subtitle') }}
v-spacer
v-btn.animated.fadeInDown(color='success', depressed, @click='save', large, :loading='loading')
v-icon(left) check
v-icon(left) mdi-check
span {{$t('common:actions.apply')}}
v-form.pt-3
v-layout(row wrap)
v-flex(lg6 xs12)
v-card.wiki-form.animated.fadeInUp
v-toolbar(color='primary', dark, dense, flat)
v-toolbar-title
.subheading {{ $t('admin:locale.settings') }}
v-toolbar-title.subtitle-1 {{ $t('admin:locale.settings') }}
v-card-text
v-select(
outline
outlined
:items='installedLocales'
prepend-icon='language'
prepend-icon='mdi-web'
v-model='selectedLocale'
item-value='code'
item-text='nativeName'
@ -32,13 +31,13 @@
)
template(slot='item', slot-scope='data')
template(v-if='typeof data.item !== "object"')
v-list-tile-content(v-text='data.item')
v-list-item-content(v-text='data.item')
template(v-else)
v-list-tile-avatar
v-list-item-avatar
v-avatar.blue.white--text(tile, size='40', v-html='data.item.code.toUpperCase()')
v-list-tile-content
v-list-tile-title(v-html='data.item.name')
v-list-tile-sub-title(v-html='data.item.nativeName')
v-list-item-content
v-list-item-title(v-html='data.item.name')
v-list-item-sub-title(v-html='data.item.nativeName')
v-divider.mt-3
v-switch(
v-model='autoUpdate'
@ -50,8 +49,7 @@
v-card.wiki-form.mt-3.animated.fadeInUp.wait-p2s
v-toolbar(color='primary', dark, dense, flat)
v-toolbar-title
.subheading {{ $t('admin:locale.namespacing') }}
v-toolbar-title.subtitle-1 {{ $t('admin:locale.namespacing') }}
v-card-text
v-switch(
v-model='namespacing'
@ -61,19 +59,19 @@
:hint='$t("admin:locale.namespaces.hint")'
)
v-alert.mt-3(
outline
outlined
color='orange'
:value='true'
icon='warning'
icon='mdi-alert'
)
span {{ $t('admin:locale.namespacingPrefixWarning.title', { langCode: selectedLocale }) }}
.caption.grey--text {{ $t('admin:locale.namespacingPrefixWarning.subtitle') }}
v-divider.mt-3.mb-4
v-select(
outline
outlined
:disabled='!namespacing'
:items='installedLocales'
prepend-icon='language'
prepend-icon='mdi-web'
multiple
chips
deletable-chips
@ -87,52 +85,47 @@
)
template(slot='item', slot-scope='data')
template(v-if='typeof data.item !== "object"')
v-list-tile-content(v-text='data.item')
v-list-item-content(v-text='data.item')
template(v-else)
v-list-tile-avatar
v-list-item-avatar
v-avatar.blue.white--text(tile, size='40', v-html='data.item.code.toUpperCase()')
v-list-tile-content
v-list-tile-title(v-html='data.item.name')
v-list-tile-sub-title(v-html='data.item.nativeName')
v-list-tile-action
v-list-item-content
v-list-item-title(v-html='data.item.name')
v-list-item-sub-title(v-html='data.item.nativeName')
v-list-item-action
v-checkbox(:input-value='data.tile.props.value', color='primary', value)
v-flex(lg6 xs12)
v-card.animated.fadeInUp.wait-p4s
v-toolbar(color='teal', dark, dense, flat)
v-toolbar-title
.subheading {{ $t('admin:locale.downloadTitle') }}
v-toolbar-title.subtitle-1 {{ $t('admin:locale.downloadTitle') }}
v-data-table(
:headers='headers',
:items='locales',
hide-actions,
hide-default-footer,
item-key='code',
:rows-per-page-items='[-1]'
)
template(v-slot:items='lc')
td
v-chip.white--text(label, color='teal', small) {{lc.item.code}}
td
strong {{lc.item.name}}
td
span {{ lc.item.nativeName }}
td.text-xs-center
v-icon(v-if='lc.item.isRTL') check
td
.d-flex.align-center.pl-4
.caption.mr-2(:class='lc.item.availability <= 33 ? `red--text` : (lc.item.availability <= 66) ? `orange--text` : `green--text`') {{lc.item.availability}}%
v-progress-circular(:value='lc.item.availability', width='2', size='20', :color='lc.item.availability <= 33 ? `red` : (lc.item.availability <= 66) ? `orange` : `green`')
td.text-xs-center
v-progress-circular(v-if='lc.item.isDownloading', indeterminate, color='blue', size='20', :width='2')
v-btn(v-else-if='lc.item.isInstalled && lc.item.installDate < lc.item.updatedAt', icon, @click='download(lc.item)')
v-icon.blue--text cached
v-btn(v-else-if='lc.item.isInstalled', icon, @click='download(lc.item)')
v-icon.green--text check
v-btn(v-else, icon, @click='download(lc.item)')
v-icon.grey--text cloud_download
:items-per-page='1000'
)
template(v-slot:item.code='{ item }')
v-chip.white--text(label, color='teal', small) {{item.code}}
template(v-slot:item.name='{ item }')
strong {{item.name}}
template(v-slot:item.isRTL='{ item }')
v-icon(v-if='item.isRTL') mdi-check
template(v-slot:item.availability='{ item }')
.d-flex.align-center.pl-4
v-progress-circular(:value='item.availability', width='2', size='20', :color='item.availability <= 33 ? `red` : (item.availability <= 66) ? `orange` : `green`')
.caption.ml-2(:class='item.availability <= 33 ? `red--text` : (item.availability <= 66) ? `orange--text` : `green--text`') {{item.availability}}%
template(v-slot:item.isInstalled='{ item }')
v-progress-circular(v-if='item.isDownloading', indeterminate, color='blue', size='20', :width='2')
v-btn(v-else-if='item.isInstalled && item.installDate < item.updatedAt', icon, @click='download(item)')
v-icon.blue--text mdi-cached
v-btn(v-else-if='item.isInstalled', icon, @click='download(item)')
v-icon.green--text mdi-check
v-btn(v-else, icon, small, @click='download(item)')
v-icon.grey--text mdi-cloud-download
v-card.wiki-form.mt-3.animated.fadeInUp.wait-p5s
v-toolbar(color='teal', dark, dense, flat)
v-toolbar-title
.subheading {{ $t('admin:locale.sideload') }}
v-toolbar-title.subtitle-1 {{ $t('admin:locale.sideload') }}
v-spacer
v-chip(label, color='white', small).teal--text coming soon
v-card-text
@ -170,7 +163,7 @@ export default {
text: this.$t('admin:locale.code'),
align: 'left',
value: 'code',
width: 10
width: 90
},
{
text: this.$t('admin:locale.name'),
@ -193,12 +186,13 @@ export default {
text: this.$t('admin:locale.availability'),
align: 'center',
value: 'availability',
sortable: false,
width: 100
},
{
text: this.$t('admin:locale.download'),
align: 'center',
value: 'code',
value: 'isInstalled',
sortable: false,
width: 100
}

@ -22,7 +22,7 @@
v-subheader {{ $t('admin:mail.sender') }}
.px-3.pb-3
v-text-field(
outline
outlined
v-model='config.senderName'
:label='$t(`admin:mail.senderName`)'
required
@ -30,7 +30,7 @@
prepend-icon='person'
)
v-text-field(
outline
outlined
v-model='config.senderEmail'
:label='$t(`admin:mail.senderEmail`)'
required
@ -41,7 +41,7 @@
v-subheader {{ $t('admin:mail.smtp') }}
.px-3.pb-3
v-text-field(
outline
outlined
v-model='config.host'
:label='$t(`admin:mail.smtpHost`)'
required
@ -49,7 +49,7 @@
prepend-icon='memory'
)
v-text-field(
outline
outlined
v-model='config.port'
:label='$t(`admin:mail.smtpPort`)'
required
@ -67,7 +67,7 @@
prepend-icon='vpn_lock'
)
v-text-field.mt-3(
outline
outlined
v-model='config.user'
:label='$t(`admin:mail.smtpUser`)'
required
@ -75,7 +75,7 @@
prepend-icon='lock_outline'
)
v-text-field(
outline
outlined
v-model='config.pass'
:label='$t(`admin:mail.smtpPwd`)'
required
@ -98,7 +98,7 @@
prepend-icon='vpn_key'
)
v-text-field(
outline
outlined
v-model='config.dkimDomainName'
:label='$t(`admin:mail.dkimDomainName`)'
:counter='255'
@ -106,7 +106,7 @@
:disabled='!config.useDKIM'
)
v-text-field(
outline
outlined
v-model='config.dkimKeySelector'
:label='$t(`admin:mail.dkimKeySelector`)'
:counter='255'
@ -114,7 +114,7 @@
:disabled='!config.useDKIM'
)
v-text-field(
outline
outlined
v-model='config.dkimPrivateKey'
:label='$t(`admin:mail.dkimPrivateKey`)'
prepend-icon='vpn_key'
@ -131,7 +131,7 @@
.pa-3
.body-2.grey--text.text--darken-2 {{ $t('admin:mail.testHint') }}
v-text-field.mt-3(
outline
outlined
v-model='testEmail'
:label='$t(`admin:mail.testRecipient`)'
:counter='255'

@ -8,30 +8,30 @@
.headline.primary--text.animated.fadeInLeft {{$t('navigation.title')}}
.subheading.grey--text.animated.fadeInLeft.wait-p4s {{$t('navigation.subtitle')}}
v-spacer
v-btn.animated.fadeInDown.wait-p2s(outline, color='grey', @click='refresh', large)
v-icon refresh
v-btn.animated.fadeInDown.wait-p2s.mr-3(outlined, color='grey', @click='refresh', large)
v-icon mdi-refresh
v-btn.animated.fadeInDown(color='success', depressed, @click='save', large)
v-icon(left) check
v-icon(left) mdi-check
span {{$t('common:actions.apply')}}
v-container.pa-0.mt-3(fluid, grid-list-lg)
v-layout(row)
v-flex(style='flex: 0 0 350px;')
v-card.animated.fadeInUp
v-list.py-2(dense, dark, :class='navTree.length < 1 ? "grey lighten-4" : "primary"')
v-list-tile(v-if='navTree.length < 1')
v-list-tile-avatar: v-icon(color='grey') explore_off
v-list-tile-content
v-list.py-2(dense, nav, dark, :class='navTree.length < 1 ? "grey lighten-4" : "primary"')
v-list-item(v-if='navTree.length < 1')
v-list-item-avatar(size='24'): v-icon(color='grey') explore_off
v-list-item-content
.caption.grey--text {{$t('navigation.emptyList')}}
draggable(v-model='navTree')
template(v-for='navItem in navTree')
v-list-tile(
v-list-item(
v-if='navItem.kind === "link"'
:key='navItem.id'
:class='(navItem === current) ? "blue" : ""'
@click='selectItem(navItem)'
)
v-list-tile-avatar: v-icon {{navItem.icon}}
v-list-tile-title {{navItem.label}}
v-list-item-avatar(size='24'): v-icon {{navItem.icon}}
v-list-item-title {{navItem.label}}
.py-2.clickable(
v-else-if='navItem.kind === "divider"'
:key='navItem.id'
@ -47,58 +47,56 @@
) {{navItem.label}}
v-card-chin
v-menu(offset-y, bottom, min-width='200px', style='flex: 1 1;')
v-btn(slot='activator', color='primary', depressed, block)
v-icon(left) add
span {{$t('common:actions.add')}}
template(v-slot:activator='{ on }')
v-btn(v-on='on', color='primary', depressed, block)
v-icon(left) mdi-plus
span {{$t('common:actions.add')}}
v-list
v-list-tile(@click='addItem("link")')
v-list-tile-avatar: v-icon link
v-list-tile-title {{$t('navigation.link')}}
v-list-tile(@click='addItem("header")')
v-list-tile-avatar: v-icon title
v-list-tile-title {{$t('navigation.header')}}
v-list-tile(@click='addItem("divider")')
v-list-tile-avatar: v-icon power_input
v-list-tile-title {{$t('navigation.divider')}}
v-list-item(@click='addItem("link")')
v-list-item-avatar(size='24'): v-icon mdi-link
v-list-item-title {{$t('navigation.link')}}
v-list-item(@click='addItem("header")')
v-list-item-avatar(size='24'): v-icon mdi-format-title
v-list-item-title {{$t('navigation.header')}}
v-list-item(@click='addItem("divider")')
v-list-item-avatar(size='24'): v-icon mdi-minus
v-list-item-title {{$t('navigation.divider')}}
v-flex.animated.fadeInUp.wait-p2s
v-card.wiki-form(v-if='current.kind === "link"')
v-toolbar(dense, color='blue', flat, dark)
.subheading {{$t('navigation.edit', { kind: $t('navigation.link') })}}
v-toolbar(dense, color='blue', flat, dark).subtitle-1 {{$t('navigation.edit', { kind: $t('navigation.link') })}}
v-card-text
v-text-field(
outline
outlined
:label='$t("navigation.label")'
prepend-icon='title'
prepend-icon='mdi-format-title'
v-model='current.label'
)
v-text-field(
outline
outlined
:label='$t("navigation.icon")'
prepend-icon='casino'
prepend-icon='mdi-dice-5'
v-model='current.icon'
hide-details
)
.caption.pt-3.pl-5 The default icon set is #[strong Material Icons]. In order to use another icon set, you must first select it in the Theme administration section.
.caption.pt-3.pl-5 #[strong Material Icons] #[em (default)]
.caption.pl-5 Refer to the #[a(href='https://material.io/tools/icons/?style=baseline', target='_blank') Material Icons Reference] for the list of all possible values.
.caption.pt-3.pl-5 The default icon set is #[strong Material Design Icons]. In order to use another icon set, you must first select it in the Theme administration section.
.caption.pt-3.pl-5: strong Material Design Icons
.caption.pl-5 Refer to the #[a(href='https://cdn.materialdesignicons.com/3.7.95/', target='_blank') Material Design Icons Reference] for the list of all possible values. You must prefix all values with #[code mdi-], e.g. #[code mdi-home]
.caption.pl-5 Refer to the #[a(href='https://materialdesignicons.com/', target='_blank') Material Design Icons Reference] for the list of all possible values. You must prefix all values with #[code mdi-], e.g. #[code mdi-home]
.caption.pt-3.pl-5: strong Font Awesome 5
.caption.pl-5 Refer to the #[a(href='https://fontawesome.com/icons?d=gallery&m=free', target='_blank') Font Awesome 5 Reference] for the list of all possible values. You must prefix all values with #[code fas fa-], e.g. #[code fas fa-home]
.caption.pt-3.pl-5: strong Font Awesome 4
.caption.pl-5 Refer to the #[a(href='https://fontawesome.com/v4.7.0/icons/', target='_blank') Font Awesome 4 Reference] for the list of all possible values. You must prefix all values with #[code fa fa-], e.g. #[code fa fa-home]
v-select.mt-4(
outline
outlined
:label='$t("navigation.targetType")'
prepend-icon='near_me'
prepend-icon='mdi-near-me'
:items='navTypes'
v-model='current.targetType'
)
v-text-field(
v-if='current.targetType === `external`'
outline
outlined
:label='$t("navigation.target")'
prepend-icon='near_me'
prepend-icon='mdi-near-me'
v-model='current.target'
)
v-btn(
@ -108,11 +106,11 @@
disabled
@click='selectPage'
)
v-icon(left) search
v-icon(left) mdi-search
span Select Page...
v-text-field(
v-else-if='current.targetType === `search`'
outline
outlined
:label='$t("navigation.navType.searchQuery")'
prepend-icon='search'
v-model='current.target'
@ -120,28 +118,27 @@
v-card-chin
v-spacer
v-btn(color='red', outline, @click='deleteItem(current)')
v-icon(left) delete
v-btn.px-5(color='red', outlined, @click='deleteItem(current)')
v-icon(left) mdi-delete
span {{$t('navigation.delete', { kind: $t('navigation.link') })}}
v-card(v-else-if='current.kind === "header"')
v-toolbar(dense, color='blue', flat, dark)
.subheading {{$t('navigation.edit', { kind: $t('navigation.header') })}}
v-card-text
v-text-field(
outline
background-color='grey lighten-2'
outlined
:label='$t("navigation.label")'
prepend-icon='title'
prepend-icon='mdi-format-title'
v-model='current.label'
)
v-card-chin
v-spacer
v-btn(color='red', outline, @click='deleteItem(current)')
v-icon(left) delete
v-btn.px-5(color='red', outlined, @click='deleteItem(current)')
v-icon(left) mdi-delete
span {{$t('navigation.delete', { kind: $t('navigation.header') })}}
div(v-else-if='current.kind === "divider"')
v-btn.mt-0(color='red', outline, @click='deleteItem(current)')
v-icon(left) delete
v-btn.mt-0.px-5(color='red', outlined, @click='deleteItem(current)')
v-icon(left) mdi-delete
span {{$t('navigation.delete', { kind: $t('navigation.divider') })}}
v-card(v-else)
v-card-text.grey--text(v-if='navTree.length > 0') {{$t('navigation.noSelectionText')}}
@ -172,7 +169,7 @@ export default {
return [
// { text: this.$t('navigation.navType.external'), value: 'external' },
{ text: this.$t('navigation.navType.home'), value: 'home' },
{ text: 'Internal Path / External Link', value: 'external' },
{ text: 'Internal Path / External Link', value: 'external' }
// { text: this.$t('navigation.navType.page'), value: 'page' }
// { text: this.$t('navigation.navType.searchQuery'), value: 'search' }
]
@ -189,7 +186,7 @@ export default {
newItem = {
...newItem,
label: this.$t('navigation.untitled', { kind: this.$t(`navigation.link`) }),
icon: 'chevron_right',
icon: 'mdi-chevron-right',
targetType: 'home',
target: '/'
}

@ -54,41 +54,41 @@
v-icon.mr-2 subject
span Properties
v-list.py-0(two-line, dense)
v-list-tile
v-list-tile-content
v-list-tile-title.caption.grey--text Title
v-list-tile-sub-title.body-2.grey--text.text--darken-3 {{ page.title }}
v-list-item
v-list-item-content
v-list-item-title.caption.grey--text Title
v-list-item-sub-title.body-2.grey--text.text--darken-3 {{ page.title }}
v-divider
v-list-tile
v-list-tile-content
v-list-tile-title.caption.grey--text Description
v-list-tile-sub-title.body-2.grey--text.text--darken-3 {{ page.description || '-' }}
v-list-item
v-list-item-content
v-list-item-title.caption.grey--text Description
v-list-item-sub-title.body-2.grey--text.text--darken-3 {{ page.description || '-' }}
v-divider
v-list-tile
v-list-tile-content
v-list-tile-title.caption.grey--text Locale
v-list-tile-sub-title.body-2.grey--text.text--darken-3 {{ page.locale }}
v-list-tile-action
v-list-item
v-list-item-content
v-list-item-title.caption.grey--text Locale
v-list-item-sub-title.body-2.grey--text.text--darken-3 {{ page.locale }}
v-list-item-action
v-btn(icon)
v-icon(color='grey') edit
v-divider
v-list-tile
v-list-tile-content
v-list-tile-title.caption.grey--text Path
v-list-tile-sub-title.body-2.grey--text.text--darken-3 {{ page.path }}
v-list-tile-action
v-list-item
v-list-item-content
v-list-item-title.caption.grey--text Path
v-list-item-sub-title.body-2.grey--text.text--darken-3 {{ page.path }}
v-list-item-action
v-btn(icon)
v-icon(color='grey') edit
v-divider
v-list-tile
v-list-tile-content
v-list-tile-title.caption.grey--text Editor
v-list-tile-sub-title.body-2.grey--text.text--darken-3 {{ page.editor || '?' }}
v-list-item
v-list-item-content
v-list-item-title.caption.grey--text Editor
v-list-item-sub-title.body-2.grey--text.text--darken-3 {{ page.editor || '?' }}
v-divider
v-list-tile
v-list-tile-content
v-list-tile-title.caption.grey--text Content Type
v-list-tile-sub-title.body-2.grey--text.text--darken-3 {{ page.contentType || '?' }}
v-list-item
v-list-item-content
v-list-item-title.caption.grey--text Content Type
v-list-item-sub-title.body-2.grey--text.text--darken-3 {{ page.contentType || '?' }}
v-toolbar.elevation-2.mt-3.animated.fadeInUp.wait-p4s(color='white', dense)
v-spacer
@ -117,25 +117,25 @@
v-icon.mr-2 people
span Users
v-list.py-0(two-line, dense)
v-list-tile
v-list-tile-avatar
v-list-item
v-list-item-avatar
v-btn(icon, :to='`/users/` + page.creatorId')
v-icon(color='grey') person
v-list-tile-content
v-list-tile-title.caption.grey--text Creator
v-list-tile-sub-title.body-2.grey--text.text--darken-3 {{ page.creatorName }} #[em.caption ({{ page.creatorEmail }})]
v-list-tile-action
v-list-tile-action-text {{ page.createdAt | moment('calendar') }}
v-list-item-content
v-list-item-title.caption.grey--text Creator
v-list-item-sub-title.body-2.grey--text.text--darken-3 {{ page.creatorName }} #[em.caption ({{ page.creatorEmail }})]
v-list-item-action
v-list-item-action-text {{ page.createdAt | moment('calendar') }}
v-divider
v-list-tile
v-list-tile-avatar
v-list-item
v-list-item-avatar
v-btn(icon, :to='`/users/` + page.authorId')
v-icon(color='grey') person
v-list-tile-content
v-list-tile-title.caption.grey--text Last Editor
v-list-tile-sub-title.body-2.grey--text.text--darken-3 {{ page.authorName }} #[em.caption ({{ page.authorEmail }})]
v-list-tile-action
v-list-tile-action-text {{ page.updatedAt | moment('calendar') }}
v-list-item-content
v-list-item-title.caption.grey--text Last Editor
v-list-item-sub-title.body-2.grey--text.text--darken-3 {{ page.authorName }} #[em.caption ({{ page.authorEmail }})]
v-list-item-action
v-list-item-action-text {{ page.updatedAt | moment('calendar') }}
v-card.mt-3.animated.fadeInUp.wait-p4s
v-toolbar(color='primary', dense, dark, flat)
v-icon.mr-2 history

@ -8,37 +8,34 @@
.headline.blue--text.text--darken-2.animated.fadeInLeft Pages
.subheading.grey--text.animated.fadeInLeft.wait-p2s Manage pages
v-spacer
v-btn.animated.fadeInDown.wait-p1s(color='grey', outline, @click='refresh', large)
v-icon.grey--text refresh
v-btn.animated.fadeInDown(color='primary', outline, large, @click='recyclebin', disabled)
v-icon(left) delete_outline
v-btn.animated.fadeInDown.wait-p1s(color='grey', outlined, @click='refresh', large)
v-icon.grey--text mdi-refresh
v-btn.animated.fadeInDown.mx-3(color='primary', outlined, large, @click='recyclebin', disabled)
v-icon(left) mdi-delete-outline
span Recycle Bin
v-btn.animated.fadeInDown(color='primary', depressed, large, @click='newpage', disabled)
v-icon(left) add
v-icon(left) mdi-plus
span New Page
v-card.wiki-form.mt-3.animated.fadeInUp
v-toolbar(flat, :color='$vuetify.dark ? `grey darken-3-d5` : `grey lighten-5`', height='80')
v-spacer
v-text-field(
outline
outlined
v-model='search'
append-icon='search'
prepend-inner-icon='mdi-file-search-outline'
label='Search Pages...'
single-line
hide-details
)
v-select.ml-2(
outline
outlined
hide-details
single-line
label='Locale'
:items='langs'
v-model='selectedLang'
)
v-select.ml-2(
outline
outlined
hide-details
single-line
label='Publish State'
:items='states'
v-model='selectedState'

@ -43,18 +43,18 @@
v-spacer
v-list.py-0(two-line, dense)
template(v-for='(rdr, n) in core.children')
v-list-tile(
v-list-item(
avatar
:key='rdr.key'
@click='selectRenderer(rdr.key)'
:class='currentRenderer.key === rdr.key ? (darkMode ? `grey darken-4-l4` : `blue lighten-5`) : ``'
)
v-list-tile-avatar
v-list-item-avatar
v-icon(:color='currentRenderer.key === rdr.key ? "primary" : "grey"') {{rdr.icon}}
v-list-tile-content
v-list-tile-title {{rdr.title}}
v-list-tile-sub-title {{rdr.description}}
v-list-tile-avatar
v-list-item-content
v-list-item-title {{rdr.title}}
v-list-item-sub-title {{rdr.description}}
v-list-item-avatar
status-indicator(v-if='rdr.isEnabled', positive, pulse)
status-indicator(v-else, negative, pulse)
v-divider.my-0(v-if='n < core.children.length - 1')

@ -23,15 +23,15 @@
.subheading {{$t('admin:search.searchEngine')}}
v-list.py-0(two-line, dense)
template(v-for='(eng, idx) in engines')
v-list-tile(:key='eng.key', @click='selectedEngine = eng.key', :disabled='!eng.isAvailable')
v-list-tile-avatar
v-list-item(:key='eng.key', @click='selectedEngine = eng.key', :disabled='!eng.isAvailable')
v-list-item-avatar
v-icon(color='grey', v-if='!eng.isAvailable') cancel
v-icon(color='primary', v-else-if='eng.key === selectedEngine') radio_button_checked
v-icon(color='grey', v-else) radio_button_unchecked
v-list-tile-content
v-list-tile-title.body-2(:class='!eng.isAvailable ? `grey--text` : (selectedEngine === eng.key ? `primary--text` : ``)') {{ eng.title }}
v-list-tile-sub-title.caption(:class='!eng.isAvailable ? `grey--text text--lighten-1` : (selectedEngine === eng.key ? `blue--text ` : ``)') {{ eng.description }}
v-list-tile-avatar(v-if='selectedEngine === eng.key')
v-list-item-content
v-list-item-title.body-2(:class='!eng.isAvailable ? `grey--text` : (selectedEngine === eng.key ? `primary--text` : ``)') {{ eng.title }}
v-list-item-sub-title.caption(:class='!eng.isAvailable ? `grey--text text--lighten-1` : (selectedEngine === eng.key ? `blue--text ` : ``)') {{ eng.description }}
v-list-item-avatar(v-if='selectedEngine === eng.key')
v-icon.animated.fadeInLeft(color='primary') arrow_forward_ios
v-divider(v-if='idx < engines.length - 1')

@ -20,15 +20,15 @@
.subheading {{$t('admin:storage.targets')}}
v-list(two-line, dense).py-0
template(v-for='(tgt, idx) in targets')
v-list-tile(:key='tgt.key', @click='selectedTarget = tgt.key', :disabled='!tgt.isAvailable')
v-list-tile-avatar
v-list-item(:key='tgt.key', @click='selectedTarget = tgt.key', :disabled='!tgt.isAvailable')
v-list-item-avatar
v-icon(color='grey', v-if='!tgt.isAvailable') indeterminate_check_box
v-icon(color='primary', v-else-if='tgt.isEnabled', v-ripple, @click='tgt.key !== `local` && (tgt.isEnabled = false)') check_box
v-icon(color='grey', v-else, v-ripple, @click='tgt.isEnabled = true') check_box_outline_blank
v-list-tile-content
v-list-tile-title.body-2(:class='!tgt.isAvailable ? `grey--text` : (selectedTarget === tgt.key ? `primary--text` : ``)') {{ tgt.title }}
v-list-tile-sub-title.caption(:class='!tgt.isAvailable ? `grey--text text--lighten-1` : (selectedTarget === tgt.key ? `blue--text ` : ``)') {{ tgt.description }}
v-list-tile-avatar(v-if='selectedTarget === tgt.key')
v-list-item-content
v-list-item-title.body-2(:class='!tgt.isAvailable ? `grey--text` : (selectedTarget === tgt.key ? `primary--text` : ``)') {{ tgt.title }}
v-list-item-sub-title.caption(:class='!tgt.isAvailable ? `grey--text text--lighten-1` : (selectedTarget === tgt.key ? `blue--text ` : ``)') {{ tgt.description }}
v-list-item-avatar(v-if='selectedTarget === tgt.key')
v-icon.animated.fadeInLeft(color='primary') arrow_forward_ios
v-divider(v-if='idx < targets.length - 1')
@ -43,28 +43,28 @@
)
v-list.py-0(two-line, dense)
template(v-for='(tgt, n) in status')
v-list-tile(:key='tgt.key')
v-list-item(:key='tgt.key')
template(v-if='tgt.status === `pending`')
v-list-tile-avatar(color='purple')
v-list-item-avatar(color='purple')
v-icon(color='white') schedule
v-list-tile-content
v-list-tile-title.body-2 {{tgt.title}}
v-list-tile-sub-title.purple--text.caption {{tgt.status}}
v-list-tile-action
v-list-item-content
v-list-item-title.body-2 {{tgt.title}}
v-list-item-sub-title.purple--text.caption {{tgt.status}}
v-list-item-action
v-progress-circular(indeterminate, :size='20', :width='2', color='purple')
template(v-else-if='tgt.status === `operational`')
v-list-tile-avatar(color='green')
v-list-item-avatar(color='green')
v-icon(color='white') check_circle
v-list-tile-content
v-list-tile-title.body-2 {{tgt.title}}
v-list-tile-sub-title.green--text.caption {{$t('admin:storage.lastSync', { time: $options.filters.moment(tgt.lastAttempt, 'from') })}}
v-list-item-content
v-list-item-title.body-2 {{tgt.title}}
v-list-item-sub-title.green--text.caption {{$t('admin:storage.lastSync', { time: $options.filters.moment(tgt.lastAttempt, 'from') })}}
template(v-else)
v-list-tile-avatar(color='red')
v-list-item-avatar(color='red')
v-icon(color='white') highlight_off
v-list-tile-content
v-list-tile-title.body-2 {{tgt.title}}
v-list-tile-sub-title.red--text.caption {{$t('admin:storage.lastSyncAttempt', { time: $options.filters.moment(tgt.lastAttempt, 'from') })}}
v-list-tile-action
v-list-item-content
v-list-item-title.body-2 {{tgt.title}}
v-list-item-sub-title.red--text.caption {{$t('admin:storage.lastSyncAttempt', { time: $options.filters.moment(tgt.lastAttempt, 'from') })}}
v-list-item-action
v-menu
v-btn(slot='activator', icon)
v-icon(color='red') info
@ -73,7 +73,7 @@
v-card-text {{tgt.message}}
v-divider(v-if='n < status.length - 1')
v-list-tile(v-if='status.length < 1')
v-list-item(v-if='status.length < 1')
em {{$t('admin:storage.noTarget')}}
v-flex(xs12, lg9)

@ -13,83 +13,83 @@
v-btn.animated.fadeInLeft.wait-p2s.btn-animate-rotate(fab, absolute, right, top, small, light, @click='refresh'): v-icon refresh
v-list(two-line, dense)
v-subheader Wiki.js
v-list-tile(avatar)
v-list-tile-avatar
v-list-item(avatar)
v-list-item-avatar
v-icon.blue.white--text system_update_alt
v-list-tile-content
v-list-tile-title {{ $t('admin:system.currentVersion') }}
v-list-tile-sub-title {{ info.currentVersion }}
v-list-tile(avatar)
v-list-tile-avatar
v-list-item-content
v-list-item-title {{ $t('admin:system.currentVersion') }}
v-list-item-sub-title {{ info.currentVersion }}
v-list-item(avatar)
v-list-item-avatar
v-icon.blue.white--text open_in_browser
v-list-tile-content
v-list-tile-title {{ $t('admin:system.latestVersion') }}
v-list-tile-sub-title {{ info.latestVersion }}
v-list-tile-action
v-list-tile-action-text {{ $t('admin:system.published') }} {{ info.latestVersionReleaseDate | moment('from') }}
v-list-item-content
v-list-item-title {{ $t('admin:system.latestVersion') }}
v-list-item-sub-title {{ info.latestVersion }}
v-list-item-action
v-list-item-action-text {{ $t('admin:system.published') }} {{ info.latestVersionReleaseDate | moment('from') }}
v-divider.mt-3
v-subheader {{ $t('admin:system.hostInfo') }}
v-list-tile(avatar)
v-list-tile-avatar
v-list-item(avatar)
v-list-item-avatar
v-avatar.blue-grey(size='40')
img(:src='`/svg/icon-` + platformLogo + `-logo.svg`', alt='Platform', style='width: 24px;')
v-list-tile-content
v-list-tile-title {{ $t('admin:system.os') }}
v-list-tile-sub-title {{ (info.platform === 'docker') ? 'Docker Container (Linux)' : info.operatingSystem }}
v-list-tile(avatar)
v-list-tile-avatar
v-list-item-content
v-list-item-title {{ $t('admin:system.os') }}
v-list-item-sub-title {{ (info.platform === 'docker') ? 'Docker Container (Linux)' : info.operatingSystem }}
v-list-item(avatar)
v-list-item-avatar
v-icon.blue-grey.white--text computer
v-list-tile-content
v-list-tile-title {{ $t('admin:system.hostname') }}
v-list-tile-sub-title {{ info.hostname }}
v-list-tile(avatar)
v-list-tile-avatar
v-list-item-content
v-list-item-title {{ $t('admin:system.hostname') }}
v-list-item-sub-title {{ info.hostname }}
v-list-item(avatar)
v-list-item-avatar
v-icon.blue-grey.white--text nfc
v-list-tile-content
v-list-tile-title {{ $t('admin:system.cpuCores') }}
v-list-tile-sub-title {{ info.cpuCores }}
v-list-tile(avatar)
v-list-tile-avatar
v-list-item-content
v-list-item-title {{ $t('admin:system.cpuCores') }}
v-list-item-sub-title {{ info.cpuCores }}
v-list-item(avatar)
v-list-item-avatar
v-icon.blue-grey.white--text memory
v-list-tile-content
v-list-tile-title {{ $t('admin:system.totalRAM') }}
v-list-tile-sub-title {{ info.ramTotal }}
v-list-tile(avatar)
v-list-tile-avatar
v-list-item-content
v-list-item-title {{ $t('admin:system.totalRAM') }}
v-list-item-sub-title {{ info.ramTotal }}
v-list-item(avatar)
v-list-item-avatar
v-icon.blue-grey.white--text last_page
v-list-tile-content
v-list-tile-title {{ $t('admin:system.workingDirectory') }}
v-list-tile-sub-title {{ info.workingDirectory }}
v-list-tile(avatar)
v-list-tile-avatar
v-list-item-content
v-list-item-title {{ $t('admin:system.workingDirectory') }}
v-list-item-sub-title {{ info.workingDirectory }}
v-list-item(avatar)
v-list-item-avatar
v-icon.blue-grey.white--text settings
v-list-tile-content
v-list-tile-title {{ $t('admin:system.configFile') }}
v-list-tile-sub-title {{ info.configFile }}
v-list-item-content
v-list-item-title {{ $t('admin:system.configFile') }}
v-list-item-sub-title {{ info.configFile }}
v-flex(lg6 xs12)
v-card.pb-3.animated.fadeInUp.wait-p4s
v-list(dense)
v-subheader Node.js
v-list-tile(avatar)
v-list-tile-avatar
v-list-item(avatar)
v-list-item-avatar
v-avatar.light-green(size='40')
icon-node-js(fillColor='#FFFFFF')
v-list-tile-content
v-list-tile-title {{ info.nodeVersion }}
v-list-item-content
v-list-item-title {{ info.nodeVersion }}
v-divider.mt-3
v-subheader {{ info.dbType }}
v-list-tile(avatar)
v-list-tile-avatar
v-list-item(avatar)
v-list-item-avatar
v-avatar.indigo.darken-1(size='40')
icon-database(fillColor='#FFFFFF')
v-list-tile-content
v-list-tile-title(v-html='dbVersion')
v-list-tile-sub-title {{ info.dbHost }}
v-list-item-content
v-list-item-title(v-html='dbVersion')
v-list-item-sub-title {{ info.dbHost }}
v-alert.mt-3(:value='isDbLimited', color='deep-orange', icon='warning') {{ $t('admin:system.dbPartialSupport') }}
</template>

@ -9,37 +9,34 @@
.subheading.grey--text.animated.fadeInLeft.wait-p2s {{$t('admin:theme.subtitle')}}
v-spacer
v-btn.animated.fadeInRight(color='success', depressed, @click='save', large, :loading='loading')
v-icon(left) check
v-icon(left) mdi-check
span {{$t('common:actions.apply')}}
v-form.pt-3
v-layout(row wrap)
v-flex(lg6 xs12)
v-card.wiki-form.animated.fadeInUp
v-toolbar(color='primary', dark, dense, flat)
v-toolbar-title
.subheading {{$t('admin:theme.title')}}
v-toolbar-title.subtitle-1 {{$t('admin:theme.title')}}
v-card-text
v-select(
:items='themes'
outline
background-color='grey lighten-2'
prepend-icon='palette'
outlined
prepend-icon='mdi-palette'
v-model='config.theme'
:label='$t(`admin:theme.siteTheme`)'
persistent-hint
:hint='$t(`admin:theme.siteThemeHint`)'
)
template(slot='item', slot-scope='data')
v-list-tile-avatar
v-list-item-avatar
v-icon.blue--text(dark) filter_frames
v-list-tile-content
v-list-tile-title(v-html='data.item.text')
v-list-tile-sub-title(v-html='data.item.author')
v-list-item-content
v-list-item-title(v-html='data.item.text')
v-list-item-sub-title(v-html='data.item.author')
v-select.mt-3(
:items='iconsets'
outline
background-color='grey lighten-2'
prepend-icon='pets'
outlined
prepend-icon='mdi-paw'
v-model='config.iconset'
:label='$t(`admin:theme.iconset`)'
persistent-hint
@ -56,14 +53,12 @@
v-card.wiki-form.mt-3.animated.fadeInUp.wait-p2s
v-toolbar(color='primary', dark, dense, flat)
v-toolbar-title
.subheading {{$t(`admin:theme.codeInjection`)}}
v-toolbar-title.subtitle-1 {{$t(`admin:theme.codeInjection`)}}
v-card-text
v-textarea(
v-model='config.injectCSS'
:label='$t(`admin:theme.cssOverride`)'
outline
background-color='grey lighten-1'
outlined
color='primary'
persistent-hint
:hint='$t(`admin:theme.cssOverrideHint`)'
@ -75,8 +70,7 @@
v-textarea.mt-3(
v-model='config.injectHead'
:label='$t(`admin:theme.headHtmlInjection`)'
outline
background-color='grey lighten-1'
outlined
color='primary'
persistent-hint
:hint='$t(`admin:theme.headHtmlInjectionHint`)'
@ -85,8 +79,7 @@
v-textarea.mt-2(
v-model='config.injectBody'
:label='$t(`admin:theme.bodyHtmlInjection`)'
outline
background-color='grey lighten-1'
outlined
color='primary'
persistent-hint
:hint='$t(`admin:theme.bodyHtmlInjectionHint`)'
@ -95,16 +88,15 @@
v-flex(lg6 xs12)
v-card.animated.fadeInUp.wait-p2s
v-toolbar(color='teal', dark, dense, flat)
v-toolbar-title
.subheading {{$t('admin:theme.downloadThemes')}}
v-toolbar-title.subtitle-1 {{$t('admin:theme.downloadThemes')}}
v-spacer
v-chip(label, color='white', small).teal--text coming soon
v-data-table(
:headers='headers',
:items='themes',
hide-actions,
hide-default-footer,
item-key='value',
:rows-per-page-items='[-1]'
:items-per-page='1000'
)
template(v-slot:items='thm')
td
@ -114,11 +106,11 @@
td.text-xs-center
v-progress-circular(v-if='thm.item.isDownloading', indeterminate, color='blue', size='20', :width='2')
v-btn(v-else-if='thm.item.isInstalled && thm.item.installDate < thm.item.updatedAt', icon)
v-icon.blue--text cached
v-icon.blue--text mdi-cached
v-btn(v-else-if='thm.item.isInstalled', icon)
v-icon.green--text check
v-icon.green--text mdi-check
v-btn(v-else, icon)
v-icon.grey--text cloud_download
v-icon.grey--text mdi-cloud-download
</template>
<script>
@ -136,10 +128,9 @@ export default {
{ text: 'Default', author: 'requarks.io', value: 'default', isInstalled: true, installDate: '', updatedAt: '' }
],
iconsets: [
{ text: 'Material Icons (default)', value: 'md' },
{ text: 'Material Design Icons', value: 'mdi' },
{ text: 'Material Design Icons (default)', value: 'mdi' },
{ text: 'Font Awesome 5', value: 'fa' },
{ text: 'Font Awesome 4', value: 'fa4' },
{ text: 'Font Awesome 4', value: 'fa4' }
],
config: {
theme: 'default',

@ -2,46 +2,72 @@
v-dialog(v-model='isShown', max-width='650', persistent)
v-card.wiki-form
.dialog-header.is-short
v-icon.mr-3(color='white') mdi-plus
span New User
v-spacer
v-btn.mx-0(color='white', outlined, disabled, dark)
v-icon(left) mdi-database-import
span Bulk Import
v-card-text
v-select(
:items='providers'
item-text='title'
item-value='key'
outline
prepend-icon='business'
outlined
prepend-icon='mdi-domain'
v-model='provider'
label='Provider'
)
v-text-field(
outline
prepend-icon='email'
outlined
prepend-icon='mdi-at'
v-model='email'
label='Email Address'
v-validate='{ required: true, email: true, min: 2, max: 255 }',
data-vv-name='email',
data-vv-as='Email Address',
data-vv-scope='newUser',
:error-messages='errors.collect(`newUser.email`)'
key='newUserEmail'
persistent-hint
ref='emailInput'
)
v-text-field(
v-if='provider === `local`'
outline
prepend-icon='lock'
append-icon='casino'
outlined
prepend-icon='mdi-lock-outline'
append-icon='mdi-dice-5'
v-model='password'
:label='mustChangePwd ? `Temporary Password` : `Password`'
counter='255'
@click:append='generatePwd'
v-validate='{ required: true, min: 6, max: 255 }',
data-vv-name='password',
data-vv-as='Password',
data-vv-scope='newUser',
:error-messages='errors.collect(`newUser.password`)'
key='newUserPassword'
persistent-hint
)
v-text-field(
outline
prepend-icon='person'
outlined
prepend-icon='mdi-account-outline'
v-model='name'
label='Name'
v-validate='{ required: true, min: 2, max: 255 }',
data-vv-name='name',
data-vv-as='Name',
data-vv-scope='newUser',
:error-messages='errors.collect(`newUser.name`)'
key='newUserName'
persistent-hint
)
v-select(
:items='groups'
item-text='name'
item-value='key'
outline
prepend-icon='people'
outlined
prepend-icon='mdi-account-group'
v-model='group'
label='Assign to Group(s)...'
clearable
@ -63,14 +89,15 @@
)
v-card-chin
v-spacer
v-btn(flat, @click='isShown = false') Cancel
v-btn(color='primary', @click='newUser(true)') Create
v-btn(color='primary', @click='newUser(false)') Create and Close
v-btn(text, @click='isShown = false') Cancel
v-btn(depressed, color='primary', @click='newUser(false)', :disabled='errors.any(`newUser`)') Create
v-btn(depressed, color='primary', @click='newUser(true)', :disabled='errors.any(`newUser`)') Create and Close
</template>
<script>
import uuidv4 from 'uuid/v4'
import _ from 'lodash'
import createUserMutation from 'gql/admin/users/users-mutation-create.gql'
import providersQuery from 'gql/admin/users/users-query-strategies.gql'
import groupsQuery from 'gql/admin/auth/auth-query-groups.gql'
@ -103,18 +130,69 @@ export default {
watch: {
value(newValue, oldValue) {
if (newValue) {
this.$validator.reset()
this.$nextTick(() => {
this.$refs.emailInput.focus()
})
}
},
provider(newValue, oldValue) {
this.$validator.reset()
}
},
methods: {
async newUser() {
this.isShown = false
async newUser(close = false) {
const validationSuccess = await this.$validator.validateAll('newUser')
if (!validationSuccess) {
return
}
try {
const resp = await this.$apollo.mutate({
mutation: createUserMutation,
variables: {
providerKey: this.provider,
email: this.email,
passwordRaw: this.password,
name: this.name,
groups: this.groups,
mustChangePassword: this.mustChangePwd,
sendWelcomeEmail: this.sendWelcomeEmail
},
watchLoading (isLoading) {
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-users-create')
}
})
if (_.get(resp, 'data.users.create.responseResult.succeeded', false)) {
this.$store.commit('showNotification', {
style: 'success',
message: 'New user created successfully.',
icon: 'check'
})
this.email = ''
this.password = ''
this.name = ''
if (close) {
this.isShown = false
} else {
this.$refs.emailInput.focus()
}
} else {
this.$store.commit('showNotification', {
style: 'red',
message: _.get(resp, 'data.users.create.responseResult.message', 'An unexpected error occured.'),
icon: 'warning'
})
}
} catch (err) {
this.$store.commit('pushGraphError', err)
}
},
generatePwd() {
this.password = uuidv4().slice(-12)
const pwdChars = 'abcdefghkmnpqrstuvwxyzABCDEFHJKLMNPQRSTUVWXYZ23456789_*=?#!()+'
this.password = _.sampleSize(pwdChars, 12).join('')
}
},
apollo: {

@ -31,23 +31,23 @@
v-icon.mr-2 directions_run
span Basic Info
v-list.py-0(two-line, dense)
v-list-tile
v-list-tile-avatar
v-list-item
v-list-item-avatar
v-icon alternate_email
v-list-tile-content
v-list-tile-title Email
v-list-tile-sub-title {{ user.email }}
v-list-tile-action(v-if='!user.isSystem')
v-list-item-content
v-list-item-title Email
v-list-item-sub-title {{ user.email }}
v-list-item-action(v-if='!user.isSystem')
v-btn(icon, color='grey', flat)
v-icon edit
v-divider
v-list-tile
v-list-tile-avatar
v-list-item
v-list-item-avatar
v-icon person
v-list-tile-content
v-list-tile-title Display Name
v-list-tile-sub-title {{ user.name }}
v-list-tile-action
v-list-item-content
v-list-item-title Display Name
v-list-item-sub-title {{ user.name }}
v-list-item-action
v-btn(icon, color='grey', flat)
v-icon edit
v-card.mt-3.animated.fadeInUp.wait-p2s(v-if='!user.isSystem')
@ -55,58 +55,58 @@
v-icon.mr-2 lock_outline
span Authentication
v-list.py-0(two-line, dense)
v-list-tile
v-list-tile-avatar
v-list-item
v-list-item-avatar
v-icon business
v-list-tile-content
v-list-tile-title Provider
v-list-tile-sub-title {{ user.providerKey }}
v-list-tile-action
v-list-item-content
v-list-item-title Provider
v-list-item-sub-title {{ user.providerKey }}
v-list-item-action
v-img(src='https://static.requarks.io/logo/wikijs.svg', alt='')
template(v-if='user.providerKey === `local`')
v-divider
v-list-tile
v-list-tile-avatar
v-list-item
v-list-item-avatar
v-icon security
v-list-tile-content
v-list-tile-title Password
v-list-tile-sub-title ********
v-list-tile-action
v-list-item-content
v-list-item-title Password
v-list-item-sub-title ********
v-list-item-action
v-btn(icon, color='grey', flat)
v-icon cached
v-list-tile-action
v-list-item-action
v-btn(icon, color='grey', flat)
v-icon email
v-divider
v-list-tile
v-list-tile-avatar
v-list-item
v-list-item-avatar
v-icon screen_lock_portrait
v-list-tile-content
v-list-tile-title Two Factor Authentication (2FA)
v-list-tile-sub-title.red--text Inactive
v-list-tile-action
v-list-item-content
v-list-item-title Two Factor Authentication (2FA)
v-list-item-sub-title.red--text Inactive
v-list-item-action
v-btn(icon, color='grey', flat)
v-icon power_settings_new
template(v-if='user.providerId')
v-divider
v-list-tile
v-list-tile-avatar
v-list-item
v-list-item-avatar
v-icon person
v-list-tile-content
v-list-tile-title Provider Id
v-list-tile-sub-title {{ user.providerId }}
v-list-item-content
v-list-item-title Provider Id
v-list-item-sub-title {{ user.providerId }}
v-card.mt-3.animated.fadeInUp.wait-p4s
v-toolbar(color='primary', dense, dark, flat)
v-icon.mr-2 people
span User Groups
v-list(dense)
template(v-for='(group, idx) in user.groups')
v-list-tile
v-list-tile-avatar
v-list-item
v-list-item-avatar
v-icon people_outline
v-list-tile-content
v-list-tile-title {{group.name}}
v-list-tile-action
v-list-item-content
v-list-item-title {{group.name}}
v-list-item-action
v-btn(icon, color='red', flat)
v-icon clear
v-divider(v-if='idx < user.groups.length - 1')
@ -121,33 +121,33 @@
v-icon.mr-2 directions_walk
span Extended Metadata
v-list.py-0(two-line, dense)
v-list-tile
v-list-tile-avatar
v-list-item
v-list-item-avatar
v-icon public
v-list-tile-content
v-list-tile-title Location
v-list-tile-sub-title {{ user.location }}
v-list-tile-action
v-list-item-content
v-list-item-title Location
v-list-item-sub-title {{ user.location }}
v-list-item-action
v-btn(icon, color='grey', flat)
v-icon edit
v-divider
v-list-tile
v-list-tile-avatar
v-list-item
v-list-item-avatar
v-icon local_library
v-list-tile-content
v-list-tile-title Job Title
v-list-tile-sub-title {{ user.jobTitle }}
v-list-tile-action
v-list-item-content
v-list-item-title Job Title
v-list-item-sub-title {{ user.jobTitle }}
v-list-item-action
v-btn(icon, color='grey', flat)
v-icon edit
v-divider
v-list-tile
v-list-tile-avatar
v-list-item
v-list-item-avatar
v-icon map
v-list-tile-content
v-list-tile-title Timezone
v-list-tile-sub-title {{ user.timezone }}
v-list-tile-action
v-list-item-content
v-list-item-title Timezone
v-list-item-sub-title {{ user.timezone }}
v-list-item-action
v-btn(icon, color='grey', flat)
v-icon edit
v-card.mt-3.animated.fadeInUp.wait-p4s

@ -6,25 +6,25 @@
img.animated.fadeInUp(src='/svg/icon-customer.svg', alt='Users', style='width: 80px;')
.admin-header-title
.headline.blue--text.text--darken-2.animated.fadeInLeft Users
.subheading.grey--text.animated.fadeInLeft.wait-p2s Manage users #[v-chip(label, color='primary', small).white--text coming soon]
.subheading.grey--text.animated.fadeInLeft.wait-p2s Manage users
v-spacer
v-btn.animated.fadeInDown.wait-p2s(outline, color='grey', large, @click='refresh')
v-icon refresh
v-btn.animated.fadeInDown(color='primary', large, depressed, @click='createUser', disabled)
v-icon(left) add
v-btn.animated.fadeInDown.wait-p2s.mr-3(outlined, color='grey', large, @click='refresh')
v-icon mdi-refresh
v-btn.animated.fadeInDown(color='primary', large, depressed, @click='createUser')
v-icon(left) mdi-plus
span New User
v-card.wiki-form.mt-3.animated.fadeInUp
v-toolbar(flat, :color='$vuetify.dark ? `grey darken-3-d5` : `grey lighten-5`', height='80')
v-spacer
v-text-field(
outline
outlined
v-model='search'
prepend-inner-icon='search'
prepend-inner-icon='mdi-account-search-outline'
label='Search Users...'
hide-details
)
v-select.ml-2(
outline
outlined
hide-details
label='Identity Provider'
:items='strategies'

@ -9,7 +9,7 @@
v-toolbar.radius-7.mt-3.wiki-form(flat, color='grey lighten-4', height='80')
v-select(
label='Source Locale'
outline
outlined
hide-details
:items='locales'
item-text='name'
@ -19,7 +19,7 @@
v-icon.mx-3(large) arrow_forward
v-select(
label='Target Locale'
outline
outlined
hide-details
:items='locales'
item-text='name'

@ -11,40 +11,40 @@
v-subheader What is collected?
.body-1.pl-3 When telemetry is enabled, only the following data is transmitted:
v-list
v-list-tile
v-list-tile-avatar: v-icon info_outline
v-list-tile-content
v-list-tile-title.body-1 Version of Wiki.js installed
v-list-tile-sub-title.caption: em e.g. v2.0.123
v-list-tile
v-list-tile-avatar: v-icon info_outline
v-list-tile-content
v-list-tile-title.body-1 Basic OS information
v-list-tile-sub-title.caption: em Platform (Linux, macOS or Windows), Total CPU cores and DB type (PostgreSQL, MySQL, MariaDB, SQLite or SQL Server)
v-list-tile
v-list-tile-avatar: v-icon info_outline
v-list-tile-content
v-list-tile-title.body-1 Crash debug data
v-list-tile-sub-title.caption: em Stack trace of the error
v-list-tile
v-list-tile-avatar: v-icon info_outline
v-list-tile-content
v-list-tile-title.body-1 Setup analytics
v-list-tile-sub-title.caption: em Installation checkpoint reached
v-list-item
v-list-item-avatar: v-icon info_outline
v-list-item-content
v-list-item-title.body-1 Version of Wiki.js installed
v-list-item-sub-title.caption: em e.g. v2.0.123
v-list-item
v-list-item-avatar: v-icon info_outline
v-list-item-content
v-list-item-title.body-1 Basic OS information
v-list-item-sub-title.caption: em Platform (Linux, macOS or Windows), Total CPU cores and DB type (PostgreSQL, MySQL, MariaDB, SQLite or SQL Server)
v-list-item
v-list-item-avatar: v-icon info_outline
v-list-item-content
v-list-item-title.body-1 Crash debug data
v-list-item-sub-title.caption: em Stack trace of the error
v-list-item
v-list-item-avatar: v-icon info_outline
v-list-item-content
v-list-item-title.body-1 Setup analytics
v-list-item-sub-title.caption: em Installation checkpoint reached
.body-1.pl-3 Note that crash debug data is stored for a maximum of 30 days while analytics are stored for a maximum of 16 months, after which it is permanently deleted.
v-divider.my-3
v-subheader What is it used for?
.body-1.pl-3 Telemetry is used by developers to improve Wiki.js, mostly for the following reasons:
v-list(dense)
v-list-tile
v-list-tile-avatar: v-icon chevron_right
v-list-tile-content: v-list-tile-title.body-1 Identify critical bugs more easily and fix them in a timely manner.
v-list-tile
v-list-tile-avatar: v-icon chevron_right
v-list-tile-content: v-list-tile-title.body-1 Understand the upgrade rate of current installations.
v-list-tile
v-list-tile-avatar: v-icon chevron_right
v-list-tile-content: v-list-tile-title.body-1 Optimize performance and testing scenarios based on most popular environments.
v-list-item
v-list-item-avatar: v-icon chevron_right
v-list-item-content: v-list-item-title.body-1 Identify critical bugs more easily and fix them in a timely manner.
v-list-item
v-list-item-avatar: v-icon chevron_right
v-list-item-content: v-list-item-title.body-1 Understand the upgrade rate of current installations.
v-list-item
v-list-item-avatar: v-icon chevron_right
v-list-item-content: v-list-item-title.body-1 Optimize performance and testing scenarios based on most popular environments.
.body-1.pl-3 Only authorized developers have access to the data. It is not shared to any 3rd party nor is it used for any other application than improving Wiki.js.
v-divider.my-3
v-subheader Settings

@ -14,13 +14,13 @@
.subheading {{$t('admin:utilities.tools')}}
v-list(two-line, dense).py-0
template(v-for='(tool, idx) in tools')
v-list-tile(:key='tool.key', @click='selectedTool = tool.key', :disabled='!tool.isAvailable')
v-list-tile-avatar
v-list-item(:key='tool.key', @click='selectedTool = tool.key', :disabled='!tool.isAvailable')
v-list-item-avatar
v-icon(:color='!tool.isAvailable ? `grey lighten-1` : (selectedTool === tool.key ? `blue ` : `grey darken-1`)') {{ tool.icon }}
v-list-tile-content
v-list-tile-title.body-2(:class='!tool.isAvailable ? `grey--text` : (selectedTool === tool.key ? `primary--text` : ``)') {{ $t('admin:utilities.' + tool.i18nKey + 'Title') }}
v-list-tile-sub-title.caption(:class='!tool.isAvailable ? `grey--text text--lighten-1` : (selectedTool === tool.key ? `blue--text ` : ``)') {{ $t('admin:utilities.' + tool.i18nKey + 'Subtitle') }}
v-list-tile-avatar(v-if='selectedTool === tool.key')
v-list-item-content
v-list-item-title.body-2(:class='!tool.isAvailable ? `grey--text` : (selectedTool === tool.key ? `primary--text` : ``)') {{ $t('admin:utilities.' + tool.i18nKey + 'Title') }}
v-list-item-sub-title.caption(:class='!tool.isAvailable ? `grey--text text--lighten-1` : (selectedTool === tool.key ? `blue--text ` : ``)') {{ $t('admin:utilities.' + tool.i18nKey + 'Subtitle') }}
v-list-item-avatar(v-if='selectedTool === tool.key')
v-icon.animated.fadeInLeft(color='primary') arrow_forward_ios
v-divider(v-if='idx < tools.length - 1')

@ -22,14 +22,14 @@
span New
v-list(two-line, dense).py-0
template(v-for='(str, idx) in hooks')
v-list-tile(:key='str.key', @click='selectedHook = str.key')
v-list-tile-avatar
v-list-item(:key='str.key', @click='selectedHook = str.key')
v-list-item-avatar
v-icon(color='primary', v-if='str.isEnabled', v-ripple, @click='str.isEnabled = false') check_box
v-icon(color='grey', v-else, v-ripple, @click='str.isEnabled = true') check_box_outline_blank
v-list-tile-content
v-list-tile-title.body-2(:class='!str.isAvailable ? `grey--text` : (selectedHook === str.key ? `primary--text` : ``)') {{ str.title }}
v-list-tile-sub-title.caption(:class='!str.isAvailable ? `grey--text text--lighten-1` : (selectedHook === str.key ? `blue--text ` : ``)') {{ str.description }}
v-list-tile-avatar(v-if='selectedHook === str.key')
v-list-item-content
v-list-item-title.body-2(:class='!str.isAvailable ? `grey--text` : (selectedHook === str.key ? `primary--text` : ``)') {{ str.title }}
v-list-item-sub-title.caption(:class='!str.isAvailable ? `grey--text text--lighten-1` : (selectedHook === str.key ? `blue--text ` : ``)') {{ str.description }}
v-list-item-avatar(v-if='selectedHook === str.key')
v-icon.animated.fadeInLeft(color='primary') arrow_forward_ios
v-divider(v-if='idx < hooks.length - 1')

@ -1,5 +1,5 @@
<template lang='pug'>
v-toolbar.nav-header(color='black', dark, app, clipped-left, fixed, flat, :extended='searchIsShown && $vuetify.breakpoint.smAndDown')
v-app-bar.nav-header(color='black', dark, app, clipped-left, fixed, flat, :extended='searchIsShown && $vuetify.breakpoint.smAndDown')
v-toolbar(color='deep-purple', flat, slot='extension', v-if='searchIsShown && $vuetify.breakpoint.smAndDown')
v-text-field(
ref='searchFieldMobile'
@ -12,49 +12,50 @@
solo
flat
hide-details
prepend-inner-icon='search'
prepend-inner-icon='mdi-search'
:loading='searchIsLoading'
@keyup.enter='searchEnter'
)
v-layout(row)
v-flex(xs6, :md4='searchIsShown', :md6='!searchIsShown')
v-toolbar.nav-header-inner(color='black', dark, flat)
v-flex(xs6, md4)
v-toolbar.nav-header-inner.pl-3(color='black', dark, flat)
v-menu(open-on-hover, offset-y, bottom, left, min-width='250', transition='slide-y-transition')
v-toolbar-side-icon.btn-animate-app(slot='activator')
v-icon view_module
v-list(dense, :light='!$vuetify.dark', :dark='$vuetify.dark', :class='$vuetify.dark ? `grey darken-4` : ``').py-0
v-list-tile(avatar, href='/')
v-list-tile-avatar: v-icon(color='blue') home
v-list-tile-content {{$t('common:header.home')}}
v-list-tile(avatar, @click='pageNew', v-if='isAuthenticated')
v-list-tile-avatar: v-icon(color='green') add_box
v-list-tile-content {{$t('common:header.newPage')}}
template(v-slot:activator='{ on }')
v-app-bar-nav-icon.btn-animate-app(v-on='on')
v-icon mdi-menu-open
v-list(nav, :light='!$vuetify.dark', :dark='$vuetify.dark', :class='$vuetify.dark ? `grey darken-4` : ``')
v-list-item.pl-4(href='/')
v-list-item-avatar(size='24'): v-icon(color='blue') mdi-home
v-list-item-title.body-2 {{$t('common:header.home')}}
v-list-item.pl-4(@click='pageNew', v-if='isAuthenticated')
v-list-item-avatar(size='24'): v-icon(color='green') mdi-file-document-box-plus-outline
v-list-item-title.body-2 {{$t('common:header.newPage')}}
template(v-if='path && path.length')
v-divider.my-0
v-subheader {{$t('common:header.currentPage')}}
v-list-tile(avatar, @click='pageView', v-if='mode !== `view`')
v-list-tile-avatar: v-icon(color='indigo') subject
v-list-tile-content {{$t('common:header.view')}}
v-list-tile(avatar, @click='pageEdit', v-if='mode !== `edit` && isAuthenticated')
v-list-tile-avatar: v-icon(color='indigo') edit
v-list-tile-content {{$t('common:header.edit')}}
v-list-tile(avatar, @click='pageHistory', v-if='mode !== `history`')
v-list-tile-avatar: v-icon(color='indigo') history
v-list-tile-content {{$t('common:header.history')}}
v-list-tile(avatar, @click='pageSource', v-if='mode !== `source`')
v-list-tile-avatar: v-icon(color='indigo') code
v-list-tile-content {{$t('common:header.viewSource')}}
v-list-tile(avatar, @click='pageMove', v-if='isAuthenticated')
v-list-tile-avatar: v-icon(color='grey lighten-2') forward
v-list-tile-content.grey--text.text--ligten-2 {{$t('common:header.move')}}
v-list-tile(avatar, @click='pageDelete', v-if='isAuthenticated')
v-list-tile-avatar: v-icon(color='red darken-2') delete
v-list-tile-content {{$t('common:header.delete')}}
v-list-item.pl-4(@click='pageView', v-if='mode !== `view`')
v-list-item-avatar(size='24'): v-icon(color='indigo') subject
v-list-item-title.body-2 {{$t('common:header.view')}}
v-list-item.pl-4(@click='pageEdit', v-if='mode !== `edit` && isAuthenticated')
v-list-item-avatar(size='24'): v-icon(color='indigo') mdi-file-document-edit-outline
v-list-item-title.body-2 {{$t('common:header.edit')}}
v-list-item.pl-4(@click='pageHistory', v-if='mode !== `history`')
v-list-item-avatar(size='24'): v-icon(color='indigo') mdi-history
v-list-item-title.body-2 {{$t('common:header.history')}}
v-list-item.pl-4(@click='pageSource', v-if='mode !== `source`')
v-list-item-avatar(size='24'): v-icon(color='indigo') mdi-code-braces
v-list-item-title.body-2 {{$t('common:header.viewSource')}}
v-list-item.pl-4(@click='pageMove', v-if='isAuthenticated')
v-list-item-avatar(size='24'): v-icon(color='grey lighten-2') mdi-content-save-move-outline
v-list-item-title.body-2.grey--text.text--ligten-2 {{$t('common:header.move')}}
v-list-item.pl-4(@click='pageDelete', v-if='isAuthenticated')
v-list-item-avatar(size='24'): v-icon(color='red darken-2') mdi-trash-can-outline
v-list-item-title.body-2 {{$t('common:header.delete')}}
v-divider.my-0
v-subheader {{$t('common:header.assets')}}
v-list-tile(avatar, @click='assets')
v-list-tile-avatar: v-icon(color='grey lighten-2') burst_mode
v-list-tile-content.grey--text.text--ligten-2 {{$t('common:header.imagesFiles')}}
v-list-item.pl-4(@click='assets')
v-list-item-avatar(size='24'): v-icon(color='grey lighten-2') mdi-folder-multiple-image
v-list-item-title.body-2.grey--text.text--ligten-2 {{$t('common:header.imagesFiles')}}
v-toolbar-title(:class='{ "ml-2": $vuetify.breakpoint.mdAndUp, "ml-0": $vuetify.breakpoint.smAndDown }')
span.subheading {{title}}
v-flex(md4, v-if='$vuetify.breakpoint.mdAndUp')
@ -71,7 +72,7 @@
solo
flat
hide-details,
prepend-inner-icon='search',
prepend-inner-icon='mdi-magnify',
:loading='searchIsLoading',
@keyup.enter='searchEnter'
@keyup.esc='searchClose'
@ -80,12 +81,6 @@
@keyup.down='searchMove(`down`)'
@keyup.up='searchMove(`up`)'
)
v-progress-linear(
indeterminate,
slot='progress',
height='2',
color='blue'
)
v-menu(
v-model='searchAdvMenuShown'
left
@ -96,11 +91,12 @@
nudge-right='5'
v-if='searchIsShown'
)
v-btn.nav-header-search-adv(icon, outline, color='grey darken-2', slot='activator')
v-icon(color='white') expand_more
template(v-slot:activator='{ on }')
v-btn.nav-header-search-adv(icon, color='grey darken-2', v-on='on')
v-icon(color='white') mdi-chevron-down
v-card.radius-0(dark)
v-toolbar(flat, color='grey darken-4', dense)
v-icon.mr-2 search
v-icon.mr-2 mdi-feature-search-outline
v-subheader.pl-0 Advanced Search
v-spacer
v-chip(label, small, color='primary') Coming soon
@ -119,14 +115,18 @@
)
v-divider
v-card-actions.grey.darken-3-d4
v-btn(depressed, color='grey darken-3', block)
v-icon(left) chevron_right
span Save as defaults
v-btn(depressed, color='grey darken-3', block)
v-icon(left) cached
span Reset
v-flex(xs6, :md4='searchIsShown', :md6='!searchIsShown')
v-toolbar.nav-header-inner(color='black', dark, flat)
v-container.pa-0(grid-list-md)
v-layout(row)
v-flex(xs6)
v-btn(depressed, color='grey darken-3', block)
v-icon(left) mdi-chevron-right
span Save as defaults
v-flex(xs6)
v-btn(depressed, color='grey darken-3', block)
v-icon(left) mdi-cached
span Reset
v-flex(xs6, md4)
v-toolbar.nav-header-inner.pr-4(color='black', dark, flat)
v-spacer
.navHeaderLoading.mr-3
v-progress-circular(indeterminate, color='blue', :size='22', :width='2' v-show='isLoading')
@ -138,53 +138,59 @@
)
v-icon(color='grey') search
v-menu(offset-y, left, transition='slide-y-transition', v-if='mode === `view` && locales.length > 0')
v-tooltip(bottom, slot='activator')
v-btn(icon, slot='activator')
v-icon(color='grey') language
span {{$t('common:header.language')}}
template(v-slot:activator='{ on: menu }')
v-tooltip(bottom)
template(v-slot:activator='{ on: tooltip }')
v-btn(icon, v-on='{ ...menu, ...tooltip }')
v-icon(color='grey') mdi-web
span {{$t('common:header.language')}}
v-list.py-0
template(v-for='(lc, idx) of locales')
v-list-tile(@click='changeLocale(lc)')
v-list-tile-action: v-chip(:color='lc.code === locale ? `blue` : `grey`', small, label, dark) {{lc.code.toUpperCase()}}
v-list-tile-title {{lc.name}}
v-list-item(@click='changeLocale(lc)')
v-list-item-action: v-chip(:color='lc.code === locale ? `blue` : `grey`', small, label, dark) {{lc.code.toUpperCase()}}
v-list-item-title {{lc.name}}
v-divider.my-0(v-if='idx < locales.length - 1')
v-tooltip(bottom, v-if='isAuthenticated && isAdmin')
v-btn.btn-animate-rotate(icon, href='/a', slot='activator')
v-icon(color='grey') settings
template(v-slot:activator='{ on }')
v-btn.btn-animate-rotate(icon, href='/a', v-on='on')
v-icon(color='grey') mdi-settings
span {{$t('common:header.admin')}}
v-menu(v-if='isAuthenticated', offset-y, min-width='300', left, transition='slide-y-transition')
v-tooltip(bottom, slot='activator')
v-btn(icon, slot='activator', outline, color='blue')
v-icon(v-if='picture.kind === `initials`', color='grey') account_circle
v-avatar(v-else-if='picture.kind === `image`', :size='29')
v-img(:src='picture.url')
span {{$t('common:header.account')}}
template(v-slot:activator='{ on: menu }')
v-tooltip(bottom)
template(v-slot:activator='{ on: tooltip }')
v-btn(icon, v-on='{ ...menu, ...tooltip }', outlined, color='blue')
v-icon(v-if='picture.kind === `initials`', color='grey') mdi-account-circle
v-avatar(v-else-if='picture.kind === `image`', :size='29')
v-img(:src='picture.url')
span {{$t('common:header.account')}}
v-list.py-0
v-list-tile.py-3.grey(avatar, :class='$vuetify.dark ? `darken-4-l5` : `lighten-5`')
v-list-tile-avatar
v-list-item.py-3.grey(avatar, :class='$vuetify.dark ? `darken-4-l5` : `lighten-5`')
v-list-item-avatar
v-avatar.blue(v-if='picture.kind === `initials`', :size='40')
span.white--text.subheading {{picture.initials}}
v-avatar(v-else-if='picture.kind === `image`', :size='40')
v-img(:src='picture.url')
v-list-tile-content
v-list-tile-title {{name}}
v-list-tile-sub-title {{email}}
v-list-item-content
v-list-item-title {{name}}
v-list-item-sub-title {{email}}
v-divider.my-0
v-list-tile(href='/w', disabled)
v-list-tile-action: v-icon(color='blue') web
v-list-tile-title {{$t('common:header.myWiki')}}
v-list-item(href='/w', disabled)
v-list-item-action: v-icon(color='blue') mdi-view-compact-outline
v-list-item-title {{$t('common:header.myWiki')}}
v-divider.my-0
v-list-tile(href='/p', disabled)
v-list-tile-action: v-icon(color='blue') person
v-list-tile-title {{$t('common:header.profile')}}
v-list-item(href='/p', disabled)
v-list-item-action: v-icon(color='blue') mdi-face-profile
v-list-item-title {{$t('common:header.profile')}}
v-divider.my-0
v-list-tile(@click='logout')
v-list-tile-action: v-icon(color='red') exit_to_app
v-list-tile-title {{$t('common:header.logout')}}
v-list-item(@click='logout')
v-list-item-action: v-icon(color='red') mdi-logout
v-list-item-title {{$t('common:header.logout')}}
v-tooltip(v-else, left)
v-btn(icon, slot='activator', outline, color='grey darken-3', href='/login')
v-icon(color='grey') account_circle
template(v-slot:activator='{ on }')
v-btn(icon, v-on='on', outline, color='grey darken-3', href='/login')
v-icon(color='grey') mdi-account-circle
span {{$t('common:header.login')}}
page-selector(mode='create', v-model='newPageModal', :open-handler='pageNewCreate')

@ -3,11 +3,10 @@
:color='notification.style'
top
multi-line
auto-height
v-model='notificationState'
)
.text-xs-left
v-icon.mr-3(dark) {{ notification.icon }}
.text-left
v-icon.mr-3(dark) mdi-{{ notification.icon }}
span {{ notification.message }}
</template>

@ -1,5 +1,5 @@
<template lang="pug">
v-dialog(v-model='isShown', lazy, max-width='850px')
v-dialog(v-model='isShown', max-width='850px')
v-card.page-selector
.dialog-header.is-dark
v-icon.mr-2(color='white') find_in_page
@ -35,21 +35,21 @@
//- v-btn(icon): v-icon forward
//- v-btn(icon): v-icon delete
//- v-list(dense)
//- v-list-tile
//- v-list-tile-avatar: v-icon insert_drive_file
//- v-list-tile-title File A
//- v-list-item
//- v-list-item-avatar: v-icon insert_drive_file
//- v-list-item-title File A
//- v-divider
//- v-list-tile
//- v-list-tile-avatar: v-icon insert_drive_file
//- v-list-tile-title File B
//- v-list-item
//- v-list-item-avatar: v-icon insert_drive_file
//- v-list-item-title File B
//- v-divider
//- v-list-tile
//- v-list-tile-avatar: v-icon insert_drive_file
//- v-list-tile-title File C
//- v-list-item
//- v-list-item-avatar: v-icon insert_drive_file
//- v-list-item-title File C
//- v-divider
//- v-list-tile
//- v-list-tile-avatar: v-icon insert_drive_file
//- v-list-tile-title File D
//- v-list-item
//- v-list-item-avatar: v-icon insert_drive_file
//- v-list-item-title File D
v-card-actions.grey.pa-2(:class='darkMode ? `darken-3-d5` : `lighten-1`')
v-select(
solo

@ -16,17 +16,17 @@
.subheading {{$t('common:header.searchNoResult')}}
template(v-if='results.length > 0')
v-subheader.white--text {{$t('common:header.searchResultsCount', { total: response.totalHits })}}
v-list.search-results-items.radius-7(two-line)
v-list.search-results-items.radius-7.py-0(two-line)
template(v-for='(item, idx) of results')
v-list-tile(@click='goToPage(item)', :key='item.id', :class='idx === cursor ? `highlighted` : ``')
v-list-tile-avatar(tile)
v-list-item(@click='goToPage(item)', :key='item.id', :class='idx === cursor ? `highlighted` : ``')
v-list-item-avatar(tile)
img(src='/svg/icon-selective-highlighting.svg')
v-list-tile-content
v-list-tile-title(v-html='item.title')
v-list-tile-sub-title(v-html='item.description')
.caption.grey--text.mt-1(v-html='item.path')
v-list-tile-action
v-chip(label) {{item.locale.toUpperCase()}}
v-list-item-content
v-list-item-title(v-html='item.title')
v-list-item-subtitle(v-html='item.description')
.caption.grey--text(v-html='item.path')
v-list-item-action
v-chip(label, outlined) {{item.locale.toUpperCase()}}
v-divider(v-if='idx < results.length - 1')
v-pagination.mt-3(
v-if='paginationLength > 1'
@ -38,18 +38,18 @@
v-subheader.white--text.mt-3 {{$t('common:header.searchDidYouMean')}}
v-list.search-results-suggestions.radius-7(dense, dark)
template(v-for='(term, idx) of suggestions')
v-list-tile(:key='term', @click='setSearchTerm(term)', :class='idx + results.length === cursor ? `highlighted` : ``')
v-list-tile-avatar
v-icon search
v-list-tile-content
v-list-tile-title(v-html='term')
v-list-item(:key='term', @click='setSearchTerm(term)', :class='idx + results.length === cursor ? `highlighted` : ``')
v-list-item-avatar
v-icon mdi-magnify
v-list-item-content
v-list-item-title(v-html='term')
v-divider(v-if='idx < suggestions.length - 1')
.text-xs-center.pt-5(v-if='search.length > 1')
v-btn(outline, color='orange', @click='search = ``', v-if='results.length > 0')
v-icon(left) save
v-btn.mx-2(outlined, color='orange', @click='search = ``', v-if='results.length > 0')
v-icon(left) mdi-content-save
span {{$t('common:header.searchCopyLink')}}
v-btn(outline, color='pink', @click='search = ``')
v-icon(left) clear
v-btn.mx-2(outlined, color='pink', @click='search = ``')
v-icon(left) mdi-close
span {{$t('common:header.searchClose')}}
</template>
@ -205,6 +205,8 @@ export default {
}
&-items {
text-align: left;
.highlighted {
background: #FFF linear-gradient(to bottom, #FFF, mc('orange', '100'));
}

@ -30,13 +30,13 @@
dense
)
template(v-for='(usr, idx) in items')
v-list-tile(:key='usr.id', @click='setUser(usr.id)')
v-list-tile-avatar(size='40', color='primary')
v-list-item(:key='usr.id', @click='setUser(usr.id)')
v-list-item-avatar(size='40', color='primary')
span.body-1.white--text {{usr.name | initials}}
v-list-tile-content
v-list-tile-title.body-2 {{usr.name}}
v-list-tile-sub-title {{usr.email}}
v-list-tile-action
v-list-item-content
v-list-item-title.body-2 {{usr.name}}
v-list-item-sub-title {{usr.email}}
v-list-item-action
v-icon(color='primary') arrow_forward
v-divider.my-0(v-if='idx < items.length - 1')
v-card-chin

@ -24,10 +24,10 @@
v-icon text_fields
v-list.py-0
template(v-for='(n, idx) in 6')
v-list-tile(@click='setHeaderLine(n)', :key='idx')
v-list-tile-action
v-list-item(@click='setHeaderLine(n)', :key='idx')
v-list-item-action
v-icon(:size='24 - (idx - 1) * 2') title
v-list-tile-title {{$t('editor:markup.heading', { level: n })}}
v-list-item-title {{$t('editor:markup.heading', { level: n })}}
v-divider(v-if='idx < 5')
v-tooltip(bottom, color='primary')
v-btn.animated.fadeIn.wait-p4s(icon, slot='activator', @click='toggleMarkup({ start: `~` })').mx-0
@ -41,30 +41,30 @@
v-btn.animated.fadeIn.wait-p6s(icon, slot='activator').mx-0
v-icon format_quote
v-list.py-0
v-list-tile(@click='insertBeforeEachLine({ content: `> `})')
v-list-tile-action
v-list-item(@click='insertBeforeEachLine({ content: `> `})')
v-list-item-action
v-icon format_quote
v-list-tile-title {{$t('editor:markup.blockquote')}}
v-list-item-title {{$t('editor:markup.blockquote')}}
v-divider
v-list-tile(@click='insertBeforeEachLine({ content: `> `, after: `{.is-info}`})')
v-list-tile-action
v-list-item(@click='insertBeforeEachLine({ content: `> `, after: `{.is-info}`})')
v-list-item-action
v-icon(color='blue') format_quote
v-list-tile-title {{$t('editor:markup.blockquoteInfo')}}
v-list-item-title {{$t('editor:markup.blockquoteInfo')}}
v-divider
v-list-tile(@click='insertBeforeEachLine({ content: `> `, after: `{.is-success}`})')
v-list-tile-action
v-list-item(@click='insertBeforeEachLine({ content: `> `, after: `{.is-success}`})')
v-list-item-action
v-icon(color='success') format_quote
v-list-tile-title {{$t('editor:markup.blockquoteSuccess')}}
v-list-item-title {{$t('editor:markup.blockquoteSuccess')}}
v-divider
v-list-tile(@click='insertBeforeEachLine({ content: `> `, after: `{.is-warning}`})')
v-list-tile-action
v-list-item(@click='insertBeforeEachLine({ content: `> `, after: `{.is-warning}`})')
v-list-item-action
v-icon(color='warning') format_quote
v-list-tile-title {{$t('editor:markup.blockquoteWarning')}}
v-list-item-title {{$t('editor:markup.blockquoteWarning')}}
v-divider
v-list-tile(@click='insertBeforeEachLine({ content: `> `, after: `{.is-danger}`})')
v-list-tile-action
v-list-item(@click='insertBeforeEachLine({ content: `> `, after: `{.is-danger}`})')
v-list-item-action
v-icon(color='error') format_quote
v-list-tile-title {{$t('editor:markup.blockquoteError')}}
v-list-item-title {{$t('editor:markup.blockquoteError')}}
v-divider
v-tooltip(bottom, color='primary')
v-btn.animated.fadeIn.wait-p7s(icon, slot='activator', @click='insertBeforeEachLine({ content: `- `})').mx-0

@ -10,14 +10,14 @@
.body-2.teal--text Blocks
v-list(two-line)
template(v-for='(item, idx) of blocks')
v-list-tile(@click='selectBlock(item)')
v-list-tile-avatar
v-list-item(@click='selectBlock(item)')
v-list-item-avatar
v-avatar.radius-7(color='teal')
v-icon(dark) dashboard
v-list-tile-content
v-list-tile-title.body-2 {{item.title}}
v-list-tile-sub-title {{item.description}}
v-list-tile-avatar(v-if='block.key === item.key')
v-list-item-content
v-list-item-title.body-2 {{item.title}}
v-list-item-sub-title {{item.description}}
v-list-item-avatar(v-if='block.key === item.key')
v-icon.animated.fadeInLeft(color='teal') arrow_forward_ios
v-divider(v-if='idx < blocks.length - 1')

@ -79,41 +79,41 @@
v-btn.ma-0(icon, slot='activator')
v-icon(color='grey darken-2') more_horiz
v-list.py-0(style='border-top: 5px solid #444;')
v-list-tile(@click='', disabled)
v-list-tile-avatar
v-list-item(@click='', disabled)
v-list-item-avatar
v-icon(color='teal') short_text
v-list-tile-content {{$t('common:actions.properties')}}
v-list-item-content {{$t('common:actions.properties')}}
v-divider
template(v-if='props.item.kind === `IMAGE`')
v-list-tile(@click='previewDialog = true', disabled)
v-list-tile-avatar
v-list-item(@click='previewDialog = true', disabled)
v-list-item-avatar
v-icon(color='green') image_search
v-list-tile-content {{$t('common:actions.preview')}}
v-list-item-content {{$t('common:actions.preview')}}
v-divider
v-list-tile(@click='', disabled)
v-list-tile-avatar
v-list-item(@click='', disabled)
v-list-item-avatar
v-icon(color='indigo') crop_rotate
v-list-tile-content {{$t('common:actions.edit')}}
v-list-item-content {{$t('common:actions.edit')}}
v-divider
v-list-tile(@click='', disabled)
v-list-tile-avatar
v-list-item(@click='', disabled)
v-list-item-avatar
v-icon(color='purple') offline_bolt
v-list-tile-content {{$t('common:actions.optimize')}}
v-list-item-content {{$t('common:actions.optimize')}}
v-divider
v-list-tile(@click='openRenameDialog')
v-list-tile-avatar
v-list-item(@click='openRenameDialog')
v-list-item-avatar
v-icon(color='orange') keyboard
v-list-tile-content {{$t('common:actions.rename')}}
v-list-item-content {{$t('common:actions.rename')}}
v-divider
v-list-tile(@click='', disabled)
v-list-tile-avatar
v-list-item(@click='', disabled)
v-list-item-avatar
v-icon(color='blue') forward
v-list-tile-content {{$t('common:actions.move')}}
v-list-item-content {{$t('common:actions.move')}}
v-divider
v-list-tile(@click='deleteDialog = true')
v-list-tile-avatar
v-list-item(@click='deleteDialog = true')
v-list-item-avatar
v-icon(color='red') delete
v-list-tile-content {{$t('common:actions.delete')}}
v-list-item-content {{$t('common:actions.delete')}}
template(slot='no-data')
v-alert.mt-3.radius-7(icon='folder_open', :value='true', outline, color='teal') {{$t('editor:assets.folderEmpty')}}
.text-xs-center.py-2(v-if='this.pageTotal > 1')

@ -224,39 +224,39 @@
v-icon.mr-3(color='teal') keyboard
.body-2.teal--text Keyboard Shortcuts
v-list.editor-markdown-help-kbd(two-line, dense)
v-list-tile
v-list-tile-content.body-2 Bold
v-list-tile-action #[kbd {{ctrlKey}}] + #[kbd B]
v-list-item
v-list-item-content.body-2 Bold
v-list-item-action #[kbd {{ctrlKey}}] + #[kbd B]
v-divider
v-list-tile
v-list-tile-content.body-2 Italic
v-list-tile-action #[kbd {{ctrlKey}}] + #[kbd I]
v-list-item
v-list-item-content.body-2 Italic
v-list-item-action #[kbd {{ctrlKey}}] + #[kbd I]
v-divider
v-list-tile
v-list-tile-content.body-2 Increase Header Level
v-list-tile-action #[kbd {{ctrlKey}}] + #[kbd {{altKey}}] + #[kbd Right]
v-list-item
v-list-item-content.body-2 Increase Header Level
v-list-item-action #[kbd {{ctrlKey}}] + #[kbd {{altKey}}] + #[kbd Right]
v-divider
v-list-tile
v-list-tile-content.body-2 Decrease Header Level
v-list-tile-action #[kbd {{ctrlKey}}] + #[kbd {{altKey}}] + #[kbd Left]
v-list-item
v-list-item-content.body-2 Decrease Header Level
v-list-item-action #[kbd {{ctrlKey}}] + #[kbd {{altKey}}] + #[kbd Left]
v-divider
v-list-tile
v-list-tile-content.body-2 Save
v-list-tile-action #[kbd {{ctrlKey}}] + #[kbd S]
v-list-item
v-list-item-content.body-2 Save
v-list-item-action #[kbd {{ctrlKey}}] + #[kbd S]
v-divider
v-list-tile
v-list-tile-content.body-2 Undo
v-list-tile-action #[kbd {{ctrlKey}}] + #[kbd Z]
v-list-item
v-list-item-content.body-2 Undo
v-list-item-action #[kbd {{ctrlKey}}] + #[kbd Z]
v-divider
v-list-tile
v-list-tile-content.body-2 Redo
v-list-tile-action #[kbd {{ctrlKey}}] + #[kbd Y]
v-list-item
v-list-item-content.body-2 Redo
v-list-item-action #[kbd {{ctrlKey}}] + #[kbd Y]
v-divider
v-list-tile
v-list-tile-content
v-list-tile-title.body-2 Distraction Free Mode
v-list-tile-sub-title Press <kbd>Esc</kbd> to exit.
v-list-tile-action #[kbd F11]
v-list-item
v-list-item-content
v-list-item-title.body-2 Distraction Free Mode
v-list-item-sub-title Press <kbd>Esc</kbd> to exit.
v-list-item-action #[kbd F11]
v-card.radius-7.animated.fadeInUp.wait-p3s.mt-3(light)
v-card-text
@ -264,17 +264,17 @@
v-icon.mr-3(color='teal') mouse
.body-2.teal--text Multi-Selection
v-list.editor-markdown-help-kbd(two-line, dense)
v-list-tile
v-list-tile-content.body-2 Multiple Cursors
v-list-tile-action #[kbd {{ctrlKey}}] + Left Click
v-list-item
v-list-item-content.body-2 Multiple Cursors
v-list-item-action #[kbd {{ctrlKey}}] + Left Click
v-divider
v-list-tile
v-list-tile-content.body-2 Select Region
v-list-tile-action #[kbd {{ctrlKey}}] + #[kbd {{altKey}}] + Left Click
v-list-item
v-list-item-content.body-2 Select Region
v-list-item-action #[kbd {{ctrlKey}}] + #[kbd {{altKey}}] + Left Click
v-divider
v-list-tile
v-list-tile-content.body-2 Deselect
v-list-tile-action #[kbd Esc]
v-list-item
v-list-item-content.body-2 Deselect
v-list-item-action #[kbd Esc]
</template>
<script>

@ -53,29 +53,29 @@
v-menu(offset-x, left)
v-btn(icon, slot='activator'): v-icon more_horiz
v-list(dense).history-promptmenu
v-list-tile(@click='setDiffTarget(ph.versionId)')
v-list-tile-avatar: v-icon call_made
v-list-tile-title Set as Differencing Target
v-list-item(@click='setDiffTarget(ph.versionId)')
v-list-item-avatar: v-icon call_made
v-list-item-title Set as Differencing Target
v-divider
v-list-tile(@click='setDiffSource(ph.versionId)')
v-list-tile-avatar: v-icon call_received
v-list-tile-title Set as Differencing Source
v-list-item(@click='setDiffSource(ph.versionId)')
v-list-item-avatar: v-icon call_received
v-list-item-title Set as Differencing Source
v-divider
v-list-tile
v-list-tile-avatar: v-icon code
v-list-tile-title View Source
v-list-item
v-list-item-avatar: v-icon code
v-list-item-title View Source
v-divider
v-list-tile
v-list-tile-avatar: v-icon cloud_download
v-list-tile-title Download Version
v-list-item
v-list-item-avatar: v-icon cloud_download
v-list-item-title Download Version
v-divider
v-list-tile
v-list-tile-avatar: v-icon restore
v-list-tile-title Restore
v-list-item
v-list-item-avatar: v-icon restore
v-list-item-title Restore
v-divider
v-list-tile
v-list-tile-avatar: v-icon call_split
v-list-tile-title Branch off from here
v-list-item
v-list-item-avatar: v-icon call_split
v-list-item-title Branch off from here
v-btn.ma-0.radius-7(
v-if='total > trail.length'

@ -3,20 +3,20 @@
nav-header
v-navigation-drawer.pb-0(v-model='profileDrawerShown', app, fixed, clipped, left, permanent)
v-list(dense)
v-list-tile.pt-2(to='/profile')
v-list-tile-action: v-icon account_circle
v-list-tile-title Profile
v-list-tile(to='/preferences')
v-list-tile-action: v-icon settings
v-list-tile-title Preferences
v-list-item.pt-2(to='/profile')
v-list-item-action: v-icon account_circle
v-list-item-title Profile
v-list-item(to='/preferences')
v-list-item-action: v-icon settings
v-list-item-title Preferences
v-divider.my-2
v-subheader My Content
v-list-tile(to='/pages')
v-list-tile-action: v-icon pages
v-list-tile-title Pages
v-list-tile(to='/comments')
v-list-tile-action: v-icon question_answer
v-list-tile-title Comments
v-list-item(to='/pages')
v-list-item-action: v-icon pages
v-list-item-title Pages
v-list-item(to='/comments')
v-list-item-action: v-icon question_answer
v-list-item-title Comments
v-content
transition(name='profile-router')

@ -148,7 +148,7 @@ export default {
try {
const resp = await axios.post('/finalize', this.conf)
if (resp.data.ok === true) {
this.success = true
this.success = true
_.delay(() => {
window.location.assign('/login')
}, 3000)
@ -157,7 +157,7 @@ export default {
this.errorMessage = resp.data.error
this.loading = false
}
} catch(err) {
} catch (err) {
window.alert(err.message)
}
}, 1000)

@ -0,0 +1,12 @@
mutation ($providerKey: String!, $email: String!, $name: String!, $passwordRaw: String, $groups: [Int]!, $mustChangePassword: Boolean, $sendWelcomeEmail: Boolean) {
users {
create(providerKey: $providerKey, email: $email, name: $name, passwordRaw: $passwordRaw, groups: $groups, mustChangePassword: $mustChangePassword, sendWelcomeEmail: $sendWelcomeEmail) {
responseResult {
succeeded
errorCode
slug
message
}
}
}
}

@ -1,10 +1,11 @@
require('core-js/stable')
require('regenerator-runtime/runtime')
require('vuetify/src/stylus/main.styl')
require('./scss/app.scss')
require('./themes/' + process.env.CURRENT_THEME + '/scss/app.scss')
require('@mdi/font/css/materialdesignicons.css')
require('./helpers/compatibility.js')
require('./client-app.js')
require('./themes/' + process.env.CURRENT_THEME + '/js/app.js')

@ -1,7 +1,6 @@
require('core-js/stable')
require('regenerator-runtime/runtime')
require('vuetify/src/stylus/main.styl')
require('./scss/app.scss')
require('./helpers/compatibility.js')

@ -15,12 +15,9 @@
@import 'components/v-dialog';
@import 'components/v-form';
@import 'layout/md2';
// @import '../libs/twemoji/twemoji-awesome';
// @import '../libs/prism/prism.css';
@import '~vue-tour/dist/vue-tour.css';
@import '~vue-status-indicator/styles.css';
@import '~xterm/dist/xterm.css';
// @import 'node_modules/diff2html/dist/diff2html.min';

@ -1,37 +1,37 @@
@font-face {
font-family: 'Material Icons';
font-style: normal;
font-weight: 400;
src: local('Material Icons'),
local('MaterialIcons-Regular'),
url(/fonts/MaterialIcons-Regular.woff2) format('woff2'),
url(/fonts/MaterialIcons-Regular.woff) format('woff');
}
// @font-face {
// font-family: 'Material Icons';
// font-style: normal;
// font-weight: 400;
// src: local('Material Icons'),
// local('MaterialIcons-Regular'),
// url(/fonts/MaterialIcons-Regular.woff2) format('woff2'),
// url(/fonts/MaterialIcons-Regular.woff) format('woff');
// }
.material-icons {
font-family: 'Material Icons', sans-serif;
font-weight: normal;
font-style: normal;
font-size: 24px; /* Preferred icon size */
display: inline-flex;
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
white-space: nowrap;
direction: ltr;
// .material-icons {
// font-family: 'Material Icons', sans-serif;
// font-weight: normal;
// font-style: normal;
// font-size: 24px; /* Preferred icon size */
// display: inline-flex;
// line-height: 1;
// text-transform: none;
// letter-spacing: normal;
// word-wrap: normal;
// white-space: nowrap;
// direction: ltr;
/* Support for all WebKit browsers. */
-webkit-font-smoothing: antialiased;
/* Support for Safari and Chrome. */
text-rendering: optimizeLegibility;
// /* Support for all WebKit browsers. */
// -webkit-font-smoothing: antialiased;
// /* Support for Safari and Chrome. */
// text-rendering: optimizeLegibility;
/* Support for Firefox. */
-moz-osx-font-smoothing: grayscale;
// /* Support for Firefox. */
// -moz-osx-font-smoothing: grayscale;
/* Support for IE. */
font-feature-settings: 'liga';
}
// /* Support for IE. */
// font-feature-settings: 'liga';
// }
.icons {
display: inline-block;

@ -1,17 +0,0 @@
.md2 {
&.v-text-field {
.v-input__slot {
border-radius: 7px;
}
}
&.v-btn {
border-radius: 7px;
}
&.v-card {
border-radius: 7px;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

@ -41,83 +41,93 @@
divider='/'
)
template(slot='item', slot-scope='props')
v-icon(v-if='props.item.path === "/"', small, @click='goHome') home
v-btn.ma-0(v-else, :href='props.item.path', small, flat) {{props.item.name}}
v-icon(v-if='props.item.path === "/"', small, @click='goHome') mdi-home
v-btn.ma-0(v-else, :href='props.item.path', small, text) {{props.item.name}}
template(v-if='!isPublished')
v-spacer
.caption.red--text {{$t('common:page.unpublished')}}
status-indicator.ml-3(negative, pulse)
v-divider
v-layout(row)
v-flex(xs12, lg9, xl10)
v-toolbar(:color='darkMode ? `grey darken-4-l3` : `grey lighten-4`', flat, :height='90')
div
.headline.grey--text(:class='darkMode ? `text--lighten-2` : `text--darken-3`') {{title}}
.caption.grey--text.text--darken-1 {{description}}
v-divider
.contents(ref='container')
slot(name='contents')
v-toolbar.px-2(:color='darkMode ? `grey darken-4-l3` : `grey lighten-4`', flat, :height='90')
div
.headline.grey--text(:class='darkMode ? `text--lighten-2` : `text--darken-3`') {{title}}
.caption.grey--text.text--darken-1 {{description}}
v-spacer
v-divider
v-container.pl-5.pt-2(fill-height, fluid, grid-list-xl)
v-layout(row)
v-flex.page-col-sd(lg3, xl2, fill-height, v-if='$vuetify.breakpoint.lgAndUp')
v-card(v-if='toc.length')
.overline.pa-5.pb-0(:class='darkMode ? `indigo--text text--lighten-3` : `primary--text`') {{$t('common:page.toc')}}
v-list.pb-3(dense, nav, :class='darkMode ? `darken-3-d3` : ``')
template(v-for='(tocItem, tocIdx) in toc')
v-list-item(@click='$vuetify.goTo(tocItem.anchor, scrollOpts)')
v-icon(color='grey', small) mdi-chevron-right
v-list-item-title.pl-3 {{tocItem.title}}
// v-divider(v-if='tocIdx < toc.length - 1 || tocItem.children.length')
template(v-for='tocSubItem in tocItem.children')
v-list-item(@click='$vuetify.goTo(tocSubItem.anchor, scrollOpts)')
v-icon.pl-3(color='grey lighten-1', small) mdi-chevron-right
v-list-item-title.pl-3.caption.grey--text.text--darken-1 {{tocSubItem.title}}
// v-divider(inset, v-if='tocIdx < toc.length - 1')
v-flex(lg3, xl2, fill-height, v-if='$vuetify.breakpoint.lgAndUp')
v-toolbar(:color='darkMode ? `grey darken-4-l3` : `grey lighten-4`', flat, :height='90')
div
.caption.grey--text.text--lighten-1 {{$t('common:page.lastEditedBy')}}
.body-2.grey--text(:class='darkMode ? `` : `text--darken-3`') {{ authorName }}
.caption.grey--text.text--darken-1 {{ updatedAt | moment('calendar') }}
template(v-if='isAuthenticated')
v-spacer
v-tooltip(left)
v-btn.btn-animate-edit(icon, slot='activator', :href='"/e/" + locale + "/" + path')
v-icon(color='grey') edit
span {{$t('common:page.editPage')}}
v-divider
template(v-if='toc.length')
v-list.grey.pb-3(dense, :class='darkMode ? `darken-3-d3` : `lighten-3`')
v-subheader.pl-4(:class='darkMode ? `indigo--text text--lighten-3` : `primary--text`') {{$t('common:page.toc')}}
template(v-for='(tocItem, tocIdx) in toc')
v-list-tile(@click='$vuetify.goTo(tocItem.anchor, scrollOpts)')
v-icon(color='grey') arrow_right
v-list-tile-title.pl-3 {{tocItem.title}}
v-divider.ml-4(v-if='tocIdx < toc.length - 1 || tocItem.children.length')
template(v-for='tocSubItem in tocItem.children')
v-list-tile(@click='$vuetify.goTo(tocSubItem.anchor, scrollOpts)')
v-icon.pl-3(color='grey lighten-1') arrow_right
v-list-tile-title.pl-3.caption {{tocSubItem.title}}
v-divider(inset, v-if='tocIdx < toc.length - 1')
v-divider
//- v-list.grey(dense, :class='darkMode ? `darken-3` : `lighten-4`')
//- v-subheader.pl-4.yellow--text.text--darken-4 Rating
//- .text-xs-center
//- v-rating(
//- v-model='rating'
//- color='yellow darken-3'
//- background-color='grey lighten-1'
//- half-increments
//- hover
//- )
//- .pb-2.caption.grey--text 5 votes
//- v-divider
template(v-if='tags.length')
v-list.grey(dense, :class='darkMode ? `darken-3-d3` : `lighten-3`')
v-subheader.pl-4.teal--text Tags
template(v-for='(tag, idx) in tags')
v-list-tile(:href='`/t/` + tag.slug')
v-list-tile-avatar: v-icon(color='teal') label
v-list-tile-title {{tag.title}}
v-divider(inset, v-if='idx < tags.length - 1')
v-divider
v-toolbar(:color='darkMode ? `grey darken-3` : `grey lighten-4`', flat, dense)
v-spacer
v-tooltip(bottom)
v-btn(icon, slot='activator'): v-icon(color='grey') bookmark
span {{$t('common:page.bookmark')}}
v-tooltip(bottom)
v-btn(icon, slot='activator'): v-icon(color='grey') share
span {{$t('common:page.share')}}
v-tooltip(bottom)
v-btn(icon, slot='activator'): v-icon(color='grey') print
span {{$t('common:page.printFormat')}}
v-spacer
v-card.mt-5
.pa-5.pt-3
.overline.indigo--text.d-flex.align-center
span {{$t('common:page.lastEditedBy')}}
v-spacer
v-tooltip(left, v-if='isAuthenticated')
template(v-slot:activator='{ on }')
v-btn.btn-animate-edit(icon, :href='"/e/" + locale + "/" + path', v-on='on', x-small)
v-icon(color='grey', dense) mdi-pencil
span {{$t('common:page.editPage')}}
.body-2.grey--text(:class='darkMode ? `` : `text--darken-3`') {{ authorName }}
.caption.grey--text.text--darken-1 {{ updatedAt | moment('calendar') }}
v-card.mt-5
.pa-5
.overline.teal--text.pb-2 Tags
v-chip.mr-1(
label
color='teal lighten-5'
v-for='(tag, idx) in tags'
:href='`/t/` + tag.slug'
:key='tag.slug'
)
v-icon(color='teal', left, small) mdi-label
span.teal--text.text--darken-2 {{tag.text}}
v-divider
.pa-5
.overline.pb-2.yellow--text.text--darken-4 Rating
.text-center
v-rating(
v-model='rating'
color='yellow darken-3'
background-color='grey lighten-1'
half-increments
hover
)
.caption.grey--text 5 votes
v-divider
v-toolbar(:color='darkMode ? `grey darken-3` : `grey lighten-4`', flat, dense)
v-spacer
v-tooltip(bottom)
template(v-slot:activator='{ on }')
v-btn(icon, small, v-on='on'): v-icon(color='grey') mdi-bookmark
span {{$t('common:page.bookmark')}}
v-tooltip(bottom)
template(v-slot:activator='{ on }')
v-btn(icon, small, v-on='on'): v-icon(color='grey') mdi-share-variant
span {{$t('common:page.share')}}
v-tooltip(bottom)
template(v-slot:activator='{ on }')
v-btn(icon, small, v-on='on'): v-icon(color='grey') mdi-printer
span {{$t('common:page.printFormat')}}
v-spacer
v-flex.page-col-content(xs12, lg9, xl10)
.contents(ref='container')
slot(name='contents')
nav-footer
notify
search-results
@ -133,7 +143,7 @@
@click='$vuetify.goTo(0, scrollOpts)'
color='primary'
)
v-icon arrow_upward
v-icon mdi-arrow-up
</template>
<script>
@ -142,6 +152,17 @@ import Prism from 'prismjs'
import { get } from 'vuex-pathify'
import _ from 'lodash'
Prism.plugins.autoloader.languages_path = '/js/prism/'
Prism.plugins.NormalizeWhitespace.setDefaults({
'remove-trailing': true,
'remove-indent': true,
'left-trim': true,
'right-trim': true,
'break-lines': 160,
'remove-initial-line-feed': true,
'tabs-to-spaces': 2
})
export default {
components: {
StatusIndicator

@ -2,7 +2,7 @@
.contents {
color: mc('grey', '800');
padding: 24px 0 50px;
padding: .5rem 0 50px;
position: relative;
> div > *:first-child {
@ -51,7 +51,7 @@
}
h1 {
padding: 0 24px;
padding: 0;
color: mc('blue', '800');
margin-top: 2rem;
position: relative;
@ -68,6 +68,7 @@
width: 100%;
height: 2px;
background: linear-gradient(to right, mc('theme', 'primary'), rgba(mc('theme', 'primary'), 0));
border-radius: 3px;
@at-root .theme--dark & {
background: linear-gradient(to right, mc('teal', '300') 0%, mc('teal', '500') 10%, rgba(mc('teal', '900'), 0) 100%);
@ -82,7 +83,7 @@
}
}
h2 {
margin: 1rem 24px 0 24px;
margin: 1rem 0 0 0;
padding: 8px 0 0 0;
color: mc('grey', '800');
position: relative;
@ -113,7 +114,7 @@
}
}
h3 {
margin: 0 24px;
margin: 0;
padding: 8px 0 0 0;
color: mc('grey', '700');
position: relative;
@ -134,7 +135,7 @@
}
h4, h5, h6 {
font-size: 1rem;
margin: 0 24px;
margin: 0;
padding: 8px 0 0 0;
color: mc('grey', '700');
position: relative;
@ -176,10 +177,14 @@
@at-root .contents > div > p:first-child {
padding-top: 0;
}
@at-root .v-application & {
margin-bottom: 0;
}
}
hr {
margin: 1rem;
margin: 1rem 0;
height: 1px;
border: none;
background-color: mc('grey', '400');
@ -198,7 +203,7 @@
padding: 0 0 1rem 0;
border-left: 5px solid mc('blue', '500');
border-radius: .5rem;
margin: 1rem 2rem;
margin: 1rem 0;
> p:first-child .emoji {
margin-right: .5rem;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

@ -28,13 +28,7 @@ html
link(rel='manifest', href='/manifest.json')
//- Icon Set
if config.theming.iconset === 'mdi'
link(
type='text/css'
rel='stylesheet'
href='https://cdn.materialdesignicons.com/3.7.95/css/materialdesignicons.min.css'
)
else if config.theming.iconset === 'fa'
if config.theming.iconset === 'fa'
link(
type='text/css'
rel='stylesheet'

@ -32,13 +32,7 @@ html
var siteConfig = !{JSON.stringify(siteConfig)}; var siteLangs = !{JSON.stringify(langs)}
//- Icon Set
if config.theming.iconset === 'mdi'
link(
type='text/css'
rel='stylesheet'
href='https://cdn.materialdesignicons.com/3.7.95/css/materialdesignicons.min.css'
)
else if config.theming.iconset === 'fa'
if config.theming.iconset === 'fa'
link(
type='text/css'
rel='stylesheet'

@ -3,6 +3,7 @@ const path = require('path')
const fs = require('fs-extra')
const yargs = require('yargs').argv
const _ = require('lodash')
const Fiber = require('fibers')
const { VueLoaderPlugin } = require('vue-loader')
const CopyWebpackPlugin = require('copy-webpack-plugin')
@ -10,6 +11,7 @@ const HtmlWebpackPlugin = require('html-webpack-plugin')
const HtmlWebpackPugPlugin = require('html-webpack-pug-plugin')
const SimpleProgressWebpackPlugin = require('simple-progress-webpack-plugin')
const SriWebpackPlugin = require('webpack-subresource-integrity')
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin')
const WriteFilePlugin = require('write-file-webpack-plugin')
const babelConfig = fs.readJsonSync(path.join(process.cwd(), '.babelrc'))
@ -66,7 +68,7 @@ module.exports = {
]
},
{
test: /\.scss$/,
test: /\.sass$/,
use: [
{
loader: 'cache-loader',
@ -80,24 +82,39 @@ module.exports = {
{
loader: 'sass-loader',
options: {
implementation: require('sass'),
fiber: Fiber,
sourceMap: false
}
},
{
loader: 'sass-resources-loader',
options: {
resources: path.join(process.cwd(), '/client/scss/global.scss')
}
}
]
},
{
test: /\.styl$/,
test: /\.scss$/,
use: [
{
loader: 'cache-loader',
options: {
cacheDirectory: cacheDir
}
},
'style-loader',
'css-loader',
'postcss-loader',
'stylus-loader'
{
loader: 'sass-loader',
options: {
implementation: require('sass'),
fiber: Fiber,
sourceMap: false
}
},
{
loader: 'sass-resources-loader',
options: {
resources: path.join(process.cwd(), '/client/scss/global.scss')
}
}
]
},
{
@ -186,8 +203,10 @@ module.exports = {
},
plugins: [
new VueLoaderPlugin(),
new VuetifyLoaderPlugin(),
new CopyWebpackPlugin([
{ from: 'client/static' },
{ from: './node_modules/prismjs/components', to: 'js/prism' },
{ from: './node_modules/graphql-voyager/dist/voyager.worker.js', to: 'js/' }
], {}),
new HtmlWebpackPlugin({

@ -38,10 +38,10 @@
"@bugsnag/js": "6.3.2",
"algoliasearch": "3.33.0",
"apollo-fetch": "0.7.0",
"apollo-server": "2.6.9",
"apollo-server-express": "2.6.9",
"apollo-server": "2.7.2",
"apollo-server-express": "2.7.2",
"auto-load": "3.0.4",
"aws-sdk": "2.493.0",
"aws-sdk": "2.501.0",
"axios": "0.19.0",
"azure-search-client": "3.1.5",
"bcryptjs-then": "1.0.1",
@ -67,7 +67,7 @@
"express": "4.17.1",
"express-brute": "1.0.1",
"express-session": "1.16.2",
"file-type": "12.0.1",
"file-type": "12.1.0",
"filesize": "4.1.2",
"fs-extra": "8.1.0",
"getos": "3.1.1",
@ -86,8 +86,8 @@
"js-yaml": "3.13.1",
"jsonwebtoken": "8.5.1",
"klaw": "3.0.0",
"knex": "0.19.0",
"lodash": "4.17.14",
"knex": "0.19.1",
"lodash": "4.17.15",
"markdown-it": "9.0.1",
"markdown-it-abbr": "1.0.4",
"markdown-it-anchor": "5.2.4",
@ -108,11 +108,11 @@
"moment-timezone": "0.5.26",
"mongodb": "3.2.7",
"mssql": "5.1.0",
"multer": "1.4.1",
"multer": "1.4.2",
"mysql2": "1.6.5",
"nanoid": "2.0.3",
"node-2fa": "1.1.2",
"node-cache": "4.2.0",
"node-cache": "4.2.1",
"nodemailer": "6.3.0",
"objection": "1.6.9",
"passport": "0.4.0",
@ -135,7 +135,7 @@
"passport-saml": "1.1.0",
"passport-twitch": "1.0.3",
"pem-jwk": "2.0.0",
"pg": "7.11.0",
"pg": "7.12.0",
"pg-hstore": "2.3.3",
"pg-query-stream": "2.0.0",
"pg-tsquery": "8.0.5",
@ -148,9 +148,9 @@
"safe-regex": "2.0.2",
"sanitize-filename": "1.6.1",
"scim-query-filter-parser": "1.1.0",
"semver": "6.2.0",
"semver": "6.3.0",
"serve-favicon": "2.5.0",
"simple-git": "1.121.0",
"simple-git": "1.123.0",
"solr-node": "1.2.1",
"sqlite3": "4.0.9",
"striptags": "3.1.1",
@ -163,7 +163,7 @@
"validator": "11.1.0",
"validator-as-promised": "1.0.2",
"winston": "3.2.1",
"yargs": "13.2.4"
"yargs": "13.3.0"
},
"devDependencies": {
"@babel/cli": "^7.5.0",
@ -179,6 +179,7 @@
"@babel/plugin-syntax-import-meta": "^7.2.0",
"@babel/polyfill": "^7.4.4",
"@babel/preset-env": "^7.5.4",
"@mdi/font": "3.8.95",
"@panter/vue-i18next": "0.15.1",
"@vue/babel-preset-app": "3.9.2",
"animate-sass": "0.8.2",
@ -198,27 +199,28 @@
"babel-loader": "^8.0.6",
"babel-plugin-graphql-tag": "2.4.0",
"babel-plugin-lodash": "3.3.4",
"babel-plugin-prismjs": "1.0.2",
"babel-plugin-prismjs": "1.1.1",
"babel-plugin-transform-imports": "2.0.0",
"brace": "0.11.1",
"cache-loader": "4.0.1",
"cache-loader": "4.1.0",
"chart.js": "2.8.0",
"clean-webpack-plugin": "3.0.0",
"copy-webpack-plugin": "5.0.3",
"copy-webpack-plugin": "5.0.4",
"core-js": "3.1.4",
"css-loader": "3.0.0",
"css-loader": "3.1.0",
"cssnano": "4.1.10",
"duplicate-package-checker-webpack-plugin": "3.0.0",
"epic-spinners": "1.1.0",
"eslint": "6.0.1",
"eslint": "6.1.0",
"eslint-config-requarks": "1.0.7",
"eslint-config-standard": "13.0.1",
"eslint-plugin-import": "2.18.0",
"eslint-plugin-import": "2.18.2",
"eslint-plugin-node": "9.1.0",
"eslint-plugin-promise": "4.2.1",
"eslint-plugin-standard": "4.0.0",
"eslint-plugin-vue": "5.2.3",
"file-loader": "4.0.0",
"fibers": "4.0.1",
"file-loader": "4.1.0",
"filepond": "4.4.11",
"filepond-plugin-file-validate-type": "1.2.4",
"filesize.js": "1.0.2",
@ -228,16 +230,15 @@
"graphql-tag": "^2.10.1",
"graphql-voyager": "1.0.0-rc.27",
"hammerjs": "2.0.8",
"html-webpack-plugin": "3.2.0",
"html-webpack-plugin": "4.0.0-beta.8",
"html-webpack-pug-plugin": "2.0.0",
"i18next-chained-backend": "2.0.0",
"i18next-localstorage-backend": "3.0.0",
"i18next-xhr-backend": "3.0.0",
"ignore-loader": "0.1.2",
"js-cookie": "2.2.0",
"mini-css-extract-plugin": "0.7.0",
"mini-css-extract-plugin": "0.8.0",
"moment-duration-format": "2.3.2",
"node-sass": "4.12.0",
"offline-plugin": "5.0.7",
"optimize-css-assets-webpack-plugin": "5.0.3",
"postcss-cssnext": "3.1.0",
@ -247,50 +248,50 @@
"postcss-loader": "3.0.0",
"postcss-preset-env": "6.7.0",
"postcss-selector-parser": "6.0.2",
"prismjs": "1.16.0",
"prismjs": "1.17.1",
"pug-lint": "2.6.0",
"pug-loader": "2.4.0",
"pug-plain-loader": "1.0.0",
"raw-loader": "3.0.0",
"raw-loader": "3.1.0",
"react": "16.8.6",
"react-dom": "16.8.6",
"resolve-url-loader": "3.1.0",
"sass": "1.22.7",
"sass-loader": "7.1.0",
"sass-resources-loader": "2.0.1",
"script-ext-html-webpack-plugin": "2.1.4",
"simple-progress-webpack-plugin": "1.1.2",
"style-loader": "0.23.1",
"stylus": "0.54.5",
"stylus-loader": "3.0.2",
"terser": "4.1.2",
"twemoji-awesome": "1.0.6",
"url-loader": "2.0.1",
"vee-validate": "2.2.12",
"url-loader": "2.1.0",
"vee-validate": "2.2.13",
"velocity-animate": "1.5.2",
"viz.js": "2.1.2",
"vue": "2.6.10",
"vue-apollo": "3.0.0-rc.1",
"vue-apollo": "3.0.0-rc.2",
"vue-chartjs": "3.4.2",
"vue-clipboards": "1.3.0",
"vue-codemirror": "4.0.6",
"vue-filepond": "5.1.1",
"vue-filepond": "5.1.2",
"vue-hot-reload-api": "2.3.3",
"vue-loader": "15.7.0",
"vue-loader": "15.7.1",
"vue-material-design-icons": "3.3.1",
"vue-moment": "4.0.0",
"vue-router": "3.0.7",
"vue-simple-breakpoints": "1.0.3",
"vue-status-indicator": "1.1.1",
"vue-status-indicator": "1.2.1",
"vue-template-compiler": "2.6.10",
"vue-tour": "1.1.0",
"vue2-animate": "2.1.0",
"vuedraggable": "2.23.0",
"vuescroll": "4.13.1",
"vuetify": "1.5.16",
"vuetify": "2.0.1",
"vuetify-loader": "1.3.0",
"vuex": "3.1.1",
"vuex-pathify": "1.2.4",
"vuex-persistedstate": "2.5.4",
"webpack": "4.35.3",
"webpack": "4.38.0",
"webpack-bundle-analyzer": "3.3.2",
"webpack-cli": "3.3.6",
"webpack-dev-middleware": "3.7.0",

@ -0,0 +1,13 @@
exports.up = knex => {
return knex.schema
.table('users', table => {
table.boolean('mustChangePwd').notNullable().defaultTo(false)
})
}
exports.down = knex => {
return knex.schema
.table('users', table => {
table.dropColumn('mustChangePwd')
})
}

@ -0,0 +1,13 @@
exports.up = knex => {
return knex.schema
.table('users', table => {
table.boolean('mustChangePwd').notNullable().defaultTo(false)
})
}
exports.down = knex => {
return knex.schema
.table('users', table => {
table.dropColumn('mustChangePwd')
})
}

@ -29,11 +29,7 @@ module.exports = {
},
UserMutation: {
create(obj, args) {
return WIKI.models.users.register({
...args,
verify: false,
bypassChecks: true
})
return WIKI.models.users.createNewUser(args)
},
delete(obj, args) {
return WIKI.models.users.query().deleteById(args.id)

@ -36,10 +36,12 @@ type UserQuery {
type UserMutation {
create(
email: String!
name: String
name: String!
passwordRaw: String
providerKey: String!
providerId: String
groups: [Int]!
mustChangePassword: Boolean
sendWelcomeEmail: Boolean
): UserResponse @auth(requires: ["write:users", "manage:users", "manage:system"])
update(

@ -360,6 +360,88 @@ module.exports = class User extends Model {
throw new WIKI.Error.AuthTFAInvalid()
}
static async createNewUser ({ providerKey, email, passwordRaw, name, groups, mustChangePassword, sendWelcomeEmail }) {
// Input sanitization
email = _.toLower(email)
// Input validation
const validation = validate({
email,
passwordRaw,
name
}, {
email: {
email: true,
length: {
maximum: 255
}
},
passwordRaw: {
presence: {
allowEmpty: false
},
length: {
minimum: 6
}
},
name: {
presence: {
allowEmpty: false
},
length: {
minimum: 2,
maximum: 255
}
}
}, { format: 'flat' })
if (validation && validation.length > 0) {
throw new WIKI.Error.InputInvalid(validation[0])
}
// Check if email already exists
const usr = await WIKI.models.users.query().findOne({ email, providerKey })
if (!usr) {
// Create the account
const newUsr = await WIKI.models.users.query().insert({
provider: providerKey,
email,
name,
password: passwordRaw,
locale: 'en',
defaultEditor: 'markdown',
tfaIsActive: false,
isSystem: false,
isActive: true,
isVerified: true,
mustChangePwd: (mustChangePassword === true)
})
// Assign to group(s)
if (groups.length > 0) {
await newUsr.$relatedQuery('groups').relate(groups)
}
if (sendWelcomeEmail) {
// Send welcome email
await WIKI.mail.send({
template: 'accountWelcome',
to: email,
subject: `Welcome to the wiki ${WIKI.config.title}`,
data: {
preheadertext: `You've been invited to the wiki ${WIKI.config.title}`,
title: `You've been invited to the wiki ${WIKI.config.title}`,
content: `Click the button below to access the wiki.`,
buttonLink: `${WIKI.config.host}/login`,
buttonText: 'Login'
},
text: `You've been invited to the wiki ${WIKI.config.title}: ${WIKI.config.host}/login`
})
}
} else {
throw new WIKI.Error.AuthAccountAlreadyExists()
}
}
static async register ({ email, password, name, verify = false, bypassChecks = false }, context) {
const localStrg = await WIKI.models.authentication.getStrategy('local')
// Check if self-registration is enabled

@ -28,13 +28,7 @@ html
link(rel='manifest', href='/manifest.json')
//- Icon Set
if config.theming.iconset === 'mdi'
link(
type='text/css'
rel='stylesheet'
href='https://cdn.materialdesignicons.com/3.7.95/css/materialdesignicons.min.css'
)
else if config.theming.iconset === 'fa'
if config.theming.iconset === 'fa'
link(
type='text/css'
rel='stylesheet'

@ -32,13 +32,7 @@ html
var siteConfig = !{JSON.stringify(siteConfig)}; var siteLangs = !{JSON.stringify(langs)}
//- Icon Set
if config.theming.iconset === 'mdi'
link(
type='text/css'
rel='stylesheet'
href='https://cdn.materialdesignicons.com/3.7.95/css/materialdesignicons.min.css'
)
else if config.theming.iconset === 'fa'
if config.theming.iconset === 'fa'
link(
type='text/css'
rel='stylesheet'

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save