Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wiki-js
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
wiki-js
Commits
72eccb7a
Unverified
Commit
72eccb7a
authored
Mar 06, 2023
by
Nicolas Giard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: accessibilty cvd option + editor page header
parent
0adb4dc3
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
365 additions
and
152 deletions
+365
-152
3.0.0.js
server/db/migrations/3.0.0.js
+4
-2
user.js
server/graph/resolvers/user.js
+2
-1
user.graphql
server/graph/schemas/user.graphql
+8
-0
ultraviolet-visualy-impaired.svg
ux/public/_assets/icons/ultraviolet-visualy-impaired.svg
+2
-0
App.vue
ux/src/App.vue
+11
-5
EditorMarkdown.vue
ux/src/components/EditorMarkdown.vue
+26
-10
PageHeader.vue
ux/src/components/PageHeader.vue
+234
-0
accessibility.js
ux/src/helpers/accessibility.js
+33
-0
en.json
ux/src/i18n/locales/en.json
+9
-1
MainLayout.vue
ux/src/layouts/MainLayout.vue
+1
-1
Index.vue
ux/src/pages/Index.vue
+2
-130
ProfileInfo.vue
ux/src/pages/ProfileInfo.vue
+27
-2
user.js
ux/src/stores/user.js
+6
-0
No files found.
server/db/migrations/3.0.0.js
View file @
72eccb7a
...
...
@@ -691,7 +691,8 @@ exports.up = async knex => {
timezone
:
'America/New_York'
,
dateFormat
:
'YYYY-MM-DD'
,
timeFormat
:
'12h'
,
appearance
:
'site'
appearance
:
'site'
,
cvd
:
'none'
},
localeCode
:
'en'
},
...
...
@@ -708,7 +709,8 @@ exports.up = async knex => {
timezone
:
'America/New_York'
,
dateFormat
:
'YYYY-MM-DD'
,
timeFormat
:
'12h'
,
appearance
:
'site'
appearance
:
'site'
,
cvd
:
'none'
},
localeCode
:
'en'
}
...
...
server/graph/resolvers/user.js
View file @
72eccb7a
...
...
@@ -229,7 +229,8 @@ module.exports = {
timezone
:
args
.
timezone
||
usr
.
prefs
.
timezone
,
dateFormat
:
args
.
dateFormat
??
usr
.
prefs
.
dateFormat
,
timeFormat
:
args
.
timeFormat
??
usr
.
prefs
.
timeFormat
,
appearance
:
args
.
appearance
||
usr
.
prefs
.
appearance
appearance
:
args
.
appearance
||
usr
.
prefs
.
appearance
,
cvd
:
args
.
cvd
||
usr
.
prefs
.
cvd
}
})
...
...
server/graph/schemas/user.graphql
View file @
72eccb7a
...
...
@@ -72,6 +72,7 @@ extend type Mutation {
dateFormat
:
String
timeFormat
:
String
appearance
:
UserSiteAppearance
cvd
:
UserCvdChoices
):
DefaultResponse
uploadUserAvatar
(
...
...
@@ -154,6 +155,13 @@ enum UserSiteAppearance {
dark
}
enum
UserCvdChoices
{
none
protanopia
deuteranopia
tritanopia
}
input
UserUpdateInput
{
email
:
String
name
:
String
...
...
ux/public/_assets/icons/ultraviolet-visualy-impaired.svg
0 → 100644
View file @
72eccb7a
<svg
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 40 40"
width=
"80px"
height=
"80px"
><path
fill=
"#fff"
d=
"M20,32.5C10.238,32.5,2.002,21.886,0.616,20C2.002,18.115,10.245,7.5,20,7.5 c9.762,0,17.998,10.614,19.384,12.5C37.998,21.885,29.755,32.5,20,32.5z"
/><path
fill=
"#4788c7"
d=
"M20,8c9.097,0,16.906,9.549,18.76,12C36.908,22.453,29.11,32,20,32c-9.097,0-16.906-9.549-18.76-12 C3.092,17.547,10.89,8,20,8 M20,7C8.954,7,0,20,0,20s8.954,13,20,13s20-13,20-13S31.046,7,20,7L20,7z"
/><path
fill=
"#98ccfd"
d=
"M25.994 26.701C27.835 25.053 29 22.665 29 20c0-4.971-4.029-9-9-9-2.665 0-5.053 1.165-6.701 3.006L25.994 26.701zM8.166 12.873L25.98 30.687c.329-.139.654-.284.974-.44l-17.99-17.99C8.693 12.46 8.428 12.666 8.166 12.873zM6.019 14.726l16.932 16.932c.378-.082.751-.182 1.123-.291L6.757 14.05C6.501 14.276 6.261 14.501 6.019 14.726zM4.707 16c-.242.247-.468.486-.69.724l15.228 15.228C19.497 31.966 19.746 32 20 32c.224 0 .443-.031.665-.042L4.707 16zM2.145 18.852l11.803 11.803c.713.305 1.442.564 2.187.773L2.791 18.084C2.557 18.357 2.341 18.614 2.145 18.852z"
/><path
fill=
"#4788c7"
d=
"M22.441,23.148C23.383,22.416,24,21.285,24,20c0-2.209-1.791-4-4-4c-1.285,0-2.416,0.617-3.148,1.559 L22.441,23.148z"
/><path
fill=
"#dff0fe"
d=
"M23 14A2 2 0 1 0 23 18A2 2 0 1 0 23 14Z"
/><path
fill=
"none"
stroke=
"#4788c7"
stroke-linecap=
"round"
stroke-miterlimit=
"10"
stroke-width=
"2"
d=
"M3 3L37 37"
/></svg>
\ No newline at end of file
ux/src/App.vue
View file @
72eccb7a
...
...
@@ -42,6 +42,10 @@ watch(() => userStore.appearance, (newValue) => {
}
})
watch
(()
=>
userStore
.
cvd
,
()
=>
{
applyTheme
()
})
// THEME
function
applyTheme
()
{
...
...
@@ -50,11 +54,13 @@ function applyTheme () {
}
else
{
$q
.
dark
.
set
(
userStore
.
appearance
===
'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
)
setCssVar
(
'primary'
,
userStore
.
getAccessibleColor
(
'primary'
,
siteStore
.
theme
.
colorPrimary
))
setCssVar
(
'secondary'
,
userStore
.
getAccessibleColor
(
'secondary'
,
siteStore
.
theme
.
colorSecondary
))
setCssVar
(
'accent'
,
userStore
.
getAccessibleColor
(
'accent'
,
siteStore
.
theme
.
colorAccent
))
setCssVar
(
'header'
,
userStore
.
getAccessibleColor
(
'header'
,
siteStore
.
theme
.
colorHeader
))
setCssVar
(
'sidebar'
,
userStore
.
getAccessibleColor
(
'sidebar'
,
siteStore
.
theme
.
colorSidebar
))
setCssVar
(
'positive'
,
userStore
.
getAccessibleColor
(
'positive'
,
'#02C39A'
))
setCssVar
(
'negative'
,
userStore
.
getAccessibleColor
(
'negative'
,
'#f03a47'
))
}
// INIT SITE STORE
...
...
ux/src/components/EditorMarkdown.vue
View file @
72eccb7a
...
...
@@ -41,7 +41,7 @@
flat
)
q-tooltip(anchor='center right' self='center left')
{{
t
(
'editor.markup.horizontalBar'
)
}}
.editor-markdown-
editor
.editor-markdown-
mid
//--------------------------------------------------------
//- TOP TOOLBAR
//--------------------------------------------------------
...
...
@@ -115,9 +115,11 @@
//--------------------------------------------------------
//- CODEMIRROR
//--------------------------------------------------------
textarea(ref='cmRef')
.editor-markdown-editor
textarea(ref='cmRef')
transition(name='editor-markdown-preview')
.editor-markdown-preview(v-if='state.previewShown')
.editor-markdown-preview-toolbar Render Preview
.editor-markdown-preview-content.contents(ref='editorPreviewContainer')
div(
ref='editorPreview'
...
...
@@ -126,7 +128,7 @@
</
template
>
<
script
setup
>
import
{
reactive
,
ref
,
shallowRef
,
onBeforeMount
,
onMounted
,
watch
}
from
'vue'
import
{
reactive
,
ref
,
shallowRef
,
nextTick
,
onBeforeMount
,
onMounted
,
watch
}
from
'vue'
import
{
useMeta
,
useQuasar
,
setCssVar
}
from
'quasar'
import
{
useI18n
}
from
'vue-i18n'
...
...
@@ -169,6 +171,7 @@ const cm = shallowRef(null)
const
cmRef
=
ref
(
null
)
const
state
=
reactive
({
content
:
''
,
previewShown
:
true
,
previewHTML
:
''
})
...
...
@@ -212,7 +215,7 @@ onMounted(async () => {
// onCmInput(editorStore.content)
})
cm
.
value
.
setSize
(
null
,
'
calc(100vh - 150px)
'
)
cm
.
value
.
setSize
(
null
,
'
100%
'
)
// -> Set Keybindings
const
keyBindings
=
{
...
...
@@ -263,7 +266,9 @@ onMounted(async () => {
// // Render initial preview
// this.processContent(this.$store.get('editor/content'))
// this.refresh()
nextTick
(()
=>
{
cm
.
value
.
refresh
()
})
// this.$root.$on('editorInsert', opts => {
// switch (opts.kind) {
...
...
@@ -306,7 +311,7 @@ onBeforeMount(() => {
</
script
>
<
style
lang=
"scss"
>
$editor-height
:
calc
(
100vh
-
112px
-
24
px
);
$editor-height
:
calc
(
100vh
-
64px
-
94px
-
2
px
);
$editor-height-mobile
:
calc
(
100vh
-
112px
-
16px
);
.editor-markdown
{
...
...
@@ -314,12 +319,17 @@ $editor-height-mobile: calc(100vh - 112px - 16px);
display
:
flex
;
width
:
100%
;
}
&
-
editor
{
&
-
mid
{
background-color
:
$dark-6
;
flex
:
1
1
50%
;
display
:
block
;
height
:
$editor-height
;
position
:
relative
;
}
&
-editor
{
display
:
block
;
height
:
calc
(
100%
-
32px
);
position
:
relative
;
// @include until($tablet) {
// height: $editor-height-mobile;
// }
...
...
@@ -330,8 +340,6 @@ $editor-height-mobile: calc(100vh - 112px - 16px);
position
:
relative
;
height
:
$editor-height
;
overflow
:
hidden
;
padding
:
1rem
;
border-top
:
32px
solid
$grey-3
;
@at-root
.theme--dark
&
{
background-color
:
$grey-9
;
...
...
@@ -350,10 +358,18 @@ $editor-height-mobile: calc(100vh - 112px - 16px);
&
-enter
,
&
-leave-to
{
max-width
:
0
;
}
&
-toolbar
{
background-color
:
$grey-3
;
color
:
$grey-8
;
height
:
32px
;
display
:
flex
;
align-items
:
center
;
padding
:
0
1rem
;
}
&
-content
{
height
:
$editor-height
;
overflow-y
:
scroll
;
padding
:
0
;
padding
:
1rem
;
width
:
calc
(
100%
+
17px
);
// -ms-overflow-style: none;
// &::-webkit-scrollbar {
...
...
ux/src/components/PageHeader.vue
0 → 100644
View file @
72eccb7a
<
template
lang=
"pug"
>
.page-header.row
//- PAGE ICON
.col-auto.q-pl-md.flex.items-center
q-btn.rounded-borders(
v-if='editorStore.isActive'
padding='none'
size='37px'
:icon='pageStore.icon'
color='primary'
flat
)
q-menu(content-class='shadow-7')
icon-picker-dialog(v-model='pageStore.icon')
q-icon.rounded-borders(
v-else
:name='pageStore.icon'
size='64px'
color='primary'
)
//- PAGE HEADER
.col.q-pa-md
.text-h4.page-header-title
span
{{
pageStore
.
title
}}
template(v-if='editorStore.isActive')
span.text-grey(v-if='!pageStore.title')
{{
t
(
`editor.props.title`
)
}}
q-btn.acrylic-btn.q-ml-md(
icon='las la-pen'
flat
padding='xs'
size='sm'
)
q-popup-edit(
v-model='pageStore.title'
auto-save
v-slot='scope'
)
q-input(
outlined
style='width: 450px;'
v-model='scope.value'
dense
autofocus
@keyup.enter='scope.set'
:label='t(`editor.props.title`)'
)
.text-subtitle2.page-header-subtitle
span
{{
pageStore
.
description
}}
template(v-if='editorStore.isActive')
span.text-grey(v-if='!pageStore.description')
{{
t
(
`editor.props.shortDescription`
)
}}
q-btn.acrylic-btn.q-ml-md(
icon='las la-pen'
flat
padding='none xs'
size='xs'
)
q-popup-edit(
v-model='pageStore.description'
auto-save
v-slot='scope'
)
q-input(
outlined
style='width: 450px;'
v-model='scope.value'
dense
autofocus
@keyup.enter='scope.set'
:label='t(`editor.props.shortDescription`)'
)
//- PAGE ACTIONS
.col-auto.q-pa-md.flex.items-center.justify-end
template(v-if='!editorStore.isActive')
q-btn.q-mr-md(
flat
dense
icon='las la-bell'
color='grey'
aria-label='Watch Page'
)
q-tooltip Watch Page
q-btn.q-mr-md(
flat
dense
icon='las la-bookmark'
color='grey'
aria-label='Bookmark Page'
)
q-tooltip Bookmark Page
q-btn.q-mr-md(
flat
dense
icon='las la-share-alt'
color='grey'
aria-label='Share'
)
q-tooltip Share
social-sharing-menu
q-btn.q-mr-md(
flat
dense
icon='las la-print'
color='grey'
aria-label='Print'
)
q-tooltip Print
template(v-if='editorStore.isActive || editorStore.hasPendingChanges')
q-btn.acrylic-btn.q-mr-sm(
flat
icon='las la-times'
color='negative'
label='Discard'
aria-label='Discard'
no-caps
@click='discardChanges'
)
q-btn.acrylic-btn(
flat
icon='las la-check'
color='positive'
label='Save Changes'
aria-label='Save Changes'
no-caps
@click='saveChanges'
)
template(v-else)
q-btn.acrylic-btn(
flat
icon='las la-edit'
color='deep-orange-9'
label='Edit'
aria-label='Edit'
no-caps
@click='editPage'
)
</
template
>
<
script
setup
>
import
{
useQuasar
}
from
'quasar'
import
{
computed
,
defineAsyncComponent
,
onMounted
,
reactive
,
ref
,
watch
}
from
'vue'
import
{
useRouter
,
useRoute
}
from
'vue-router'
import
{
useI18n
}
from
'vue-i18n'
import
{
useEditorStore
}
from
'src/stores/editor'
import
{
useFlagsStore
}
from
'src/stores/flags'
import
{
usePageStore
}
from
'src/stores/page'
import
{
useSiteStore
}
from
'src/stores/site'
import
{
useUserStore
}
from
'src/stores/user'
import
IconPickerDialog
from
'src/components/IconPickerDialog.vue'
import
SocialSharingMenu
from
'src/components/SocialSharingMenu.vue'
// QUASAR
const
$q
=
useQuasar
()
// STORES
const
editorStore
=
useEditorStore
()
const
flagsStore
=
useFlagsStore
()
const
pageStore
=
usePageStore
()
const
siteStore
=
useSiteStore
()
const
userStore
=
useUserStore
()
// ROUTER
const
router
=
useRouter
()
const
route
=
useRoute
()
// I18N
const
{
t
}
=
useI18n
()
// COMPUTED
const
editMode
=
computed
(()
=>
{
return
pageStore
.
mode
===
'edit'
})
const
editCreateMode
=
computed
(()
=>
{
return
pageStore
.
mode
===
'edit'
&&
pageStore
.
mode
===
'create'
})
const
editUrl
=
computed
(()
=>
{
let
pagePath
=
siteStore
.
useLocales
?
`
${
pageStore
.
locale
}
/`
:
''
pagePath
+=
!
pageStore
.
path
?
'home'
:
pageStore
.
path
return
`/_edit/
${
pagePath
}
`
})
// METHODS
async
function
discardChanges
()
{
$q
.
loading
.
show
()
try
{
editorStore
.
$patch
({
isActive
:
false
,
editor
:
''
})
await
pageStore
.
pageLoad
({
id
:
pageStore
.
id
})
$q
.
notify
({
type
:
'positive'
,
message
:
'Page has been reverted to the last saved state.'
})
}
catch
(
err
)
{
$q
.
notify
({
type
:
'negative'
,
message
:
'Failed to reload page state.'
})
}
$q
.
loading
.
hide
()
}
async
function
saveChanges
()
{
$q
.
loading
.
show
()
try
{
await
pageStore
.
pageSave
()
$q
.
notify
({
type
:
'positive'
,
message
:
'Page saved successfully.'
})
}
catch
(
err
)
{
$q
.
notify
({
type
:
'negative'
,
message
:
'Failed to save page changes.'
})
}
$q
.
loading
.
hide
()
}
function
editPage
()
{
editorStore
.
$patch
({
isActive
:
true
,
editor
:
'markdown'
})
}
</
script
>
ux/src/helpers/accessibility.js
0 → 100644
View file @
72eccb7a
const
protanopia
=
{
negative
:
'#fb8c00'
,
positive
:
'#2196f3'
,
primary
:
'#1976D2'
,
secondary
:
'#2196f3'
}
const
deuteranopia
=
{
negative
:
'#ef6c00'
,
positive
:
'#2196f3'
,
primary
:
'#1976D2'
,
secondary
:
'#2196f3'
}
const
tritanopia
=
{
primary
:
'#e91e63'
,
secondary
:
'#02C39A'
}
export
function
getAccessibleColor
(
name
,
base
,
cvd
)
{
switch
(
cvd
)
{
case
'protanopia'
:
{
return
protanopia
[
name
]
??
base
}
case
'deuteranopia'
:
{
return
deuteranopia
[
name
]
??
base
}
case
'tritanopia'
:
{
return
tritanopia
[
name
]
??
base
}
}
return
base
}
ux/src/i18n/locales/en.json
View file @
72eccb7a
...
...
@@ -1708,5 +1708,13 @@
"admin.editors.markdown.quotesHint"
:
"When typographer is enabled. Double + single quotes replacement pairs. e.g. «»„“ for Russian, „“‚‘ for German, etc."
,
"admin.editors.saveSuccess"
:
"Editors state saved successfully."
,
"admin.editors.markdown.saveSuccess"
:
"Markdown editor configuration saved successfully."
,
"editor.markup.insertTable"
:
"Insert Table"
"editor.markup.insertTable"
:
"Insert Table"
,
"editor.markup.header"
:
"Header"
,
"profile.cvdHint"
:
"Alter the color scheme of certain UI elements to account for certain color vision dificiencies."
,
"profile.cvd"
:
"Color Vision Deficiency"
,
"profile.cvdNone"
:
"None"
,
"profile.cvdProtanopia"
:
"Protanopia"
,
"profile.cvdTritanopia"
:
"Tritanopia"
,
"profile.cvdDeuteranopia"
:
"Deuteranopia"
,
"profile.accessibility"
:
"Accessibility"
}
ux/src/layouts/MainLayout.vue
View file @
72eccb7a
...
...
@@ -78,7 +78,7 @@ q-layout(view='hHh Lpr lff')
size='md'
)
main-overlay-dialog
footer-nav
footer-nav
(v-if='!editorStore.isActive')
</
template
>
<
script
setup
>
...
...
ux/src/pages/Index.vue
View file @
72eccb7a
...
...
@@ -27,83 +27,7 @@ q-page.column
.text-caption.text-accent: strong Unpublished
q-separator.q-mx-sm(vertical)
.text-caption.text-grey-6 Last modified on #[strong
{{
lastModified
}}
]
.page-header.row
//- PAGE ICON
.col-auto.q-pl-md.flex.items-center
q-icon.rounded-borders(
:name='pageStore.icon'
size='64px'
color='primary'
)
//- PAGE HEADER
.col.q-pa-md
.text-h4.page-header-title
{{
pageStore
.
title
}}
.text-subtitle2.page-header-subtitle
{{
pageStore
.
description
}}
//- PAGE ACTIONS
.col-auto.q-pa-md.flex.items-center.justify-end
q-btn.q-mr-md(
flat
dense
icon='las la-bell'
color='grey'
aria-label='Watch Page'
)
q-tooltip Watch Page
q-btn.q-mr-md(
flat
dense
icon='las la-bookmark'
color='grey'
aria-label='Bookmark Page'
)
q-tooltip Bookmark Page
q-btn.q-mr-md(
flat
dense
icon='las la-share-alt'
color='grey'
aria-label='Share'
)
q-tooltip Share
social-sharing-menu
q-btn.q-mr-md(
flat
dense
icon='las la-print'
color='grey'
aria-label='Print'
)
q-tooltip Print
template(v-if='editorStore.hasPendingChanges')
q-btn.acrylic-btn.q-mr-sm(
flat
icon='las la-times'
color='negative'
label='Discard'
aria-label='Discard'
no-caps
@click='discardChanges'
)
q-btn.acrylic-btn(
flat
icon='las la-check'
color='positive'
label='Save Changes'
aria-label='Save Changes'
no-caps
@click='saveChanges'
)
template(v-else)
q-btn.acrylic-btn(
flat
icon='las la-edit'
color='deep-orange-9'
label='Edit'
aria-label='Edit'
no-caps
@click='editPage'
)
page-header
.page-container.row.no-wrap.items-stretch(style='flex: 1 1 100%;')
.col(style='order: 1;')
q-no-ssr(
...
...
@@ -336,8 +260,8 @@ import { useSiteStore } from 'src/stores/site'
// COMPONENTS
import
SocialSharingMenu
from
'../components/SocialSharingMenu.vue'
import
LoadingGeneric
from
'src/components/LoadingGeneric.vue'
import
PageHeader
from
'src/components/PageHeader.vue'
import
PageTags
from
'../components/PageTags.vue'
const
sideDialogs
=
{
...
...
@@ -428,17 +352,6 @@ const relationsCenter = computed(() => {
const
relationsRight
=
computed
(()
=>
{
return
pageStore
.
relations
?
pageStore
.
relations
.
filter
(
r
=>
r
.
position
===
'right'
)
:
[]
})
const
editMode
=
computed
(()
=>
{
return
pageStore
.
mode
===
'edit'
})
const
editCreateMode
=
computed
(()
=>
{
return
pageStore
.
mode
===
'edit'
&&
pageStore
.
mode
===
'create'
})
const
editUrl
=
computed
(()
=>
{
let
pagePath
=
siteStore
.
useLocales
?
`
${
pageStore
.
locale
}
/`
:
''
pagePath
+=
!
pageStore
.
path
?
'home'
:
pageStore
.
path
return
`/_edit/
${
pagePath
}
`
})
const
lastModified
=
computed
(()
=>
{
return
pageStore
.
updatedAt
?
DateTime
.
fromISO
(
pageStore
.
updatedAt
).
toLocaleString
(
DateTime
.
DATETIME_MED
)
:
'N/A'
})
...
...
@@ -545,47 +458,6 @@ function refreshTocExpanded (baseToc, lvl) {
return
toExpand
}
}
async
function
discardChanges
()
{
$q
.
loading
.
show
()
try
{
await
pageStore
.
pageLoad
({
id
:
pageStore
.
id
})
$q
.
notify
({
type
:
'positive'
,
message
:
'Page has been reverted to the last saved state.'
})
}
catch
(
err
)
{
$q
.
notify
({
type
:
'negative'
,
message
:
'Failed to reload page state.'
})
}
$q
.
loading
.
hide
()
}
async
function
saveChanges
()
{
$q
.
loading
.
show
()
try
{
await
pageStore
.
pageSave
()
$q
.
notify
({
type
:
'positive'
,
message
:
'Page saved successfully.'
})
}
catch
(
err
)
{
$q
.
notify
({
type
:
'negative'
,
message
:
'Failed to save page changes.'
})
}
$q
.
loading
.
hide
()
}
function
editPage
()
{
editorStore
.
$patch
({
isActive
:
true
,
editor
:
'markdown'
})
}
</
script
>
<
style
lang=
"scss"
>
...
...
ux/src/pages/ProfileInfo.vue
View file @
72eccb7a
...
...
@@ -134,6 +134,21 @@ q-page.q-py-md(:style-fn='pageStyle')
toggle-color='primary'
:options='appearances'
)
.text-header.q-mt-lg
{{
t
(
'profile.accessibility'
)
}}
q-item
blueprint-icon(icon='visualy-impaired')
q-item-section
q-item-label
{{
t
(
`profile.cvd`
)
}}
q-item-label(caption)
{{
t
(
`profile.cvdHint`
)
}}
q-item-section.col-auto
q-btn-toggle(
v-model='state.config.cvd'
push
glossy
no-caps
toggle-color='primary'
:options='cvdChoices'
)
.actions-bar.q-mt-lg
q-btn(
icon='las la-check'
...
...
@@ -149,7 +164,7 @@ import gql from 'graphql-tag'
import
{
useI18n
}
from
'vue-i18n'
import
{
useMeta
,
useQuasar
}
from
'quasar'
import
{
onMounted
,
reactive
,
watch
}
from
'vue'
import
{
onMounted
,
reactive
}
from
'vue'
import
{
useSiteStore
}
from
'src/stores/site'
import
{
useUserStore
}
from
'src/stores/user'
...
...
@@ -185,7 +200,8 @@ const state = reactive({
timezone
:
''
,
dateFormat
:
''
,
timeFormat
:
'12h'
,
appearance
:
'site'
appearance
:
'site'
,
cvd
:
'none'
}
})
...
...
@@ -206,6 +222,12 @@ const appearances = [
{
value
:
'light'
,
label
:
t
(
'profile.appearanceLight'
)
},
{
value
:
'dark'
,
label
:
t
(
'profile.appearanceDark'
)
}
]
const
cvdChoices
=
[
{
value
:
'none'
,
label
:
t
(
'profile.cvdNone'
)
},
{
value
:
'protanopia'
,
label
:
t
(
'profile.cvdProtanopia'
)
},
{
value
:
'deuteranopia'
,
label
:
t
(
'profile.cvdDeuteranopia'
)
},
{
value
:
'tritanopia'
,
label
:
t
(
'profile.cvdTritanopia'
)
}
]
const
timezones
=
Intl
.
supportedValuesOf
(
'timeZone'
)
// METHODS
...
...
@@ -232,6 +254,7 @@ async function save () {
$dateFormat: String
$timeFormat: String
$appearance: UserSiteAppearance
$cvd: UserCvdChoices
) {
updateProfile (
name: $name
...
...
@@ -242,6 +265,7 @@ async function save () {
dateFormat: $dateFormat
timeFormat: $timeFormat
appearance: $appearance
cvd: $cvd
) {
operation {
succeeded
...
...
@@ -283,5 +307,6 @@ onMounted(() => {
state
.
config
.
dateFormat
=
userStore
.
dateFormat
||
''
state
.
config
.
timeFormat
=
userStore
.
timeFormat
||
'12h'
state
.
config
.
appearance
=
userStore
.
appearance
||
'site'
state
.
config
.
cvd
=
userStore
.
cvd
||
'none'
})
</
script
>
ux/src/stores/user.js
View file @
72eccb7a
...
...
@@ -3,6 +3,7 @@ import jwtDecode from 'jwt-decode'
import
Cookies
from
'js-cookie'
import
gql
from
'graphql-tag'
import
{
DateTime
}
from
'luxon'
import
{
getAccessibleColor
}
from
'src/helpers/accessibility'
export
const
useUserStore
=
defineStore
(
'user'
,
{
state
:
()
=>
({
...
...
@@ -15,6 +16,7 @@ export const useUserStore = defineStore('user', {
dateFormat
:
'YYYY-MM-DD'
,
timeFormat
:
'12h'
,
appearance
:
'site'
,
cvd
:
'none'
,
permissions
:
[],
iat
:
0
,
exp
:
null
,
...
...
@@ -87,10 +89,14 @@ export const useUserStore = defineStore('user', {
this
.
dateFormat
=
resp
.
prefs
.
dateFormat
||
''
this
.
timeFormat
=
resp
.
prefs
.
timeFormat
||
'12h'
this
.
appearance
=
resp
.
prefs
.
appearance
||
'site'
this
.
cvd
=
resp
.
prefs
.
cvd
||
'none'
this
.
profileLoaded
=
true
}
catch
(
err
)
{
console
.
warn
(
err
)
}
},
getAccessibleColor
(
base
,
hexBase
)
{
return
getAccessibleColor
(
base
,
hexBase
,
this
.
cvd
)
}
}
})
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment