Skip to content

Commit

Permalink
feat: ✨ gestion de la config console (System Settings)
Browse files Browse the repository at this point in the history
  • Loading branch information
KomsteRr authored and clairenollet committed Sep 17, 2024
1 parent cf7c52f commit 69c1236
Show file tree
Hide file tree
Showing 12 changed files with 293 additions and 72 deletions.
15 changes: 13 additions & 2 deletions apps/client/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script setup lang="ts">
import type { SystemSettings } from '@cpn-console/shared'
import { apiPrefix } from '@cpn-console/shared'
import { getKeycloak } from './utils/keycloak/keycloak.js'
import { useSnackbarStore } from './stores/snackbar.js'
Expand Down Expand Up @@ -38,21 +39,31 @@ watch(label, (label: string) => {
quickLinks.value[0].label = label
})
const systemSettings = ref<SystemSettings>()
const serviceStore = useServiceStore()
onBeforeMount(() => {
serviceStore.startHealthPolling()
serviceStore.checkServicesHealth()
systemStore.listSystemSettings()
systemSettings.value = systemStore.systemSettings
})
</script>

<template>
<DsfrHeader
<!-- <DsfrHeader
service-title="Console Cloud π Native"
:logo-text="['Ministère', 'de l’intérieur', 'et des outre-mer']"
:quick-links="quickLinks"
/> -->
<DsfrHeader
:service-title="systemSettings.appName"
:logo-text="systemSettings.appSubTitle"
:quick-links="quickLinks"
/>
<DsfrNotice
v-if="systemStore.systemSettingsByKey.maintenance?.value === 'on'"
v-if="systemStore.systemSettings?.maintenance === 'on'"
title="Le mode Maintenance est actuellement activé"
data-testid="maintenance-notice"
/>
Expand Down
2 changes: 1 addition & 1 deletion apps/client/src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ router.beforeEach(async (to, _from, next) => {
&& userStore.isLoggedIn
) {
await systemStore.listSystemSettings('maintenance')
if (systemStore.systemSettingsByKey.maintenance?.value === 'on' && userStore.adminPerms === 0n) return next('/maintenance')
if (systemStore.systemSettings?.maintenance === 'on' && userStore.adminPerms === 0n) return next('/maintenance')
}

next()
Expand Down
31 changes: 13 additions & 18 deletions apps/client/src/stores/system-settings.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,29 @@
import { defineStore } from 'pinia'
import {
type SystemSetting,
type SystemSettings,
type UpsertSystemSettingBody,
resourceListToDictByKey,
import type {
SystemSettings,
} from '@cpn-console/shared'
import { apiClient, extractData } from '@/api/xhr-client.js'

export const useSystemSettingsStore = defineStore('systemSettings', () => {
const systemSettings = ref<SystemSettings>([])
const systemSettingsByKey = computed(() => resourceListToDictByKey(systemSettings.value))
const systemSettings = ref<SystemSettings>()

const listSystemSettings = async (key?: SystemSetting['key']) => {
const listSystemSettings = async (key?: keyof SystemSettings) => {
systemSettings.value = await apiClient.SystemSettings.listSystemSettings({ query: { key } })
.then(response => extractData(response, 200))
}

const upsertSystemSetting = async (newSystemSetting: UpsertSystemSettingBody) => {
const res = await apiClient.SystemSettings.upsertSystemSetting({ body: newSystemSetting })
.then(response => extractData(response, 201))
systemSettings.value = systemSettings.value
.toSpliced(systemSettings.value
.findIndex(systemSetting => systemSetting.key === res.key), 1, res)
return res
}
// const upsertSystemSetting = async (newSystemSetting: UpsertSystemSettingBody) => {
// const res = await apiClient.SystemSettings.upsertSystemSetting({ body: newSystemSetting })
// .then(response => extractData(response, 201))
// systemSettings.value = systemSettings.value
// .toSpliced(systemSettings.value
// .findIndex(systemSetting => systemSetting.key === res.key), 1, res)
// return res
// }

return {
systemSettings,
systemSettingsByKey,
listSystemSettings,
upsertSystemSetting,
// upsertSystemSetting,
}
})
74 changes: 65 additions & 9 deletions apps/client/src/views/admin/SystemSettings.vue
Original file line number Diff line number Diff line change
@@ -1,29 +1,85 @@
<script lang="ts" setup>
import type { SystemSettings } from '@cpn-console/shared'
import { useSystemSettingsStore } from '@/stores/system-settings.js'
const systemStore = useSystemSettingsStore()
onBeforeMount(async () => {
const updated = ref<Record<string, Record<string, string>>>({})
// permet de definir quel input choisir ??
// function refTheValues(settings: SystemSetting[]) {
// return settings.map((setting) => {
// return {
// ...setting,
// // manifest ??
// }
// })
// }
const systemSettings = ref<SystemSettings>()
// reload les settings
async function reload() {
await systemStore.listSystemSettings()
systemSettings.value = systemStore.systemSettings
updated.value = {}
}
onBeforeMount(async () => {
// await systemStore.listSystemSettings()
reload()
})
// A modifié pour save les settings dynamiquement
async function upsertSystemSetting(key: string, value: boolean) {
await systemStore.upsertSystemSetting({ key, value: value ? 'on' : 'off' })
// await systemStore.upsertSystemSetting({ key, value: value ? 'on' : 'off' })
console.log(key + value)
}
</script>

<template>
<h1>Réglages de la console Cloud π Native</h1>
<div
class="flex <md:flex-col-reverse items-center justify-between gap-2 mt-8"
class="flex <md:flex-col items-center justify-between gap-2 mt-8"
>
<!-- {{ systemSettings }} -->
<DsfrToggleSwitch
v-for="setting in systemStore.systemSettings"
:key="setting.key"
:model-value="setting.value === 'on'"
:label="`${setting.value === 'on' ? 'Désactiver' : 'Activer'} le mode ${setting.key}`"
:data-testid="`toggle-${setting.key}`"
@update:model-value="(event: boolean) => upsertSystemSetting(setting.key, event)"
:model-value="systemSettings.maintenance === 'on'"
:label="`${systemSettings.maintenance === 'on' ? 'Désactiver' : 'Activer'} le mode maintenance`"
data-testid="toggle-maintenance"
@update:model-value="(event: boolean) => upsertSystemSetting('maintenance', event)"
/>
<DsfrInput
v-model="systemSettings.appName"
data-testid="input-appName"
label="appName"
label-visible
/>
<DsfrInput
v-model="systemSettings.contactMail"
data-testid="input-contactMail"
label="contactMail"
label-visible
/>
<DsfrInput
v-model="systemSettings.appSubTitle"
data-testid="input-appSubTitle"
label="appSubTitle"
label-visible
/>
</div>
</template>

<!-- <template>
<h1>Réglages de la console Cloud π Native</h1>
<div
v-if="!systemStore.systemSettings.length"
class="flex <md:flex-col-reverse items-center justify-between gap-2 mt-8"
>
<div> -->
<!-- trouvé comment faire du l'input dynamique -->
<!-- HINT : etablir des regle, ex : on|off => switch, sinon input classic -->
<!-- </div>
</div>
</template> -->
3 changes: 2 additions & 1 deletion apps/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@
"node-vault-client": "^1.0.1",
"prisma": "^5.16.1",
"undici": "^6.19.2",
"vitest-mock-extended": "^1.3.1"
"vitest-mock-extended": "^1.3.1",
"zod": "^3.23.8"
},
"devDependencies": {
"@cpn-console/eslint-config": "workspace:^",
Expand Down
20 changes: 13 additions & 7 deletions apps/server/src/resources/system/settings/business.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import type { UpsertSystemSettingBody } from '@cpn-console/shared'
import {
getSystemSettings as getSystemSettingsQuery,
upsertSystemSetting as upsertSystemSettingQuery,
} from './queries.js'
// import type { UpsertSystemSettingBody } from '@cpn-console/shared'

export const getSystemSettings = (key?: string) => getSystemSettingsQuery({ key })
import { config } from '@/utils/config.js'

export const upsertSystemSetting = (newSystemSetting: UpsertSystemSettingBody) => upsertSystemSettingQuery(newSystemSetting)
export function getSystemSettings(key?: keyof typeof config) {
// getSystemSettingsQuery({ key })

if (key) {
return { [key]: config[key] }
} else {
return config
}
}

// export const upsertSystemSetting = (newSystemSetting: UpsertSystemSettingBody) => upsertSystemSettingQuery(newSystemSetting)
32 changes: 18 additions & 14 deletions apps/server/src/resources/system/settings/router.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
import { AdminAuthorized, systemSettingsContract } from '@cpn-console/shared'
import { getSystemSettings, upsertSystemSetting } from './business.js'
import { systemSettingsContract } from '@cpn-console/shared'
import { getSystemSettings } from './business.js'
import { serverInstance } from '@/app.js'
import { authUser } from '@/utils/controller.js'
import { Forbidden403 } from '@/utils/errors.js'

export function systemSettingsRouter() {
return serverInstance.router(systemSettingsContract, {
listSystemSettings: async ({ query }) => {
const systemSettings = await getSystemSettings(query.key)

if (!systemSettings) {
return {
status: 500,
body: { error: 'System settings not found' },
}
}
return {
status: 200,
body: systemSettings,
}
},

upsertSystemSetting: async ({ request: req, body: data }) => {
const requestor = req.session.user
const perms = await authUser(requestor)
if (!AdminAuthorized.isAdmin(perms.adminPermissions)) return new Forbidden403()
// upsertSystemSetting: async ({ request: req, body: data }) => {
// const requestor = req.session.user
// const perms = await authUser(requestor)
// if (!AdminAuthorized.isAdmin(perms.adminPermissions)) return new Forbidden403()

const systemSetting = await upsertSystemSetting(data)
// const systemSetting = await upsertSystemSetting(data)

return {
status: 201,
body: systemSetting,
}
},
// return {
// status: 201,
// body: systemSetting,
// }
// },
})
}
Loading

0 comments on commit 69c1236

Please sign in to comment.