Skip to content

Commit

Permalink
refactor: work on vuetify theme init
Browse files Browse the repository at this point in the history
  • Loading branch information
albanm committed Nov 4, 2024
1 parent 5f17488 commit 2e4e276
Show file tree
Hide file tree
Showing 11 changed files with 89 additions and 67 deletions.
16 changes: 3 additions & 13 deletions api/config/custom-environment-variables.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -86,27 +86,17 @@ module.exports = {
theme: {
logo: 'THEME_LOGO',
favicon: 'THEME_FAVICON',
dark: 'THEME_DARK',
colors: {
background: 'THEME_BACKGROUND',
surface: 'THEME_SURFACE',
primary: 'THEME_PRIMARY',
secondary: 'THEME_SECONDARY',
accent: 'THEME_ACCENT',
error: 'THEME_ERROR',
info: 'THEME_INFO',
success: 'THEME_SUCCESS',
warning: 'THEME_WARNING'
},
darkColors: {
primary: 'THEME_DARK_PRIMARY',
secondary: 'THEME_DARK_SECONDARY',
accent: 'THEME_DARK_ACCENT',
error: 'THEME_DARK_ERROR',
info: 'THEME_DARK_INFO',
success: 'THEME_DARK_SUCCESS',
warning: 'THEME_DARK_WARNING'
},
cssUrl: 'THEME_CSS_URL',
cssText: 'THEME_CSS_TEXT'
}
},
i18n: {
defaultLocale: 'I18N_DEFAULT_LOCALE',
Expand Down
12 changes: 3 additions & 9 deletions api/config/default.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,10 @@ module.exports = {
analytics: {}, // a "modules" definition for @koumoul/vue-multianalytics
theme: {
logo: undefined,
favicon: undefined,
dark: false,
colors: {
// standard vuetify colors
background: '#FFFFFF',
surface: '#FFFFFF',
primary: '#1E88E5', // blue.darken1
secondary: '#42A5F5', // blue.lighten1,
accent: '#FF9800', // orange.base
Expand All @@ -134,13 +134,7 @@ module.exports = {
success: '#4CAF50', // green.base
warning: '#E91E63', // pink.base
admin: '#E53935' // red.darken1
},
darkColors: {
primary: '#2196F3', // blue.base
success: '#00E676' // green.accent3
},
cssUrl: undefined,
cssText: ''
}
},
i18n: {
defaultLocale: 'fr',
Expand Down
46 changes: 40 additions & 6 deletions api/config/type/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,16 +122,14 @@
},
"theme": {
"type": "object",
"required": [],
"required": ["colors"],
"properties": {
"logo": {
"type": "string"
},
"notificationIcon": {
"type": "string"
},
"notificationBadge": {
"type": "string"
"colors": {
"type": "object",
"$ref": "#/$defs/colors"
}
}
},
Expand Down Expand Up @@ -673,6 +671,42 @@
"type": "string"
}
}
},
"colors": {
"type": "object",
"required": ["background", "surface", "primary", "secondary", "accent", "error", "info", "success", "warning", "admin"],
"properties": {
"background": {
"type": "string"
},
"surface": {
"type": "string"
},
"primary": {
"type": "string"
},
"secondary": {
"type": "string"
},
"accent": {
"type": "string"
},
"error": {
"type": "string"
},
"info": {
"type": "string"
},
"success": {
"type": "string"
},
"warning": {
"type": "string"
},
"admin": {
"type": "string"
}
}
}
}
}
6 changes: 3 additions & 3 deletions api/src/invitations/router.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type UserWritable, type Invitation } from '#types'
import { type UserWritable, type Invitation, type ActionPayload, type ShortenedInvitation } from '#types'
import { Router } from 'express'
import config from '#config'
import { assertAccountRole, reqUser, reqSession, reqSiteUrl, session, httpError, reqUserAuthenticated } from '@data-fair/lib-express'
Expand Down Expand Up @@ -173,7 +173,7 @@ router.get('/_accept', async (req, res, next) => {
// if the token was once valid, but deprecated we accept it partially
// meaning that we will not perform writes based on it
// but we accept to check the user's existence and create the best redirect for him
invit = unshortenInvit(decodeToken(req.query.invit_token))
invit = unshortenInvit(decodeToken(req.query.invit_token) as ShortenedInvitation)
verified = false
}
debug('accept invitation', invit, verified)
Expand Down Expand Up @@ -206,7 +206,7 @@ router.get('/_accept', async (req, res, next) => {
throw new Error('missing password verification implementation')
} else {
if (!await storage.getPassword(invit.email) && !config.passwordless) {
const payload = { id: existingUser.id, email: existingUser.email, action: 'changePassword' }
const payload: ActionPayload = { id: existingUser.id, email: existingUser.email, action: 'changePassword' }
const token = await signToken(payload, config.jwtDurations.initialToken)
const reboundRedirect = redirectUrl.href
redirectUrl = new URL(`${reqSiteUrl(req) + '/simple-directory'}/login`)
Expand Down
31 changes: 18 additions & 13 deletions api/src/sites/router.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type SitePublic } from '#types'
import { Router, type Request } from 'express'
import config from '#config'
import { reqUser, reqUserAuthenticated, reqSiteUrl, httpError, reqSessionAuthenticated } from '@data-fair/lib-express'
import { reqUser, reqUserAuthenticated, reqSiteUrl, httpError, reqSessionAuthenticated, reqHost } from '@data-fair/lib-express'
import { nanoid } from 'nanoid'
import { findAllSites, findOwnerSites, patchSite, deleteSite } from './service.ts'
import { reqSite } from '#services'
Expand Down Expand Up @@ -63,17 +63,22 @@ router.delete('/:id', async (req, res, next) => {
router.get('/_public', async (req, res, next) => {
const site = await reqSite(req)
if (!site) {
// TODO: return information for main site too ?
return res.status(204).send()
}
const sitePublic: SitePublic = {
host: site.host,
theme: site.theme,
logo: site.logo || `${reqSiteUrl(req) + '/simple-directory'}/api/avatars/${site.owner.type}/${site.owner.id}/avatar.png`,
reducedPersonalInfoAtCreation: site.reducedPersonalInfoAtCreation,
tosMessage: site.tosMessage,
authMode: site.authMode ?? 'onlyBackOffice',
authOnlyOtherSite: site.authOnlyOtherSite
const sitePublic: SitePublic = {
main: true,
host: reqHost(req),
colors: config.theme.colors,
authMode: 'onlyLocal'
}
res.send(sitePublic)
} else {
const colors = { ...config.theme.colors }
if (site.theme?.primaryColor) colors.primary = site.theme?.primaryColor
const sitePublic: SitePublic = {
host: site.host,
logo: site.logo || `${reqSiteUrl(req) + '/simple-directory'}/api/avatars/${site.owner.type}/${site.owner.id}/avatar.png`,
colors,
authMode: site.authMode ?? 'onlyBackOffice'
}
res.send(sitePublic)
}
res.send(sitePublic)
})
2 changes: 1 addition & 1 deletion api/src/tokens/keys-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const start = async () => {
while (!stopped) {
if (await locks.acquire('signature-keys-rotation')) {
const signatureKeys = await getSignatureKeys()
if (dayjs().diff(dayjs(signatureKeys.lastUpdate), 'day') > 20) {
if (dayjs().diff(dayjs(signatureKeys.lastUpdate), 'day') > 30) {
rotatePromise = rotateKeys()
await rotatePromise
}
Expand Down
10 changes: 6 additions & 4 deletions api/types/site-public/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@
"additionalProperties":false,
"required":[
"host",
"theme",
"logo",
"colors",
"authMode"
],
"properties":{
"main": {
"type": "boolean"
},
"host": {
"$ref": "https://github.com/data-fair/simple-directory/site#/properties/host"
},
"theme": {
"$ref": "https://github.com/data-fair/simple-directory/site#/properties/theme"
"colors": {
"$ref": "https://github.com/data-fair/simple-directory/api/config#/$defs/colors"
},
"logo": {
"$ref": "https://github.com/data-fair/simple-directory/site#/properties/logo"
Expand Down
18 changes: 9 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
"lint-fix": "eslint --fix ."
},
"dependencies": {
"@data-fair/lib-vue": "^1.8.0",
"@data-fair/lib-vuetify": "^1.3.0",
"@data-fair/lib-vue": "^1.9.1",
"@data-fair/lib-vuetify": "^1.4.1",
"@intlify/unplugin-vue-i18n": "^5.2.0",
"@koumoul/v-iframe": "^2.4.4",
"@mdi/js": "^7.4.47",
Expand Down
4 changes: 2 additions & 2 deletions ui/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createRouter, createWebHistory } from 'vue-router'
import { routes } from 'vue-router/auto-routes'
import { createVuetify } from 'vuetify'
import { aliases, mdi } from 'vuetify/iconsets/mdi-svg'
import { defaultOptions } from '@data-fair/lib-vuetify'
import { vuetifySessionOptions } from '@data-fair/lib-vuetify'
import '@data-fair/lib-vuetify/default.scss'
import { createReactiveSearchParams } from '@data-fair/lib-vue/reactive-search-params.js'
import { createLocaleDayjs } from '@data-fair/lib-vue/locale-dayjs.js'
Expand All @@ -24,7 +24,7 @@ import 'iframe-resizer/js/iframeResizer.contentWindow.js'
const localeDayjs = createLocaleDayjs(session.state.lang)
const uiNotif = createUiNotif()
const vuetify = createVuetify({
...defaultOptions(reactiveSearchParams.state, session.state.dark),
...vuetifySessionOptions(session),
icons: { defaultSet: 'mdi', aliases, sets: { mdi, } }
})
const i18n = createI18n({ locale: session.state.lang, messages: $uiConfig.publicMessages })
Expand Down
7 changes: 2 additions & 5 deletions ui/src/store/style.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import tinycolor from 'tinycolor2'

const isDark = (color) => tinycolor(color).getLuminance() < 0.4
export const isDark = (color) => tinycolor(color).getLuminance() < 0.4

// calculate a variant of a color with guaranteed readability
// default background is #FAFAFA the light grey background
// TODO: deprecate this, instead we rely on warnings showed to admins when the colors they chose don't have a sufficient contrast
const contrastColorCache = {}
const contrastColor = (color1, color2 = '#FAFAFA', color3) => {
export const contrastColor = (color1, color2 = '#FAFAFA', color3) => {
if (!color1) return
const cacheKey = JSON.stringify([color1, color2, color3])
if (contrastColorCache[cacheKey]) return contrastColorCache[cacheKey]
Expand All @@ -28,9 +28,6 @@ export default () => ({
customPrimaryColor: null
},
getters: {
contrastColor () {
return (color1, color2, color3) => contrastColor(color1, color2, color2)
},
readablePrimaryColor (state, getters, rootState) {
return state.customPrimaryColor && contrastColor(state.customPrimaryColor)
},
Expand Down

0 comments on commit 2e4e276

Please sign in to comment.