From 8bc7de92e8bf6d9f98a48493ec885b9241552495 Mon Sep 17 00:00:00 2001 From: davwas Date: Thu, 7 Sep 2023 13:47:04 +0200 Subject: [PATCH 01/20] add new feature flag --- src/store/env-config.ts | 4 ++++ src/store/types/env-config.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/src/store/env-config.ts b/src/store/env-config.ts index fdc6a3cd7b..6670afca2a 100644 --- a/src/store/env-config.ts +++ b/src/store/env-config.ts @@ -127,6 +127,10 @@ export default class EnvConfigModule extends VuexModule { return this.env.FEATURE_SCHOOL_POLICY_ENABLED_NEW; } + get getSchoolTermsOfUseEnabled() { + return this.env.FEATURE_SCHOOL_TERMS_OF_USE_ENABLED; + } + get getLoginLinkEnabled() { return this.env.FEATURE_LOGIN_LINK_ENABLED; } diff --git a/src/store/types/env-config.ts b/src/store/types/env-config.ts index bc090c3300..3ec0837b4f 100644 --- a/src/store/types/env-config.ts +++ b/src/store/types/env-config.ts @@ -17,6 +17,7 @@ export type Envs = { FEATURE_LESSON_SHARE?: boolean; FEATURE_LOGIN_LINK_ENABLED?: boolean; FEATURE_SCHOOL_POLICY_ENABLED_NEW?: boolean; + FEATURE_SCHOOL_TERMS_OF_USE_ENABLED?: boolean; FEATURE_SCHOOL_SANIS_USER_MIGRATION_ENABLED?: boolean; FEATURE_TEAMS_ENABLED?: boolean; FEATURE_USER_MIGRATION_ENABLED?: boolean; From 13d34b4efd2f6eced5bfdb109458143df3ddb1af Mon Sep 17 00:00:00 2001 From: davwas Date: Thu, 7 Sep 2023 16:36:14 +0200 Subject: [PATCH 02/20] remove unused component --- .../SchoolPolicyExpansionPanel.vue | 67 ------------------- 1 file changed, 67 deletions(-) delete mode 100644 src/components/molecules/administration/SchoolPolicyExpansionPanel.vue diff --git a/src/components/molecules/administration/SchoolPolicyExpansionPanel.vue b/src/components/molecules/administration/SchoolPolicyExpansionPanel.vue deleted file mode 100644 index 309c84aeea..0000000000 --- a/src/components/molecules/administration/SchoolPolicyExpansionPanel.vue +++ /dev/null @@ -1,67 +0,0 @@ - - - - - From e88d7aa1736af0b168e6d58a0aaa33d5b51fe568 Mon Sep 17 00:00:00 2001 From: davwas Date: Thu, 7 Sep 2023 16:36:40 +0200 Subject: [PATCH 03/20] add new translations --- src/locales/de.json | 15 +++++++++++++++ src/locales/en.json | 23 +++++++++++++++++++---- src/locales/es.json | 27 +++++++++++++++++++++------ src/locales/uk.json | 15 +++++++++++++++ 4 files changed, 70 insertions(+), 10 deletions(-) diff --git a/src/locales/de.json b/src/locales/de.json index dfd270aa00..fccf8fc5c8 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -115,6 +115,7 @@ "common.words.lernstore": "Lern-Store", "common.words.planned": "geplant", "common.words.privacyPolicy": "Datenschutzerklärung", + "common.words.termsOfUse": "Nutzungsordnung", "common.words.published": "veröffentlicht", "common.words.ready": "bereit", "common.words.schoolYear": "Schuljahr", @@ -703,6 +704,20 @@ "pages.administration.school.index.schoolPolicy.longText.willReplaceAndSendConsent": "Die neue Datenschutzerklärung wird die alte unwiderruflich ersetzen und allen Nutzern dieser Schule zur Genehmigung vorgelegt werden.", "pages.administration.school.index.schoolPolicy.edit": "Datenschutzerklärung bearbeiten", "pages.administration.school.index.schoolPolicy.download": "Datenschutzerklärung herunterladen", + "pages.administration.school.index.termsOfUse.labels.uploadFile": "Datei auswählen", + "pages.administration.school.index.termsOfUse.hints.uploadFile": "Datei hochladen (nur PDF, max. 4MB)", + "pages.administration.school.index.termsOfUse.validation.fileTooBig": "Die Datei ist größer als 4MB. Bitte reduzieren sie die Dateigröße", + "pages.administration.school.index.termsOfUse.validation.notPdf": "Dieses Dateiformat wird nicht unterstützt. Verwenden Sie bitte PDF", + "pages.administration.school.index.termsOfUse.error": "Beim Laden der Nutzungsordnung ist ein Fehler aufgetreten", + "pages.administration.school.index.termsOfUse.success": "Neue Datei wurde erfolgreich hochgeladen.", + "pages.administration.school.index.termsOfUse.replace": "Ersetzen", + "pages.administration.school.index.termsOfUse.cancel": "Abbrechen", + "pages.administration.school.index.termsOfUse.uploadedOn": "Hochgeladen am {date}", + "pages.administration.school.index.termsOfUse.notUploadedYet": "Noch nicht hochgeladen", + "pages.administration.school.index.termsOfUse.fileName": "Nutzungsordnung der Schule", + "pages.administration.school.index.termsOfUse.longText.willReplaceAndSendConsent": "Die neue Nutzungsordnung wird die alte unwiderruflich ersetzen und allen Nutzern dieser Schule zur Genehmigung vorgelegt werden.", + "pages.administration.school.index.termsOfUse.edit": "Nutzungsordnung bearbeiten", + "pages.administration.school.index.termsOfUse.download": "Nutzungsordnung herunterladen", "pages.administration.school.index.authSystems.title": "Authentifizierung", "pages.administration.school.index.authSystems.alias": "Alias", "pages.administration.school.index.authSystems.type": "Typ", diff --git a/src/locales/en.json b/src/locales/en.json index 02c8bfe960..2322956ace 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -114,6 +114,7 @@ "common.words.lernstore": "Learning Store", "common.words.planned": "planned", "common.words.privacyPolicy": "Privacy Policy", + "common.words.termsOfUse": "Terms of Use", "common.words.published": "published", "common.words.ready": "ready", "common.words.schoolYear": "School year", @@ -697,10 +698,24 @@ "pages.administration.school.index.schoolPolicy.cancel": "Cancel", "pages.administration.school.index.schoolPolicy.uploadedOn": "Uploaded on {date}", "pages.administration.school.index.schoolPolicy.notUploadedYet": "Not uploaded yet", - "pages.administration.school.index.schoolPolicy.fileName": "Privacy policy of the school", - "pages.administration.school.index.schoolPolicy.longText.willReplaceAndSendConsent": "The new privacy policy will irretrievably replace the old one and will be presented to all users of this school for approval.", - "pages.administration.school.index.schoolPolicy.edit": "Edit privacy policy", - "pages.administration.school.index.schoolPolicy.download": "Download privacy policy", + "pages.administration.school.index.schoolPolicy.fileName": "Privacy Policy of the school", + "pages.administration.school.index.schoolPolicy.longText.willReplaceAndSendConsent": "The new Privacy Policy will irretrievably replace the old one and will be presented to all users of this school for approval.", + "pages.administration.school.index.schoolPolicy.edit": "Edit Privacy Policy", + "pages.administration.school.index.schoolPolicy.download": "Download Privacy Policy", + "pages.administration.school.index.termsOfUse.labels.uploadFile": "Select file", + "pages.administration.school.index.termsOfUse.hints.uploadFile": "Upload file (PDF only, 4MB max)", + "pages.administration.school.index.termsOfUse.validation.fileTooBig": "The file is larger than 4MB. Please reduce the file size", + "pages.administration.school.index.termsOfUse.validation.notPdf": "This file format is not supported. Please use PDF only", + "pages.administration.school.index.termsOfUse.error": "An error occurred while loading the terms of use", + "pages.administration.school.index.termsOfUse.success": "New file was successfully uploaded.", + "pages.administration.school.index.termsOfUse.replace": "Replace", + "pages.administration.school.index.termsOfUse.cancel": "Cancel", + "pages.administration.school.index.termsOfUse.uploadedOn": "Uploaded on {date}", + "pages.administration.school.index.termsOfUse.notUploadedYet": "Not uploaded yet", + "pages.administration.school.index.termsOfUse.fileName": "Terms of Use of the school", + "pages.administration.school.index.termsOfUse.longText.willReplaceAndSendConsent": "The new Terms of Use will irretrievably replace the old one and will be presented to all users of this school for approval.", + "pages.administration.school.index.termsOfUse.edit": "Edit Terms of Use", + "pages.administration.school.index.termsOfUse.download": "Download Terms of Use", "pages.administration.school.index.authSystems.title": "Authentification", "pages.administration.school.index.authSystems.alias": "Alias", "pages.administration.school.index.authSystems.type": "Type", diff --git a/src/locales/es.json b/src/locales/es.json index caedf270ca..ed552703d3 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -113,7 +113,8 @@ "common.words.learnContent": "Contenidos de aprendizaje", "common.words.lernstore": "Lern-Store", "common.words.planned": "previsto", - "common.words.privacyPolicy": "Política de privacidad", + "common.words.privacyPolicy": "Política de Privacidad", + "common.words.termsOfUse": "Condiciones de Uso", "common.words.published": "publicado", "common.words.ready": "listo", "common.words.schoolYear": "Año escolar", @@ -680,16 +681,30 @@ "pages.administration.school.index.schoolPolicy.hints.uploadFile": "Cargar archivo (sólo PDF, 4 MB como máximo)", "pages.administration.school.index.schoolPolicy.validation.fileTooBig": "El archivo pesa más de 4 MB. Por favor, reduzca el tamaño del archivo", "pages.administration.school.index.schoolPolicy.validation.notPdf": "Este formato de archivo no es compatible. Utilice sólo PDF", - "pages.administration.school.index.schoolPolicy.error": "Se ha producido un error al cargar la política de privacidad", + "pages.administration.school.index.schoolPolicy.error": "Se ha producido un error al cargar la Política de Privacidad", "pages.administration.school.index.schoolPolicy.success": "El nuevo archivo se ha cargado correctamente.", "pages.administration.school.index.schoolPolicy.replace": "Sustituir", "pages.administration.school.index.schoolPolicy.cancel": "Cancelar", "pages.administration.school.index.schoolPolicy.uploadedOn": "Subido el {date}", "pages.administration.school.index.schoolPolicy.notUploadedYet": "Aún no se ha cargado", - "pages.administration.school.index.schoolPolicy.fileName": "Política de privacidad de la escuela", - "pages.administration.school.index.schoolPolicy.longText.willReplaceAndSendConsent": "La nueva política de privacidad sustituirá irremediablemente a la anterior y se presentará a todos los usuarios de esta escuela para su aprobación.", - "pages.administration.school.index.schoolPolicy.edit": "Editar política de privacidad", - "pages.administration.school.index.schoolPolicy.download": "Descargar política de privacidad", + "pages.administration.school.index.schoolPolicy.fileName": "Política de Privacidad de la escuela", + "pages.administration.school.index.schoolPolicy.longText.willReplaceAndSendConsent": "La nueva Política de Privacidad sustituirá irremediablemente a la anterior y se presentará a todos los usuarios de esta escuela para su aprobación.", + "pages.administration.school.index.schoolPolicy.edit": "Editar Política de Privacidad", + "pages.administration.school.index.schoolPolicy.download": "Descargar Política de Privacidad", + "pages.administration.school.index.termsOfUse.labels.uploadFile": "Seleccionar archivo", + "pages.administration.school.index.termsOfUse.hints.uploadFile": "Cargar archivo (sólo PDF, 4 MB como máximo)", + "pages.administration.school.index.termsOfUse.validation.fileTooBig": "El archivo pesa más de 4 MB. Por favor, reduzca el tamaño del archivo", + "pages.administration.school.index.termsOfUse.validation.notPdf": "Este formato de archivo no es compatible. Utilice sólo PDF", + "pages.administration.school.index.termsOfUse.error": "Se ha producido un error al cargar la Condiciones de Uso", + "pages.administration.school.index.termsOfUse.success": "El nuevo archivo se ha cargado correctamente.", + "pages.administration.school.index.termsOfUse.replace": "Sustituir", + "pages.administration.school.index.termsOfUse.cancel": "Cancelar", + "pages.administration.school.index.termsOfUse.uploadedOn": "Subido el {date}", + "pages.administration.school.index.termsOfUse.notUploadedYet": "Aún no se ha cargado", + "pages.administration.school.index.termsOfUse.fileName": "Condiciones de Uso de la escuela", + "pages.administration.school.index.termsOfUse.longText.willReplaceAndSendConsent": "La nueva Condiciones de Uso sustituirá irremediablemente a la anterior y se presentará a todos los usuarios de esta escuela para su aprobación.", + "pages.administration.school.index.termsOfUse.edit": "Editar Condiciones de Uso", + "pages.administration.school.index.termsOfUse.download": "Descargar Condiciones de Uso", "pages.administration.school.index.authSystems.title": "Autenticación", "pages.administration.school.index.authSystems.alias": "Alias", "pages.administration.school.index.authSystems.type": "Tipo", diff --git a/src/locales/uk.json b/src/locales/uk.json index 15d1dd64fa..57d108c1ea 100644 --- a/src/locales/uk.json +++ b/src/locales/uk.json @@ -115,6 +115,7 @@ "common.words.lernstore": "Навчальний магазин", "common.words.planned": "запланований", "common.words.privacyPolicy": "Політика конфіденційності", + "common.words.termsOfUse": "Умови використання", "common.words.published": "опубліковано", "common.words.ready": "Готовий", "common.words.schoolYear": "Навчальний рік", @@ -669,6 +670,20 @@ "pages.administration.school.index.schoolPolicy.longText.willReplaceAndSendConsent": "Нова політика конфіденційності безповоротно замінить стару і буде представлена всім користувачам цієї школи для затвердження.", "pages.administration.school.index.schoolPolicy.edit": "Редагувати політику конфіденційності", "pages.administration.school.index.schoolPolicy.download": "Завантажте політику конфіденційності", + "pages.administration.school.index.termsOfUse.labels.uploadFile": "Виберіть файл", + "pages.administration.school.index.termsOfUse.hints.uploadFile": "Завантажити файл (тільки PDF, максимум 4 МБ)", + "pages.administration.school.index.termsOfUse.validation.fileTooBig": "Розмір файлу перевищує 4 МБ. Будь ласка, зменшіть розмір файлу", + "pages.administration.school.index.termsOfUse.validation.notPdf": "Цей формат файлу не підтримується. Будь ласка, використовуйте тільки PDF", + "pages.administration.school.index.termsOfUse.error": "Виникла помилка під час завантаження Умови використання", + "pages.administration.school.index.termsOfUse.success": "Новий файл успішно завантажено.", + "pages.administration.school.index.termsOfUse.replace": "Замінити", + "pages.administration.school.index.termsOfUse.cancel": "Скасувати", + "pages.administration.school.index.termsOfUse.uploadedOn": "Завантажено {date}", + "pages.administration.school.index.termsOfUse.notUploadedYet": "Ще не завантажено", + "pages.administration.school.index.termsOfUse.fileName": "Умови використання школи", + "pages.administration.school.index.termsOfUse.longText.willReplaceAndSendConsent": "Нова Умови використання безповоротно замінить стару і буде представлена всім користувачам цієї школи для затвердження.", + "pages.administration.school.index.termsOfUse.edit": "Редагувати Умови використання", + "pages.administration.school.index.termsOfUse.download": "Завантажте Умови використання", "pages.administration.school.index.title": "Керувати школою", "pages.administration.school.index.usedFileStorage": "Використовуване файлове сховище у хмарі", "pages.administration.select": "вибрати", From bc00218a179c1a9b23f4ac65e8546179507dbd9e Mon Sep 17 00:00:00 2001 From: davwas Date: Thu, 7 Sep 2023 16:40:41 +0200 Subject: [PATCH 04/20] add terms of use module --- src/main.ts | 2 + src/store/store-accessor.ts | 4 ++ src/store/terms-of-use.ts | 107 ++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 src/store/terms-of-use.ts diff --git a/src/main.ts b/src/main.ts index 492150e968..64a04f9c78 100644 --- a/src/main.ts +++ b/src/main.ts @@ -16,6 +16,7 @@ import { newsModule, notifierModule, privacyPolicyModule, + termsOfUseModule, roomModule, roomsModule, schoolExternalToolsModule, @@ -154,6 +155,7 @@ Vue.use(VueDOMPurifyHTML, { newsModule, [NOTIFIER_MODULE_KEY.valueOf()]: notifierModule, privacyPolicyModule, + termsOfUseModule, [ROOM_MODULE_KEY.valueOf()]: roomModule, roomsModule, [SCHOOL_EXTERNAL_TOOLS_MODULE_KEY.valueOf()]: schoolExternalToolsModule, diff --git a/src/store/store-accessor.ts b/src/store/store-accessor.ts index 3a16a1dd9f..d5b832c660 100644 --- a/src/store/store-accessor.ts +++ b/src/store/store-accessor.ts @@ -34,6 +34,7 @@ import { getModule } from "vuex-module-decorators"; import ContextExternalToolsModule from "@/store/context-external-tools"; import SchoolExternalToolsModule from "@/store/school-external-tools"; import VideoConferenceModule from "@/store/video-conference"; +import TermsOfUseModule from "@/store/terms-of-use"; // Each store is the singleton instance of its module class // Use these -- they have methods for state/getters/mutations/actions @@ -55,6 +56,7 @@ export let loadingStateModule: LoadingStateModule; export let newsModule: NewsModule; export let notifierModule: NotifierModule; export let privacyPolicyModule: PrivacyPolicyModule; +export let termsOfUseModule: TermsOfUseModule; export let roomModule: RoomModule; export let roomsModule: RoomsModule; export let schoolExternalToolsModule: SchoolExternalToolsModule; @@ -85,6 +87,7 @@ export function initializeStores(store: Store): void { newsModule = getModule(NewsModule, store); notifierModule = getModule(NotifierModule, store); privacyPolicyModule = getModule(PrivacyPolicyModule, store); + termsOfUseModule = getModule(TermsOfUseModule, store); roomModule = getModule(RoomModule, store); roomsModule = getModule(RoomsModule, store); schoolExternalToolsModule = getModule(SchoolExternalToolsModule, store); @@ -118,6 +121,7 @@ export const modules = { newsModule: NewsModule, notifierModule: NotifierModule, privacyPolicyModule: PrivacyPolicyModule, + termsOfUseModule: TermsOfUseModule, roomModule: RoomModule, roomsModule: RoomsModule, schoolExternalToolsModule: SchoolExternalToolsModule, diff --git a/src/store/terms-of-use.ts b/src/store/terms-of-use.ts new file mode 100644 index 0000000000..50fe43bf90 --- /dev/null +++ b/src/store/terms-of-use.ts @@ -0,0 +1,107 @@ +import { Action, Module, Mutation, VuexModule } from "vuex-module-decorators"; +import { $axios } from "@/utils/api"; +import { + ConsentVersion, + CreateConsentVersionPayload, +} from "@/store/types/consent-version"; +import { BusinessError, Status } from "@/store/types/commons"; + +@Module({ + name: "termsOfUseModule", + namespaced: true, + stateFactory: true, +}) +export default class TermsOfUseModule extends VuexModule { + termsOfUse: ConsentVersion | null = null; + status: Status = ""; + businessError: BusinessError = { + statusCode: "", + message: "", + }; + + get getTermsOfUse(): ConsentVersion | null { + return this.termsOfUse; + } + + get getStatus(): string { + return this.status; + } + + get getBusinessError() { + return this.businessError; + } + + @Mutation + setTermsOfUse(termsOfUse: ConsentVersion | null): void { + this.termsOfUse = termsOfUse; + } + + @Mutation + setBusinessError(businessError: BusinessError): void { + this.businessError = businessError; + } + + @Mutation + resetBusinessError(): void { + this.businessError = { + statusCode: "", + message: "", + }; + } + + @Mutation + setStatus(status: Status): void { + this.status = status; + } + + @Action + async fetchTermsOfUse(schoolId: string): Promise { + try { + this.resetBusinessError(); + this.setStatus("pending"); + + const params = { + schoolId, + consentTypes: ["termsOfUse"], + consentDataId: { $exists: true }, + $populate: "consentData", + $limit: 1, + $sort: { + publishedAt: -1, + }, + }; + const response = (await $axios.get("/v1/consentVersions", { params })) + .data; + + this.setTermsOfUse(response.data.length ? response.data[0] : null); + this.setStatus("completed"); + } catch (error) { + this.setBusinessError(error as BusinessError); + this.setStatus("error"); + } + } + + @Action + async createTermsOfUse(payload: CreateConsentVersionPayload): Promise { + try { + this.resetBusinessError(); + this.setStatus("pending"); + + // create new terms of use and delete the old one + const response = (await $axios.post("/v1/consentVersions", payload)).data; + if (this.termsOfUse) { + await $axios.delete(`/v1/consentVersions/${this.termsOfUse._id}`); + } + + response.consentData = { + data: payload.consentData, + }; + + this.setTermsOfUse(response); + this.setStatus("completed"); + } catch (error) { + this.setBusinessError(error as BusinessError); + this.setStatus("error"); + } + } +} From d24612ccc99379e6c5914a8866bcd40a4cd175bb Mon Sep 17 00:00:00 2001 From: davwas Date: Thu, 7 Sep 2023 16:40:55 +0200 Subject: [PATCH 05/20] add terms of use vue components --- .../organisms/administration/SchoolTerms.vue | 193 +++++++++++++++ .../administration/SchoolTermsFormDialog.vue | 220 ++++++++++++++++++ 2 files changed, 413 insertions(+) create mode 100644 src/components/organisms/administration/SchoolTerms.vue create mode 100644 src/components/organisms/administration/SchoolTermsFormDialog.vue diff --git a/src/components/organisms/administration/SchoolTerms.vue b/src/components/organisms/administration/SchoolTerms.vue new file mode 100644 index 0000000000..a3f0d1c01a --- /dev/null +++ b/src/components/organisms/administration/SchoolTerms.vue @@ -0,0 +1,193 @@ + + + diff --git a/src/components/organisms/administration/SchoolTermsFormDialog.vue b/src/components/organisms/administration/SchoolTermsFormDialog.vue new file mode 100644 index 0000000000..084cba3109 --- /dev/null +++ b/src/components/organisms/administration/SchoolTermsFormDialog.vue @@ -0,0 +1,220 @@ + + + + + From ccfb859ecbf356b0d368853f2477a9afec13c159 Mon Sep 17 00:00:00 2001 From: davwas Date: Thu, 7 Sep 2023 16:41:15 +0200 Subject: [PATCH 06/20] add terms of use components to school settings page --- src/pages/administration/SchoolSettings.page.vue | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/administration/SchoolSettings.page.vue b/src/pages/administration/SchoolSettings.page.vue index d08da618ab..a648db4677 100644 --- a/src/pages/administration/SchoolSettings.page.vue +++ b/src/pages/administration/SchoolSettings.page.vue @@ -36,6 +36,7 @@ +