feat: profile page to vue 3 composition + add fonts / width options to theme + site config preload

parent d9dbd0f6
...@@ -486,10 +486,13 @@ exports.up = async knex => { ...@@ -486,10 +486,13 @@ exports.up = async knex => {
injectCSS: '', injectCSS: '',
injectHead: '', injectHead: '',
injectBody: '', injectBody: '',
contentWidth: 'full',
sidebarPosition: 'left', sidebarPosition: 'left',
tocPosition: 'right', tocPosition: 'right',
showSharingMenu: true, showSharingMenu: true,
showPrintBtn: true showPrintBtn: true,
baseFont: 'roboto',
contentFont: 'roboto'
} }
} }
}) })
......
...@@ -39,33 +39,33 @@ module.exports = { ...@@ -39,33 +39,33 @@ module.exports = {
}) })
}, []), 'key') }, []), 'key')
})) }))
},
/**
* Fetch active authentication strategies
*/
async authSiteStrategies (obj, args, context, info) {
let strategies = await WIKI.models.authentication.getStrategies()
strategies = strategies.map(stg => {
const strategyInfo = _.find(WIKI.data.authentication, ['key', stg.strategyKey]) || {}
return {
...stg,
strategy: strategyInfo,
config: _.sortBy(_.transform(stg.config, (res, value, key) => {
const configData = _.get(strategyInfo.props, key, false)
if (configData) {
res.push({
key,
value: JSON.stringify({
...configData,
value
})
})
}
}, []), 'key')
}
})
return args.enabledOnly ? _.filter(strategies, 'isEnabled') : strategies
} }
// /**
// * Fetch active authentication strategies
// */
// async activeStrategies (obj, args, context, info) {
// let strategies = await WIKI.models.authentication.getStrategies()
// strategies = strategies.map(stg => {
// const strategyInfo = _.find(WIKI.data.authentication, ['key', stg.strategyKey]) || {}
// return {
// ...stg,
// strategy: strategyInfo,
// config: _.sortBy(_.transform(stg.config, (res, value, key) => {
// const configData = _.get(strategyInfo.props, key, false)
// if (configData) {
// res.push({
// key,
// value: JSON.stringify({
// ...configData,
// value
// })
// })
// }
// }, []), 'key')
// }
// })
// return args.enabledOnly ? _.filter(strategies, 'isEnabled') : strategies
// }
}, },
Mutation: { Mutation: {
/** /**
......
...@@ -7,10 +7,12 @@ extend type Query { ...@@ -7,10 +7,12 @@ extend type Query {
apiState: Boolean apiState: Boolean
authStrategies( authStrategies: [AuthenticationStrategy]
siteId: UUID
authSiteStrategies(
siteId: UUID!
enabledOnly: Boolean enabledOnly: Boolean
): [AuthenticationStrategy] ): [AuthenticationSiteStrategy]
} }
extend type Mutation { extend type Mutation {
...@@ -70,12 +72,12 @@ extend type Mutation { ...@@ -70,12 +72,12 @@ extend type Mutation {
# ----------------------------------------------- # -----------------------------------------------
type AuthenticationStrategy { type AuthenticationStrategy {
key: String! key: String
props: [KeyValuePair] @auth(requires: ["manage:system"]) props: [KeyValuePair]
title: String! title: String
description: String description: String
isAvailable: Boolean isAvailable: Boolean
useForm: Boolean! useForm: Boolean
usernameType: String usernameType: String
logo: String logo: String
color: String color: String
...@@ -83,16 +85,16 @@ type AuthenticationStrategy { ...@@ -83,16 +85,16 @@ type AuthenticationStrategy {
icon: String icon: String
} }
type AuthenticationActiveStrategy { type AuthenticationSiteStrategy {
key: String! key: String
strategy: AuthenticationStrategy! strategy: AuthenticationStrategy
displayName: String! displayName: String
order: Int! order: Int
isEnabled: Boolean! isEnabled: Boolean
config: [KeyValuePair] @auth(requires: ["manage:system"]) config: [KeyValuePair]
selfRegistration: Boolean! selfRegistration: Boolean
domainWhitelist: [String]! @auth(requires: ["manage:system"]) domainWhitelist: [String]
autoEnrollGroups: [Int]! @auth(requires: ["manage:system"]) autoEnrollGroups: [Int]
} }
type AuthenticationLoginResponse { type AuthenticationLoginResponse {
......
...@@ -3,42 +3,42 @@ ...@@ -3,42 +3,42 @@
# =============================================== # ===============================================
extend type Query { extend type Query {
sites: [Site] @auth(requires: ["manage:system"]) sites: [Site]
siteById ( siteById (
id: UUID! id: UUID!
): Site @auth(requires: ["manage:system"]) ): Site
siteByHostname ( siteByHostname (
hostname: String! hostname: String!
exact: Boolean! exact: Boolean!
): Site @auth(requires: ["manage:system"]) ): Site
} }
extend type Mutation { extend type Mutation {
createSite ( createSite (
hostname: String! hostname: String!
title: String! title: String!
): SiteCreateResponse @auth(requires: ["manage:system"]) ): SiteCreateResponse
updateSite ( updateSite (
id: UUID! id: UUID!
patch: SiteUpdateInput! patch: SiteUpdateInput!
): DefaultResponse @auth(requires: ["manage:system"]) ): DefaultResponse
uploadSiteLogo ( uploadSiteLogo (
id: UUID! id: UUID!
image: Upload! image: Upload!
): DefaultResponse @auth(requires: ["manage:system"]) ): DefaultResponse
uploadSiteFavicon ( uploadSiteFavicon (
id: UUID! id: UUID!
image: Upload! image: Upload!
): DefaultResponse @auth(requires: ["manage:system"]) ): DefaultResponse
deleteSite ( deleteSite (
id: UUID! id: UUID!
): DefaultResponse @auth(requires: ["manage:system"]) ): DefaultResponse
} }
# ----------------------------------------------- # -----------------------------------------------
...@@ -103,13 +103,22 @@ type SiteTheme { ...@@ -103,13 +103,22 @@ type SiteTheme {
injectCSS: String injectCSS: String
injectHead: String injectHead: String
injectBody: String injectBody: String
contentWidth: SiteThemeWidth
sidebarPosition: SiteThemePosition sidebarPosition: SiteThemePosition
tocPosition: SiteThemePosition tocPosition: SiteThemePosition
showSharingMenu: Boolean showSharingMenu: Boolean
showPrintBtn: Boolean showPrintBtn: Boolean
baseFont: String
contentFont: String
}
enum SiteThemeWidth {
full
centered
} }
enum SiteThemePosition { enum SiteThemePosition {
off
left left
right right
} }
...@@ -172,8 +181,11 @@ input SiteThemeInput { ...@@ -172,8 +181,11 @@ input SiteThemeInput {
injectCSS: String injectCSS: String
injectHead: String injectHead: String
injectBody: String injectBody: String
contentWidth: SiteThemeWidth
sidebarPosition: SiteThemePosition sidebarPosition: SiteThemePosition
tocPosition: SiteThemePosition tocPosition: SiteThemePosition
showSharingMenu: Boolean showSharingMenu: Boolean
showPrintBtn: Boolean showPrintBtn: Boolean
baseFont: String
contentFont: String
} }
...@@ -97,7 +97,9 @@ module.exports = class Site extends Model { ...@@ -97,7 +97,9 @@ module.exports = class Site extends Model {
sidebarPosition: 'left', sidebarPosition: 'left',
tocPosition: 'right', tocPosition: 'right',
showSharingMenu: true, showSharingMenu: true,
showPrintBtn: true showPrintBtn: true,
baseFont: 'roboto',
contentFont: 'roboto'
} }
}) })
}) })
......
...@@ -8,9 +8,7 @@ ...@@ -8,9 +8,7 @@
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width"> <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
<title>Wiki.js</title> <title>Wiki.js</title>
<!--preload-links--> <!--preload-links-->
<link rel="preconnect" href="https://fonts.googleapis.com"> <link href="/_assets/fonts/roboto/roboto.css" rel="stylesheet" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Rubik:wght@300..900&display=swap" rel="stylesheet">
<style type="text/css"> <style type="text/css">
@keyframes initspinner { @keyframes initspinner {
to { transform: rotate(360deg); } to { transform: rotate(360deg); }
...@@ -69,7 +67,7 @@ ...@@ -69,7 +67,7 @@
</style> </style>
</noscript> </noscript>
</head> </head>
<body> <body class="wiki-root">
<div class="init-loading"></div> <div class="init-loading"></div>
<div id="app"><!-- quasar:entry-point --></div> <div id="app"><!-- quasar:entry-point --></div>
</body> </body>
......
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
/* roboto-300 - vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
src: local(''),
url('/_assets/fonts/roboto/roboto-all-300.woff2') format('woff2')
}
/* roboto-regular - vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: local(''),
url('/_assets/fonts/roboto/roboto-all-regular.woff2') format('woff2')
}
/* roboto-500 - vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
src: local(''),
url('/_assets/fonts/roboto/roboto-all-500.woff2') format('woff2')
}
/* roboto-700 - vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: local(''),
url('/_assets/fonts/roboto/roboto-all-700.woff2') format('woff2')
}
/* roboto-900 - vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 900;
src: local(''),
url('/_assets/fonts/roboto/roboto-all-900.woff2') format('woff2')
}
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
/* cyrillic-ext */
@font-face {
font-family: 'Rubik';
font-display: swap;
src: url(/_assets/fonts/rubik/rubik-variable-cyrillic-ext.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Rubik';
font-display: swap;
src: url(/_assets/fonts/rubik/rubik-variable-cyrillic.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* hebrew */
@font-face {
font-family: 'Rubik';
font-display: swap;
src: url(/_assets/fonts/rubik/rubik-variable-hebrew.woff2) format('woff2');
unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
}
/* latin-ext */
@font-face {
font-family: 'Rubik';
font-display: swap;
src: url(/_assets/fonts/rubik/rubik-variable-latin-ext.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Rubik';
font-display: swap;
src: url(/_assets/fonts/rubik/rubik-variable-latin.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
body.wiki-root {
font-family: 'Rubik', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40" width="80px" height="80px"><path fill="#b6dcfe" d="M37,29v-8c0,0,0-4-3-5c0,0,4-1,5,5v8H37z"/><path fill="#b6dcfe" d="M26,26c0,1.657,1.343,3,3,3v-6C27.343,23,26,24.343,26,26z"/><polygon fill="#b6dcfe" points="9,8 13,8 21,29.5 17,29.5"/><path fill="#4788c7" d="M21.469,29.325l-8-21.5C13.396,7.63,13.209,7.5,13,7.5H9c-0.001,0-0.003,0.001-0.004,0.001 C8.921,7.502,8.85,7.521,8.784,7.553C8.765,7.562,8.751,7.577,8.733,7.588C8.689,7.617,8.65,7.65,8.616,7.691 C8.609,7.701,8.597,7.705,8.59,7.715C8.581,7.728,8.581,7.744,8.573,7.757C8.562,7.778,8.544,7.794,8.535,7.816l-8.5,21.5 c-0.102,0.257,0.024,0.547,0.281,0.648C0.377,29.989,0.438,30,0.5,30c0.199,0,0.388-0.12,0.465-0.316L3.607,23H14 c0.016,0,0.029-0.008,0.044-0.009l2.487,6.684C16.604,29.87,16.791,30,17,30h4c0.164,0,0.317-0.08,0.41-0.215 C21.504,29.65,21.525,29.479,21.469,29.325z M4.003,22L8.986,9.396L13.676,22H4.003z M17.348,29L9.72,8.5h2.933L20.28,29H17.348z"/><path fill="#4788c7" d="M38.512,17.309c-1.107-1.354-3.235-2.852-7.082-2.304c-0.04,0.006-0.078,0.016-0.113,0.03 c-1.539,0.168-3.374,1.214-5.24,4.2c-0.146,0.233-0.075,0.542,0.159,0.688c0.232,0.146,0.542,0.076,0.688-0.159 c1.932-3.091,3.959-4.282,6.033-3.544c1.326,0.474,2.541,1.967,2.915,3.418C35.439,20.339,33.944,22,29.5,22 c-2.481,0-4.5,1.794-4.5,4s2.019,4,4.5,4c3.349,0,5.417-1.668,6.5-2.922V29.5c0,0.276,0.224,0.5,0.5,0.5h3 c0.276,0,0.5-0.224,0.5-0.5v-7.76C40,20.055,39.472,18.481,38.512,17.309z M26,26c0-1.509,1.306-2.761,3-2.97v5.939 C27.306,28.761,26,27.509,26,26z M30,28.976v-5.99c3.282-0.094,5.065-1.085,6-1.965v4.352C35.684,25.938,33.906,28.747,30,28.976z M39,29h-2v-8.5c0-1.604-0.979-3.368-2.329-4.439c1.248,0.284,2.274,0.912,3.067,1.881C38.552,18.937,39,20.285,39,21.74V29z"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40" width="80px" height="80px"><path fill="#b6dcfe" d="M34.5 6.5H37.5V32.5H34.5z"/><path fill="#4788c7" d="M37,7v25h-2V7H37 M38,6h-4v27h4V6L38,6z"/><path fill="#b6dcfe" d="M1.5 6.5H4.5V32.5H1.5z"/><path fill="#4788c7" d="M4 7v25H2V7H4M5 6H1v27h4V6L5 6zM30.5 32A.5.5 0 1 0 30.5 33 .5.5 0 1 0 30.5 32zM28.5 32A.5.5 0 1 0 28.5 33 .5.5 0 1 0 28.5 32zM26.5 32A.5.5 0 1 0 26.5 33 .5.5 0 1 0 26.5 32zM24.5 32A.5.5 0 1 0 24.5 33 .5.5 0 1 0 24.5 32zM22.5 32A.5.5 0 1 0 22.5 33 .5.5 0 1 0 22.5 32zM20.5 32A.5.5 0 1 0 20.5 33 .5.5 0 1 0 20.5 32zM18.5 32A.5.5 0 1 0 18.5 33 .5.5 0 1 0 18.5 32zM16.5 32A.5.5 0 1 0 16.5 33 .5.5 0 1 0 16.5 32zM14.5 32A.5.5 0 1 0 14.5 33 .5.5 0 1 0 14.5 32zM12.5 32A.5.5 0 1 0 12.5 33 .5.5 0 1 0 12.5 32zM10.5 32A.5.5 0 1 0 10.5 33 .5.5 0 1 0 10.5 32zM8.5 32A.5.5 0 1 0 8.5 33 .5.5 0 1 0 8.5 32zM6.5 32A.5.5 0 1 0 6.5 33 .5.5 0 1 0 6.5 32zM30.5 6A.5.5 0 1 0 30.5 7 .5.5 0 1 0 30.5 6zM32.5 32A.5.5 0 1 0 32.5 33 .5.5 0 1 0 32.5 32zM32.5 6A.5.5 0 1 0 32.5 7 .5.5 0 1 0 32.5 6zM28.5 6A.5.5 0 1 0 28.5 7 .5.5 0 1 0 28.5 6zM26.5 6A.5.5 0 1 0 26.5 7 .5.5 0 1 0 26.5 6zM24.5 6A.5.5 0 1 0 24.5 7 .5.5 0 1 0 24.5 6zM22.5 6A.5.5 0 1 0 22.5 7 .5.5 0 1 0 22.5 6zM20.5 6A.5.5 0 1 0 20.5 7 .5.5 0 1 0 20.5 6zM18.5 6A.5.5 0 1 0 18.5 7 .5.5 0 1 0 18.5 6zM16.5 6A.5.5 0 1 0 16.5 7 .5.5 0 1 0 16.5 6zM14.5 6A.5.5 0 1 0 14.5 7 .5.5 0 1 0 14.5 6zM12.5 6A.5.5 0 1 0 12.5 7 .5.5 0 1 0 12.5 6zM10.5 6A.5.5 0 1 0 10.5 7 .5.5 0 1 0 10.5 6zM8.5 6A.5.5 0 1 0 8.5 7 .5.5 0 1 0 8.5 6zM6.5 6A.5.5 0 1 0 6.5 7 .5.5 0 1 0 6.5 6z"/><g><path fill="#4788c7" d="M12 21L20 21 20 18 12 18 12 13 5 19.5 12 26z"/></g><g><path fill="#4788c7" d="M27 18L19 18 19 21 27 21 27 26 34 19.5 27 13z"/></g></svg>
\ No newline at end of file
...@@ -46,9 +46,8 @@ module.exports = configure(function (/* ctx */) { ...@@ -46,9 +46,8 @@ module.exports = configure(function (/* ctx */) {
'fontawesome-v6', 'fontawesome-v6',
// 'eva-icons', // 'eva-icons',
// 'themify', // 'themify',
'line-awesome', 'line-awesome'
'roboto-font-latin-ext' // this or either 'roboto-font', NEVER both! // 'roboto-font-latin-ext' // this or either 'roboto-font', NEVER both!
// 'roboto-font', // optional, you are not bound to it // 'roboto-font', // optional, you are not bound to it
// 'material-icons' // optional, you are not bound to it // 'material-icons' // optional, you are not bound to it
], ],
......
...@@ -3,15 +3,42 @@ router-view ...@@ -3,15 +3,42 @@ router-view
</template> </template>
<script setup> <script setup>
import { nextTick, onMounted } from 'vue' import { nextTick, onMounted, reactive } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useSiteStore } from 'src/stores/site' import { useSiteStore } from 'src/stores/site'
import { setCssVar, useQuasar } from 'quasar'
/* global siteConfig */ /* global siteConfig */
// QUASAR
const $q = useQuasar()
// STORES // STORES
const siteStore = useSiteStore() const siteStore = useSiteStore()
// ROUTER
const router = useRouter()
// STATE
const state = reactive({
isInitialized: false
})
// THEME
function applyTheme () {
$q.dark.set(siteStore.theme.dark)
setCssVar('primary', siteStore.theme.colorPrimary)
setCssVar('secondary', siteStore.theme.colorSecondary)
setCssVar('accent', siteStore.theme.colorAccent)
setCssVar('header', siteStore.theme.colorHeader)
setCssVar('sidebar', siteStore.theme.colorSidebar)
}
// INIT SITE STORE // INIT SITE STORE
if (typeof siteConfig !== 'undefined') { if (typeof siteConfig !== 'undefined') {
...@@ -19,15 +46,21 @@ if (typeof siteConfig !== 'undefined') { ...@@ -19,15 +46,21 @@ if (typeof siteConfig !== 'undefined') {
id: siteConfig.id, id: siteConfig.id,
title: siteConfig.title title: siteConfig.title
}) })
} else { applyTheme()
siteStore.loadSite(window.location.hostname)
} }
// MOUNTED router.beforeEach(async (to, from) => {
if (!siteStore.id) {
onMounted(async () => { console.info('No pre-cached site config. Loading site info...')
nextTick(() => { await siteStore.loadSite(window.location.hostname)
console.info(`Using Site ID ${siteStore.id}`)
applyTheme()
}
})
router.afterEach(() => {
if (!state.isInitialized) {
state.isInitialized = true
document.querySelector('.init-loading').remove() document.querySelector('.init-loading').remove()
}) }
}) })
</script> </script>
...@@ -6,7 +6,6 @@ export default boot(({ app }) => { ...@@ -6,7 +6,6 @@ export default boot(({ app }) => {
const i18n = createI18n({ const i18n = createI18n({
legacy: false, legacy: false,
locale: 'en-US', locale: 'en-US',
allowComposition: true,
messages messages
}) })
......
...@@ -17,14 +17,14 @@ q-header.bg-header.text-white.site-header( ...@@ -17,14 +17,14 @@ q-header.bg-header.text-white.site-header(
square square
) )
img(src='/_assets/logo-wikijs.svg') img(src='/_assets/logo-wikijs.svg')
q-toolbar-title.text-h6.font-poppins {{siteTitle}} q-toolbar-title.text-h6 {{siteStore.title}}
q-toolbar.gt-sm( q-toolbar.gt-sm(
style='height: 64px;' style='height: 64px;'
dark dark
) )
q-input( q-input(
dark dark
v-model='search' v-model='state.search'
standout='bg-white text-dark' standout='bg-white text-dark'
dense dense
rounded rounded
...@@ -37,8 +37,8 @@ q-header.bg-header.text-white.site-header( ...@@ -37,8 +37,8 @@ q-header.bg-header.text-white.site-header(
template(v-slot:append) template(v-slot:append)
q-icon.cursor-pointer( q-icon.cursor-pointer(
name='las la-times' name='las la-times'
@click='search=``' @click='state.search=``'
v-if='search.length > 0' v-if='state.search.length > 0'
:color='$q.dark.isActive ? `blue` : `grey-4`' :color='$q.dark.isActive ? `blue` : `grey-4`'
) )
q-btn.q-ml-md( q-btn.q-ml-md(
...@@ -47,7 +47,7 @@ q-header.bg-header.text-white.site-header( ...@@ -47,7 +47,7 @@ q-header.bg-header.text-white.site-header(
dense dense
icon='las la-tags' icon='las la-tags'
color='grey' color='grey'
to='/t' to='/_tags'
) )
q-toolbar( q-toolbar(
style='height: 64px;' style='height: 64px;'
...@@ -56,7 +56,7 @@ q-header.bg-header.text-white.site-header( ...@@ -56,7 +56,7 @@ q-header.bg-header.text-white.site-header(
q-space q-space
transition(name='syncing') transition(name='syncing')
q-spinner-rings.q-mr-sm( q-spinner-rings.q-mr-sm(
v-show='isSyncing' v-show='siteStore.routerLoading'
color='orange' color='orange'
size='34px' size='34px'
) )
...@@ -83,26 +83,33 @@ q-header.bg-header.text-white.site-header( ...@@ -83,26 +83,33 @@ q-header.bg-header.text-white.site-header(
account-menu account-menu
</template> </template>
<script> <script setup>
import { get } from 'vuex-pathify'
import AccountMenu from './AccountMenu.vue' import AccountMenu from './AccountMenu.vue'
import NewMenu from './PageNewMenu.vue' import NewMenu from './PageNewMenu.vue'
export default { import { useI18n } from 'vue-i18n'
components: { import { useQuasar } from 'quasar'
AccountMenu, import { reactive } from 'vue'
NewMenu
}, import { useSiteStore } from 'src/stores/site'
data () {
return { // QUASAR
search: ''
} const $q = useQuasar()
},
computed: { // STORES
isSyncing: get('isLoading', false),
siteTitle: get('site/title', false) const siteStore = useSiteStore()
}
} // I18N
const { t } = useI18n()
// DATA
const state = reactive({
search: ''
})
</script> </script>
<style lang="scss"> <style lang="scss">
......
...@@ -24,20 +24,32 @@ q-menu( ...@@ -24,20 +24,32 @@ q-menu(
blueprint-icon(icon='advance') blueprint-icon(icon='advance')
q-item-section.q-pr-sm New Redirection q-item-section.q-pr-sm New Redirection
q-separator.q-my-sm(inset) q-separator.q-my-sm(inset)
q-item(clickable, to='/f') q-item(clickable, to='/_assets')
blueprint-icon(icon='add-image') blueprint-icon(icon='add-image')
q-item-section.q-pr-sm Upload Media Asset q-item-section.q-pr-sm Upload Media Asset
</template> </template>
<script> <script setup>
export default { import { useI18n } from 'vue-i18n'
data () { import { useQuasar } from 'quasar'
return { }
}, import { usePageStore } from 'src/stores/page'
methods: {
create (editor) { // QUASAR
this.$store.dispatch('page/pageCreate', { editor })
} const $q = useQuasar()
}
// STORES
const pageStore = usePageStore()
// I18N
const { t } = useI18n()
// METHODS
function create (editor) {
pageStore.pageCreate({ editor })
} }
</script> </script>
...@@ -28,17 +28,8 @@ body::-webkit-scrollbar-thumb { ...@@ -28,17 +28,8 @@ body::-webkit-scrollbar-thumb {
// ------------------------------------------------------------------ // ------------------------------------------------------------------
@font-face { @font-face {
font-family: 'Poppins';
src: url(./fonts/poppins-medium.woff2);
}
.font-poppins {
font-family: $font-poppins;
}
@font-face {
font-family: 'Roboto Mono'; font-family: 'Roboto Mono';
src: url(./fonts/roboto-mono.woff2); src: url(/_assets/fonts/roboto-mono/roboto-mono.woff2);
} }
.font-robotomono { .font-robotomono {
......
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
...@@ -30,7 +30,3 @@ $dark-6: #070a0d; ...@@ -30,7 +30,3 @@ $dark-6: #070a0d;
$dark-5: #0d1117; $dark-5: #0d1117;
$dark-4: #161b22; $dark-4: #161b22;
$dark-3: #1e232a; $dark-3: #1e232a;
// -- FONTS --
$font-poppins: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
...@@ -683,10 +683,10 @@ ...@@ -683,10 +683,10 @@
"admin.theme.headHtmlInjection": "Head HTML Injection", "admin.theme.headHtmlInjection": "Head HTML Injection",
"admin.theme.headHtmlInjectionHint": "HTML code to be injected just before the closing head tag. Usually for script tags.", "admin.theme.headHtmlInjectionHint": "HTML code to be injected just before the closing head tag. Usually for script tags.",
"admin.theme.headerColor": "Header Color", "admin.theme.headerColor": "Header Color",
"admin.theme.headerColorHint": "The background color for the site top header.", "admin.theme.headerColorHint": "The background color for the site top header. Does not apply to the administration area.",
"admin.theme.iconset": "Icon Set", "admin.theme.iconset": "Icon Set",
"admin.theme.iconsetHint": "Set of icons to use for the sidebar navigation.", "admin.theme.iconsetHint": "Set of icons to use for the sidebar navigation.",
"admin.theme.layout": "Theme Layout", "admin.theme.layout": "Layout",
"admin.theme.options": "Theme Options", "admin.theme.options": "Theme Options",
"admin.theme.primaryColor": "Primary Color", "admin.theme.primaryColor": "Primary Color",
"admin.theme.primaryColorHint": "The main color for primary action buttons and most form elements.", "admin.theme.primaryColorHint": "The main color for primary action buttons and most form elements.",
...@@ -701,7 +701,7 @@ ...@@ -701,7 +701,7 @@
"admin.theme.showSharingMenu": "Show Sharing Menu", "admin.theme.showSharingMenu": "Show Sharing Menu",
"admin.theme.showSharingMenuHint": "Should the sharing menu be displayed on all pages.", "admin.theme.showSharingMenuHint": "Should the sharing menu be displayed on all pages.",
"admin.theme.sidebarColor": "Sidebar Color", "admin.theme.sidebarColor": "Sidebar Color",
"admin.theme.sidebarColorHint": "The background color for the side navigation menu on content pages.", "admin.theme.sidebarColorHint": "The background color for the side navigation menu on content pages. Does not apply to the administration area.",
"admin.theme.sidebarPosition": "Sidebar Position", "admin.theme.sidebarPosition": "Sidebar Position",
"admin.theme.sidebarPositionHint": "On which side should the main site navigation sidebar be displayed.", "admin.theme.sidebarPositionHint": "On which side should the main site navigation sidebar be displayed.",
"admin.theme.siteTheme": "Site Theme", "admin.theme.siteTheme": "Site Theme",
...@@ -1429,5 +1429,13 @@ ...@@ -1429,5 +1429,13 @@
"admin.general.footerExtraHint": "Optionally add more content to the footer, such as additional copyright terms or mandatory regulatory info.", "admin.general.footerExtraHint": "Optionally add more content to the footer, such as additional copyright terms or mandatory regulatory info.",
"admin.general.urlHandling": "URL Handling", "admin.general.urlHandling": "URL Handling",
"admin.general.pageExtensions": "Page Extensions", "admin.general.pageExtensions": "Page Extensions",
"admin.general.pageExtensionsHint": "A comma-separated list of URL extensions that will be treated as pages. For example, adding md will treat /foobar.md the same as /foobar." "admin.general.pageExtensionsHint": "A comma-separated list of URL extensions that will be treated as pages. For example, adding md will treat /foobar.md the same as /foobar.",
"admin.theme.appearance": "Appearance",
"admin.theme.fonts": "Fonts",
"admin.theme.baseFont": "Base Font",
"admin.theme.baseFontHint": "The font used across the site for the interface.",
"admin.theme.contentFont": "Content Font",
"admin.theme.contentFontHint": "The font used specifically for page content.",
"admin.theme.contentWidth": "Content Width",
"admin.theme.contentWidthHint": "Should the content use all available viewport space or stay centered."
} }
...@@ -6,7 +6,7 @@ q-layout.admin(view='hHh Lpr lff') ...@@ -6,7 +6,7 @@ q-layout.admin(view='hHh Lpr lff')
q-btn(dense, flat, href='/') q-btn(dense, flat, href='/')
q-avatar(size='34px', square) q-avatar(size='34px', square)
img(src='/_assets/logo-wikijs.svg') img(src='/_assets/logo-wikijs.svg')
q-toolbar-title.text-h6.font-poppins Wiki.js q-toolbar-title.text-h6 Wiki.js
q-toolbar.gt-sm.justify-center(style='height: 64px;', dark) q-toolbar.gt-sm.justify-center(style='height: 64px;', dark)
.text-overline.text-uppercase.text-grey {{t('admin.adminArea')}} .text-overline.text-uppercase.text-grey {{t('admin.adminArea')}}
q-badge.q-ml-sm( q-badge.q-ml-sm(
...@@ -267,10 +267,6 @@ watch(() => adminStore.currentSiteId, (newValue) => { ...@@ -267,10 +267,6 @@ watch(() => adminStore.currentSiteId, (newValue) => {
} }
}) })
setCssVar('primary', '#1976D2')
setCssVar('secondary', '#02C39A')
setCssVar('accent', '#f03a47')
// MOUNTED // MOUNTED
onMounted(async () => { onMounted(async () => {
......
...@@ -12,7 +12,6 @@ q-layout(view='hHh lpr lff') ...@@ -12,7 +12,6 @@ q-layout(view='hHh lpr lff')
.auth { .auth {
background-color: #FFF; background-color: #FFF;
display: flex; display: flex;
font-family: 'Rubik', sans-serif;
@at-root .body--dark & { @at-root .body--dark & {
background-color: $dark-6; background-color: $dark-6;
......
...@@ -9,7 +9,7 @@ q-layout(view='hHh Lpr lff') ...@@ -9,7 +9,7 @@ q-layout(view='hHh Lpr lff')
v-for='navItem of sidenav' v-for='navItem of sidenav'
:key='navItem.key' :key='navItem.key'
clickable clickable
:to='`/p/` + navItem.key' :to='`/_profile/` + navItem.key'
active-class='is-active' active-class='is-active'
v-ripple v-ripple
) )
...@@ -21,7 +21,7 @@ q-layout(view='hHh Lpr lff') ...@@ -21,7 +21,7 @@ q-layout(view='hHh Lpr lff')
q-item( q-item(
clickable clickable
v-ripple v-ripple
to='/p/me' to='/_profile/me'
) )
q-item-section(side) q-item-section(side)
q-icon(name='las la-id-card') q-icon(name='las la-id-card')
...@@ -42,67 +42,79 @@ q-layout(view='hHh Lpr lff') ...@@ -42,67 +42,79 @@ q-layout(view='hHh Lpr lff')
span(style='font-size: 11px;') &copy; Cyberdyne Systems Corp. 2020 | Powered by #[strong Wiki.js] span(style='font-size: 11px;') &copy; Cyberdyne Systems Corp. 2020 | Powered by #[strong Wiki.js]
</template> </template>
<script> <script setup>
import gql from 'graphql-tag'
import { useI18n } from 'vue-i18n'
import { useMeta, useQuasar } from 'quasar'
import { onMounted, reactive, watch } from 'vue'
import { useSiteStore } from 'src/stores/site'
import HeaderNav from '../components/HeaderNav.vue' import HeaderNav from '../components/HeaderNav.vue'
export default { // QUASAR
name: 'ProfileLayout',
components: { const $q = useQuasar()
HeaderNav
// STORES
const siteStore = useSiteStore()
// I18N
const { t } = useI18n()
// DATA
const sidenav = [
{
key: 'info',
label: 'Profile',
icon: 'las la-user-circle'
}, },
data () { {
return { key: 'avatar',
sidenav: [ label: 'Avatar',
{ icon: 'las la-otter'
key: 'profile', },
label: 'Profile', {
icon: 'las la-user-circle' key: 'password',
}, label: 'Password',
{ icon: 'las la-key'
key: 'avatar', },
label: 'Avatar', {
icon: 'las la-otter' key: 'groups',
}, label: 'Groups',
{ icon: 'las la-users'
key: 'password', },
label: 'Password', {
icon: 'las la-key' key: 'notifications',
}, label: 'Notifications',
{ icon: 'las la-bell'
key: 'groups', },
label: 'Groups', {
icon: 'las la-users' key: 'pages',
}, label: 'My Pages',
{ icon: 'las la-file-alt'
key: 'notifications', },
label: 'Notifications', {
icon: 'las la-bell' key: 'activity',
}, label: 'Activity',
{ icon: 'las la-history'
key: 'pages',
label: 'My Pages',
icon: 'las la-file-alt'
},
{
key: 'activity',
label: 'Activity',
icon: 'las la-history'
}
],
thumbStyle: {
right: '2px',
borderRadius: '5px',
backgroundColor: '#FFF',
width: '5px',
opacity: 0.5
},
barStyle: {
backgroundColor: '#000',
width: '9px',
opacity: 0.1
}
}
} }
]
const thumbStyle = {
right: '2px',
borderRadius: '5px',
backgroundColor: '#FFF',
width: '5px',
opacity: 0.5
}
const barStyle = {
backgroundColor: '#000',
width: '9px',
opacity: 0.1
} }
</script> </script>
......
...@@ -267,7 +267,7 @@ q-page.admin-general ...@@ -267,7 +267,7 @@ q-page.admin-general
src='https://m.media-amazon.com/images/G/01/audibleweb/arya/navigation/audible_logo._V517446980_.svg' src='https://m.media-amazon.com/images/G/01/audibleweb/arya/navigation/audible_logo._V517446980_.svg'
style='height: 34px;' style='height: 34px;'
) )
q-toolbar-title.text-h6.font-poppins(v-if='state.config.logoText') {{state.config.title}} q-toolbar-title.text-h6(v-if='state.config.logoText') {{state.config.title}}
q-separator.q-my-sm(inset) q-separator.q-my-sm(inset)
q-item(tag='label') q-item(tag='label')
blueprint-icon(icon='information') blueprint-icon(icon='information')
......
...@@ -38,7 +38,7 @@ q-page.admin-theme ...@@ -38,7 +38,7 @@ q-page.admin-theme
//- ----------------------- //- -----------------------
q-card.shadow-1.q-pb-sm q-card.shadow-1.q-pb-sm
q-card-section.flex.items-center q-card-section.flex.items-center
.text-subtitle1 {{t('admin.theme.options')}} .text-subtitle1 {{t('admin.theme.appearance')}}
q-space q-space
q-btn.acrylic-btn( q-btn.acrylic-btn(
icon='las la-redo-alt' icon='las la-redo-alt'
...@@ -94,6 +94,21 @@ q-page.admin-theme ...@@ -94,6 +94,21 @@ q-page.admin-theme
q-card-section q-card-section
.text-subtitle1 {{t('admin.theme.layout')}} .text-subtitle1 {{t('admin.theme.layout')}}
q-item q-item
blueprint-icon(icon='width')
q-item-section
q-item-label {{t(`admin.theme.contentWidth`)}}
q-item-label(caption) {{t(`admin.theme.contentWidthHint`)}}
q-item-section.col-auto
q-btn-toggle(
v-model='state.config.contentWidth'
push
glossy
no-caps
toggle-color='primary'
:options='widthOptions'
)
q-separator.q-my-sm(inset)
q-item
blueprint-icon(icon='right-navigation-toolbar') blueprint-icon(icon='right-navigation-toolbar')
q-item-section q-item-section
q-item-label {{t(`admin.theme.sidebarPosition`)}} q-item-label {{t(`admin.theme.sidebarPosition`)}}
...@@ -153,9 +168,55 @@ q-page.admin-theme ...@@ -153,9 +168,55 @@ q-page.admin-theme
.col-6 .col-6
//- ----------------------- //- -----------------------
//- Code Injection //- Fonts
//- ----------------------- //- -----------------------
q-card.shadow-1.q-pb-sm q-card.shadow-1.q-pb-sm
q-card-section.flex.items-center
.text-subtitle1 {{t('admin.theme.fonts')}}
q-space
q-btn.acrylic-btn(
icon='las la-redo-alt'
:label='t(`admin.theme.resetDefaults`)'
flat
size='sm'
color='pink'
@click='resetFonts'
)
q-item
blueprint-icon(icon='fonts-app')
q-item-section
q-item-label {{t(`admin.theme.baseFont`)}}
q-item-label(caption) {{t(`admin.theme.baseFontHint`)}}
q-item-section
q-select(
outlined
v-model='state.config.baseFont'
:options='fonts'
emit-value
map-options
dense
:aria-label='t(`admin.theme.baseFont`)'
)
q-item
blueprint-icon(icon='fonts-app')
q-item-section
q-item-label {{t(`admin.theme.contentFont`)}}
q-item-label(caption) {{t(`admin.theme.contentFontHint`)}}
q-item-section
q-select(
outlined
v-model='state.config.contentFont'
:options='fonts'
emit-value
map-options
dense
:aria-label='t(`admin.theme.contentFont`)'
)
//- -----------------------
//- Code Injection
//- -----------------------
q-card.shadow-1.q-pb-sm.q-mt-md
q-card-section q-card-section
.text-subtitle1 {{t('admin.theme.codeInjection')}} .text-subtitle1 {{t('admin.theme.codeInjection')}}
q-item q-item
...@@ -205,7 +266,7 @@ q-page.admin-theme ...@@ -205,7 +266,7 @@ q-page.admin-theme
import gql from 'graphql-tag' import gql from 'graphql-tag'
import { cloneDeep, startCase } from 'lodash-es' import { cloneDeep, startCase } from 'lodash-es'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useMeta, useQuasar } from 'quasar' import { setCssVar, useMeta, useQuasar } from 'quasar'
import { onMounted, reactive, watch } from 'vue' import { onMounted, reactive, watch } from 'vue'
import { useAdminStore } from 'src/stores/admin' import { useAdminStore } from 'src/stores/admin'
...@@ -246,10 +307,13 @@ const state = reactive({ ...@@ -246,10 +307,13 @@ const state = reactive({
colorAccent: '#f03a47', colorAccent: '#f03a47',
colorHeader: '#000', colorHeader: '#000',
colorSidebar: '#1976D2', colorSidebar: '#1976D2',
contentWidth: 'full',
sidebarPosition: 'left', sidebarPosition: 'left',
tocPosition: 'right', tocPosition: 'right',
showSharingMenu: true, showSharingMenu: true,
showPrintBtn: true showPrintBtn: true,
baseFont: '',
contentFont: ''
} }
}) })
...@@ -261,11 +325,27 @@ const colorKeys = [ ...@@ -261,11 +325,27 @@ const colorKeys = [
'sidebar' 'sidebar'
] ]
const widthOptions = [
{ label: 'Full Width', value: 'full' },
{ label: 'Centered', value: 'centered' }
]
const rightLeftOptions = [ const rightLeftOptions = [
{ label: 'Hide', value: 'off' },
{ label: 'Left', value: 'left' }, { label: 'Left', value: 'left' },
{ label: 'Right', value: 'right' } { label: 'Right', value: 'right' }
] ]
const fonts = [
{ label: 'Inter', value: 'inter' },
{ label: 'Open Sans', value: 'opensans' },
{ label: 'Montserrat', value: 'montserrat' },
{ label: 'Roboto', value: 'roboto' },
{ label: 'Rubik', value: 'rubik' },
{ label: 'Tajawal', value: 'tajawal' },
{ label: 'User System Defaults', value: 'user' }
]
// WATCHERS // WATCHERS
watch(() => adminStore.currentSiteId, (newValue) => { watch(() => adminStore.currentSiteId, (newValue) => {
...@@ -283,6 +363,11 @@ function resetColors () { ...@@ -283,6 +363,11 @@ function resetColors () {
state.config.colorSidebar = '#1976D2' state.config.colorSidebar = '#1976D2'
} }
function resetFonts () {
state.config.baseFont = 'roboto'
state.config.contentFont = 'roboto'
}
async function load () { async function load () {
state.loading++ state.loading++
$q.loading.show() $q.loading.show()
...@@ -296,15 +381,18 @@ async function load () { ...@@ -296,15 +381,18 @@ async function load () {
id: $id id: $id
) { ) {
theme { theme {
dark baseFont
contentFont
colorPrimary colorPrimary
colorSecondary colorSecondary
colorAccent colorAccent
colorHeader colorHeader
colorSidebar colorSidebar
dark
injectCSS injectCSS
injectHead injectHead
injectBody injectBody
contentWidth
sidebarPosition sidebarPosition
tocPosition tocPosition
showSharingMenu showSharingMenu
...@@ -345,10 +433,13 @@ async function save () { ...@@ -345,10 +433,13 @@ async function save () {
injectCSS: state.config.injectCSS, injectCSS: state.config.injectCSS,
injectHead: state.config.injectHead, injectHead: state.config.injectHead,
injectBody: state.config.injectBody, injectBody: state.config.injectBody,
contentWidth: state.config.contentWidth,
sidebarPosition: state.config.sidebarPosition, sidebarPosition: state.config.sidebarPosition,
tocPosition: state.config.tocPosition, tocPosition: state.config.tocPosition,
showSharingMenu: state.config.showSharingMenu, showSharingMenu: state.config.showSharingMenu,
showPrintBtn: state.config.showPrintBtn showPrintBtn: state.config.showPrintBtn,
baseFont: state.config.baseFont,
contentFont: state.config.contentFont
} }
const respRaw = await APOLLO_CLIENT.mutate({ const respRaw = await APOLLO_CLIENT.mutate({
mutation: gql` mutation: gql`
...@@ -381,6 +472,11 @@ async function save () { ...@@ -381,6 +472,11 @@ async function save () {
theme: patchTheme theme: patchTheme
}) })
$q.dark.set(state.config.dark) $q.dark.set(state.config.dark)
setCssVar('primary', state.config.colorPrimary)
setCssVar('secondary', state.config.colorSecondary)
setCssVar('accent', state.config.colorAccent)
setCssVar('header', state.config.colorHeader)
setCssVar('sidebar', state.config.colorSidebar)
} }
$q.notify({ $q.notify({
type: 'positive', type: 'positive',
......
...@@ -55,7 +55,7 @@ q-page.column ...@@ -55,7 +55,7 @@ q-page.column
q-input.no-height( q-input.no-height(
borderless borderless
v-model='title' v-model='title'
input-class='font-poppins text-h4 text-grey-9' input-class='text-h4 text-grey-9'
input-style='padding: 0;' input-style='padding: 0;'
placeholder='Untitled Page' placeholder='Untitled Page'
hide-hint hide-hint
...@@ -63,12 +63,12 @@ q-page.column ...@@ -63,12 +63,12 @@ q-page.column
q-input.no-height( q-input.no-height(
borderless borderless
v-model='description' v-model='description'
input-class='font-poppins text-subtitle2 text-grey-7' input-class='text-subtitle2 text-grey-7'
input-style='padding: 0;' input-style='padding: 0;'
placeholder='Enter a short description' placeholder='Enter a short description'
hide-hint hide-hint
) )
.col.q-pa-md.font-poppins(v-else) .col.q-pa-md(v-else)
.text-h4.page-header-title {{title}} .text-h4.page-header-title {{title}}
.text-subtitle2.page-header-subtitle {{description}} .text-subtitle2.page-header-subtitle {{description}}
......
...@@ -5,40 +5,40 @@ ...@@ -5,40 +5,40 @@
img(src='/_assets/logo-wikijs.svg' :alt='siteStore.title') img(src='/_assets/logo-wikijs.svg' :alt='siteStore.title')
h2.auth-site-title {{ siteStore.title }} h2.auth-site-title {{ siteStore.title }}
p.text-grey-7 Login to continue p.text-grey-7 Login to continue
template(v-if='state.strategies?.length > 1') template(v-if='state.strategies?.length > 1 || true')
p Sign in with p Sign in with
.auth-strategies .auth-strategies
q-btn( q-btn(
label='GitHub' label='GitHub'
icon='lab la-github' icon='lab la-github'
push push
no-caps no-caps
:color='$q.dark.isActive ? `blue-grey-9` : `grey-1`' :color='$q.dark.isActive ? `blue-grey-9` : `grey-1`'
:text-color='$q.dark.isActive ? `white` : `blue-grey-9`' :text-color='$q.dark.isActive ? `white` : `blue-grey-9`'
) )
q-btn( q-btn(
label='Google' label='Google'
icon='lab la-google-plus' icon='lab la-google-plus'
push push
no-caps no-caps
:color='$q.dark.isActive ? `blue-grey-9` : `grey-1`' :color='$q.dark.isActive ? `blue-grey-9` : `grey-1`'
:text-color='$q.dark.isActive ? `white` : `blue-grey-9`' :text-color='$q.dark.isActive ? `white` : `blue-grey-9`'
) )
q-btn( q-btn(
label='Twitter' label='Twitter'
icon='lab la-twitter' icon='lab la-twitter'
push push
no-caps no-caps
:color='$q.dark.isActive ? `blue-grey-9` : `grey-1`' :color='$q.dark.isActive ? `blue-grey-9` : `grey-1`'
:text-color='$q.dark.isActive ? `white` : `blue-grey-9`' :text-color='$q.dark.isActive ? `white` : `blue-grey-9`'
) )
q-btn( q-btn(
label='Local' label='Local'
icon='las la-seedling' icon='las la-seedling'
push push
color='primary' color='primary'
no-caps no-caps
) )
q-form.q-mt-md q-form.q-mt-md
q-input( q-input(
outlined outlined
...@@ -62,21 +62,22 @@ ...@@ -62,21 +62,22 @@
no-caps no-caps
icon='las la-sign-in-alt' icon='las la-sign-in-alt'
) )
q-separator.q-my-md template(v-if='true')
q-btn.acrylic-btn.full-width( q-separator.q-my-md
flat q-btn.acrylic-btn.full-width(
color='primary' flat
label='Create an Account' color='primary'
no-caps label='Create an Account'
icon='las la-user-plus' no-caps
) icon='las la-user-plus'
q-btn.acrylic-btn.full-width.q-mt-sm( )
flat q-btn.acrylic-btn.full-width.q-mt-sm(
color='primary' flat
label='Forgot Password' color='primary'
no-caps label='Forgot Password'
icon='las la-life-ring' no-caps
) icon='las la-life-ring'
)
.auth-bg(aria-hidden="true") .auth-bg(aria-hidden="true")
img(src='https://docs.requarks.io/_assets/img/splash/1.jpg' alt='') img(src='https://docs.requarks.io/_assets/img/splash/1.jpg' alt='')
</template> </template>
...@@ -189,9 +190,9 @@ async function fetchStrategies () { ...@@ -189,9 +190,9 @@ async function fetchStrategies () {
const resp = await APOLLO_CLIENT.query({ const resp = await APOLLO_CLIENT.query({
query: gql` query: gql`
query loginFetchSiteStrategies( query loginFetchSiteStrategies(
$siteId: UUID $siteId: UUID!
) { ) {
authStrategies( authSiteStrategies(
siteId: $siteId siteId: $siteId
enabledOnly: true enabledOnly: true
) { ) {
......
<template lang="pug"> <template lang="pug">
q-page.q-py-md(:style-fn='pageStyle') q-page.q-py-md(:style-fn='pageStyle')
.text-header {{$t('profile.myInfo')}} .text-header {{t('profile.myInfo')}}
q-item q-item
blueprint-icon(icon='contact') blueprint-icon(icon='contact')
q-item-section q-item-section
q-item-label {{$t(`profile.displayName`)}} q-item-label {{t(`profile.displayName`)}}
q-item-label(caption) {{$t(`profile.displayNameHint`)}} q-item-label(caption) {{t(`profile.displayNameHint`)}}
q-item-section q-item-section
q-input( q-input(
outlined outlined
v-model='config.name' v-model='state.config.name'
dense dense
hide-bottom-space hide-bottom-space
:aria-label='$t(`profile.displayName`)' :aria-label='t(`profile.displayName`)'
) )
q-separator.q-my-sm(inset) q-separator.q-my-sm(inset)
q-item q-item
blueprint-icon(icon='envelope') blueprint-icon(icon='envelope')
q-item-section q-item-section
q-item-label {{$t(`profile.email`)}} q-item-label {{t(`profile.email`)}}
q-item-label(caption) {{$t(`profile.emailHint`)}} q-item-label(caption) {{t(`profile.emailHint`)}}
q-item-section q-item-section
q-input( q-input(
outlined outlined
v-model='config.email' v-model='state.config.email'
dense dense
:aria-label='$t(`profile.email`)' :aria-label='t(`profile.email`)'
readonly readonly
) )
q-separator.q-my-sm(inset) q-separator.q-my-sm(inset)
q-item q-item
blueprint-icon(icon='address') blueprint-icon(icon='address')
q-item-section q-item-section
q-item-label {{$t(`profile.location`)}} q-item-label {{t(`profile.location`)}}
q-item-label(caption) {{$t(`profile.locationHint`)}} q-item-label(caption) {{t(`profile.locationHint`)}}
q-item-section q-item-section
q-input( q-input(
outlined outlined
v-model='config.location' v-model='state.config.location'
dense dense
hide-bottom-space hide-bottom-space
:aria-label='$t(`profile.location`)' :aria-label='t(`profile.location`)'
) )
q-separator.q-my-sm(inset) q-separator.q-my-sm(inset)
q-item q-item
blueprint-icon(icon='new-job') blueprint-icon(icon='new-job')
q-item-section q-item-section
q-item-label {{$t(`profile.jobTitle`)}} q-item-label {{t(`profile.jobTitle`)}}
q-item-label(caption) {{$t(`profile.jobTitleHint`)}} q-item-label(caption) {{t(`profile.jobTitleHint`)}}
q-item-section q-item-section
q-input( q-input(
outlined outlined
v-model='config.jobTitle' v-model='state.config.jobTitle'
dense dense
hide-bottom-space hide-bottom-space
:aria-label='$t(`profile.jobTitle`)' :aria-label='t(`profile.jobTitle`)'
) )
q-separator.q-my-sm(inset) q-separator.q-my-sm(inset)
q-item q-item
blueprint-icon(icon='gender') blueprint-icon(icon='gender')
q-item-section q-item-section
q-item-label {{$t(`profile.pronouns`)}} q-item-label {{t(`profile.pronouns`)}}
q-item-label(caption) {{$t(`profile.pronounsHint`)}} q-item-label(caption) {{t(`profile.pronounsHint`)}}
q-item-section q-item-section
q-input( q-input(
outlined outlined
v-model='config.pronouns' v-model='state.config.pronouns'
dense dense
hide-bottom-space hide-bottom-space
:aria-label='$t(`profile.pronouns`)' :aria-label='t(`profile.pronouns`)'
) )
.text-header.q-mt-lg {{$t('profile.preferences')}} .text-header.q-mt-lg {{t('profile.preferences')}}
q-item q-item
blueprint-icon(icon='timezone') blueprint-icon(icon='timezone')
q-item-section q-item-section
q-item-label {{$t(`profile.timezone`)}} q-item-label {{t(`profile.timezone`)}}
q-item-label(caption) {{$t(`profile.timezoneHint`)}} q-item-label(caption) {{t(`profile.timezoneHint`)}}
q-item-section q-item-section
q-select( q-select(
outlined outlined
v-model='config.timezone' v-model='state.config.timezone'
:options='timezones' :options='dataStore.timezones'
option-value='value' option-value='value'
option-label='text' option-label='text'
emit-value emit-value
map-options map-options
dense dense
options-dense options-dense
:aria-label='$t(`admin.general.defaultTimezone`)' :aria-label='t(`admin.general.defaultTimezone`)'
) )
q-separator.q-my-sm(inset) q-separator.q-my-sm(inset)
q-item q-item
blueprint-icon(icon='calendar') blueprint-icon(icon='calendar')
q-item-section q-item-section
q-item-label {{$t(`profile.dateFormat`)}} q-item-label {{t(`profile.dateFormat`)}}
q-item-label(caption) {{$t(`profile.dateFormatHint`)}} q-item-label(caption) {{t(`profile.dateFormatHint`)}}
q-item-section q-item-section
q-select( q-select(
outlined outlined
v-model='config.dateFormat' v-model='state.config.dateFormat'
emit-value emit-value
map-options map-options
dense dense
:aria-label='$t(`admin.general.defaultDateFormat`)' :aria-label='t(`admin.general.defaultDateFormat`)'
:options=`[ :options='dateFormats'
{ label: $t('profile.localeDefault'), value: '' },
{ label: 'DD/MM/YYYY', value: 'DD/MM/YYYY' },
{ label: 'DD.MM.YYYY', value: 'DD.MM.YYYY' },
{ label: 'MM/DD/YYYY', value: 'MM/DD/YYYY' },
{ label: 'YYYY-MM-DD', value: 'YYYY-MM-DD' },
{ label: 'YYYY/MM/DD', value: 'YYYY/MM/DD' }
]`
) )
q-separator.q-my-sm(inset) q-separator.q-my-sm(inset)
q-item q-item
blueprint-icon(icon='clock') blueprint-icon(icon='clock')
q-item-section q-item-section
q-item-label {{$t(`profile.timeFormat`)}} q-item-label {{t(`profile.timeFormat`)}}
q-item-label(caption) {{$t(`profile.timeFormatHint`)}} q-item-label(caption) {{t(`profile.timeFormatHint`)}}
q-item-section.col-auto q-item-section.col-auto
q-btn-toggle( q-btn-toggle(
v-model='config.timeFormat' v-model='state.config.timeFormat'
push push
glossy glossy
no-caps no-caps
toggle-color='primary' toggle-color='primary'
:options=`[ :options='timeFormats'
{ label: $t('admin.general.defaultTimeFormat12h'), value: '12h' },
{ label: $t('admin.general.defaultTimeFormat24h'), value: '24h' }
]`
) )
q-separator.q-my-sm(inset) q-separator.q-my-sm(inset)
q-item(tag='label', v-ripple) q-item(tag='label', v-ripple)
blueprint-icon(icon='light-on') blueprint-icon(icon='light-on')
q-item-section q-item-section
q-item-label {{$t(`profile.darkMode`)}} q-item-label {{t(`profile.darkMode`)}}
q-item-label(caption) {{$t(`profile.darkModeHint`)}} q-item-label(caption) {{t(`profile.darkModeHint`)}}
q-item-section(avatar) q-item-section(avatar)
q-toggle( q-toggle(
v-model='config.darkMode' v-model='state.config.darkMode'
color='primary' color='primary'
checked-icon='las la-check' checked-icon='las la-check'
unchecked-icon='las la-times' unchecked-icon='las la-times'
:aria-label='$t(`profile.darkMode`)' :aria-label='t(`profile.darkMode`)'
) )
.actions-bar.q-mt-lg .actions-bar.q-mt-lg
q-btn( q-btn(
icon='mdi-check' icon='las la-check'
unelevated unelevated
label='Save Changes' label='Save Changes'
color='secondary' color='secondary'
) )
</template> </template>
<script> <script setup>
import { get } from 'vuex-pathify' import gql from 'graphql-tag'
export default { import { useI18n } from 'vue-i18n'
data () { import { useMeta, useQuasar } from 'quasar'
return { import { onMounted, reactive, watch } from 'vue'
config: {
name: 'John Doe', import { useSiteStore } from 'src/stores/site'
email: 'john.doe@company.com', import { useDataStore } from 'src/stores/data'
location: '',
jobTitle: '', // QUASAR
pronouns: '',
dateFormat: '', const $q = useQuasar()
timeFormat: '12h',
darkMode: false // STORES
}
} const siteStore = useSiteStore()
}, const dataStore = useDataStore()
computed: {
timezones: get('data/timezones', false) // I18N
},
watch: { const { t } = useI18n()
'config.darkMode' (newValue) {
this.$q.dark.set(newValue) // META
}
}, useMeta({
methods: { title: t('profile.title')
pageStyle (offset, height) { })
return {
'min-height': `${height - 100 - offset}px` // DATA
}
} const state = reactive({
config: {
name: 'John Doe',
email: 'john.doe@company.com',
location: '',
jobTitle: '',
pronouns: '',
dateFormat: '',
timeFormat: '12h',
darkMode: false
}
})
const dateFormats = [
{ value: '', label: t('profile.localeDefault') },
{ value: 'DD/MM/YYYY', label: 'DD/MM/YYYY' },
{ value: 'DD.MM.YYYY', label: 'DD.MM.YYYY' },
{ value: 'MM/DD/YYYY', label: 'MM/DD/YYYY' },
{ value: 'YYYY-MM-DD', label: 'YYYY-MM-DD' },
{ value: 'YYYY/MM/DD', label: 'YYYY/MM/DD' }
]
const timeFormats = [
{ value: '12h', label: t('admin.general.defaultTimeFormat12h') },
{ value: '24h', label: t('admin.general.defaultTimeFormat24h') }
]
// METHODS
function pageStyle (offset, height) {
return {
'min-height': `${height - 100 - offset}px`
} }
} }
</script> </script>
...@@ -15,14 +15,14 @@ const routes = [ ...@@ -15,14 +15,14 @@ const routes = [
{ path: '', component: () => import('../pages/Login.vue') } { path: '', component: () => import('../pages/Login.vue') }
] ]
}, },
// { {
// path: '/p', path: '/_profile',
// component: () => import('../layouts/ProfileLayout.vue'), component: () => import('../layouts/ProfileLayout.vue'),
// children: [ children: [
// { path: '', redirect: '/p/profile' }, { path: '', redirect: '/_profile/info' },
// { path: 'profile', component: () => import('../pages/Profile.vue') } { path: 'info', component: () => import('../pages/Profile.vue') }
// ] ]
// }, },
{ {
path: '/_admin', path: '/_admin',
component: () => import('../layouts/AdminLayout.vue'), component: () => import('../layouts/AdminLayout.vue'),
......
...@@ -70,6 +70,20 @@ export const useSiteStore = defineStore('site', { ...@@ -70,6 +70,20 @@ export const useSiteStore = defineStore('site', {
logoText logoText
company company
contentLicense contentLicense
theme {
dark
colorPrimary
colorSecondary
colorAccent
colorHeader
colorSidebar
sidebarPosition
tocPosition
showSharingMenu
showPrintBtn
baseFont
contentFont
}
} }
} }
`, `,
...@@ -86,6 +100,10 @@ export const useSiteStore = defineStore('site', { ...@@ -86,6 +100,10 @@ export const useSiteStore = defineStore('site', {
this.logoUrl = clone(siteInfo.logoUrl) this.logoUrl = clone(siteInfo.logoUrl)
this.company = clone(siteInfo.company) this.company = clone(siteInfo.company)
this.contentLicense = clone(siteInfo.contentLicense) this.contentLicense = clone(siteInfo.contentLicense)
this.theme = {
...this.theme,
...clone(siteInfo.theme)
}
} else { } else {
throw new Error('Invalid Site') throw new Error('Invalid Site')
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment