From c9d3d3739eeb493511f296f9981d4d0569e513ae Mon Sep 17 00:00:00 2001 From: mechtelm <nicht@mehr.fragen> Date: Tue, 28 Apr 2020 13:06:04 +0200 Subject: [PATCH] changes of booklet/test config; documentation of customTexts and bookletConfig (via scripts) --- docs/booklet-config.md | 67 ++++++++++ docs/custom-texts.md | 94 ++++++++++++++ src/app/app.interceptor.ts | 1 + .../{test-config.json => booklet-config.json} | 0 src/app/config/booklet-config.md | 25 ++++ src/app/config/booklet-config.ts | 57 +++++++++ src/app/config/custom-texts.json | 6 +- src/app/config/custom-texts.md | 65 ++++++++++ src/app/maindata.service.ts | 7 ++ src/app/test-controller/test-config.ts | 117 +----------------- src/scripts/findCustomTexts.js | 23 +++- src/scripts/generateBookletConfigClass.js | 58 +++++++++ 12 files changed, 400 insertions(+), 120 deletions(-) create mode 100644 docs/booklet-config.md create mode 100644 docs/custom-texts.md rename src/app/config/{test-config.json => booklet-config.json} (100%) create mode 100644 src/app/config/booklet-config.md create mode 100644 src/app/config/booklet-config.ts create mode 100644 src/app/config/custom-texts.md create mode 100644 src/scripts/generateBookletConfigClass.js diff --git a/docs/booklet-config.md b/docs/booklet-config.md new file mode 100644 index 00000000..aaa1150f --- /dev/null +++ b/docs/booklet-config.md @@ -0,0 +1,67 @@ +# Booklet config +There are some configuration parameters for adjusting the behaviour during the test.This +document describes the ways to bring the parameters to the application and lists +all possible keys. + +### Configuration file on the server +There is one file on the server where the application looks for booklet definitions: +``` +/config/bookletDefintions.json +``` +This configuration is loaded at (re)start of the application and is applied for +all booklets, if no other configuration is found. This is a simple JSON file with +key value pairs. Example: +``` +{ + "force_responses_complete": "OFF", + "unit_navibuttons": "ARROWS_ONLY", +... +} +``` +The adminstrator of the server can upload this file. We aim at providing an +administration feature of the super-admin section of the application to manage +this configuration. + +### List of parameters + +####`loading_mode` +Ladeverhalten beim Start + * "LAZY" (default): Start sobald wie möglich, Laden im Hintergrund fortsetzen + * "EAGER": Testheft erst dann starten, wenn alle Inhalte geladen sind + +####`log_mode` +Erfassen und Speichern von Log-Daten + * "OFF": Ausgeschaltet + * "LEAN": Nur wichtige Meldungen + * "RICH" (default): Alles + +####`page_navibuttons` +Navigationsbuttons für die Seitennavigation (innerhalb einer Aufgabe) + * "OFF": Keine Seitennavigation unterstützen (übernimmt ggf. die Aufgabe selbst) + * "MERGED": Die Seitennavigation wird durch die Aufgabennavigation mit übernommen + * "SEPARATE_TOP": Seitennavigation über getrennte Button-Leiste - oben + * "SEPARATE_BOTTOM" (default): Seitennavigation über getrennte Button-Leiste - unten + +####`unit_navibuttons` +Navigationsbuttons für die Navigation zwischen den Aufgaben + * "OFF": Keine Buttons für Aufgabennavigation anzeigen (übernimmt ggf. die Aufgabe selbst) + * "ARROWS_ONLY": Nur die Buttons für 'Weiter' und 'Zurück' anzeigen + * "FULL" (default): Buttons für 'Weiter' und 'Zurück' und dazwischen kleine Buttons für jede Aufgabe anzeigen + +####`unit_menu` +Extra-Seite mit großen Buttons für Aufgaben zum direkten Springen + * "OFF": Ausgeschaltet + * "ENABLED_ONLY" (default): Eingeschaltet - nur die Aufgaben anzeigen, die noch freigegeben sind + * "FULL": Eingeschaltet - auch die Aufgaben anzeigen, die nicht mehr freigegeben sind (gegraut) + +####`force_presentation_complete` +Verhalten, wenn noch nicht alle Elemente der Aufgabe angezeigt wurden + * "OFF" (default): Ignorieren - Weiterblättern möglich + * "ON": Weiterblättern verhindern, bis Anzeige vollständig + +####`force_responses_complete` +Verhalten, wenn noch nicht alle Antworten der Aufgabe vollständig gegeben wurden + * "OFF" (default): Ignorieren - Weiterblättern möglich + * "SOME": Weiterblättern erst möglich, wenn einige Antworten gegeben wurden + * "COMPLETE": Weiterblättern erst möglich, wenn alle Antworten gegeben wurden + * "COMPLETE_AND_VALID": Weiterblättern erst möglich, wenn alle Antworten gegeben wurden und als gültig eingeschätzt wurden diff --git a/docs/custom-texts.md b/docs/custom-texts.md new file mode 100644 index 00000000..2d289d1b --- /dev/null +++ b/docs/custom-texts.md @@ -0,0 +1,94 @@ +# CustomTexts +This application enables changes of texts during runtime. It's an implementation +of the CustomTextPipe/CustomTextService +of [iqb-components](https://github.com/iqb-berlin/iqb-components). The idea is, that +there might be some cases where the standard titles, prompts or explanations are not +suitable for the specific environment the iqb-testcenter application is run in. One +could change the source code and rebuild the application, but for minor changes we +use this text replacement feature 'custom texts'. + +This document +describes the ways to bring the custom texts to the application and lists +all possible keys. + +### Configuration file on the server +There is one file on the server where the application looks for custom texts: +``` +/config/customTexts.json +``` +These custom texts are loaded at (re)start of the application and the replacement starts +as soon as possible. This is a simple JSON file with key value pairs. Example: +``` +{ + "login_testEndButtonText": "Test beenden", + "login_bookletSelectPrompt": "Bitte wählen", +... +} +``` +The adminstrator of the server can upload this file. We aim at providing an +administration feature of the super-admin section of the application to manage +these texts. + +### Configuration via login configuration +For some tests, the test authority might like to change standard titles, prompts or explanations +furthermore depending on the testtaker. For example, the questionnaire for teachers +will use 'Please contact the administrator of the survey' and the booklet for students +will prompt 'Please ask the test proctor'. + +The login configuration goes with the XML file for the longin(s). There is one optional +section 'CustomTexts' in every login file. Text replacements in this section will apply +for every login of this file. Example: +``` +<CustomTexts> + <CustomText key="login_testEndButtonText">Test beenden</CustomText> + <CustomText key="login_bookletSelectPrompt">Bitte wählen</CustomText> +... +</CustomTexts> +``` +### Configuration of System check +In the definition file for system checks, there is also one place to define text +replacements: +``` +<Config> + <UploadSpeed ... + <DownloadSpeed ... + <CustomText key="syscheck_questionsintro">...</CustomText> + <CustomText key="app_intro1">...</CustomText> +... +</Config> +``` + +### List of possible replacements +| Key | Used for | Default | +| :------------- | :---------- | :----------- | +|`app_title`|Titel der Hauptanwendung|IQB-Testcenter| +|`app_intro1`|Begrüßungstext auf der Startseite (Text nach IQB-Link)|betreibt auf diesen Seiten eine Anwendung für das computerbasierte Leistungstesten von Schülerinnen und Schülern. Der Zugang zu einem Test ist nur möglich, wenn Sie von Testverantwortlichen Zugangsdaten erhalten haben. Es sind keine weiteren Seiten öffentlich verfügbar.| +|`login_testRunningText`|Kurznachricht, dass ein Test (Booklet) gestartet ist|Ein Testheft ist gestartet| +|`login_testRunningTextAndClick`|Nachricht, dass ein Test (Booklet) gestartet ist, mit Aufforderung zum Klicken|Es wird gerade ein Test ausgeführt. Bitte durch Klicken auf eine der beiden Schaltflächen links wählen, ob der Test fortgesetzt oder beendet werden soll!| +|`login_testEndButtonLabel`|Schalterbeschriftung für 'Test beenden'|Test beenden| +|`booklet_warningLeaveTimerBlockTextPrompt`|Schalterbeschriftung für 'Zurück zum Test'|Du verlässt einen zeitbeschränkten Bereich und kannst nicht zurückkehren. Trotzdem weiterblättern?| +|`login_testReturnButtonLabel`|Schalterbeschriftung für 'Zurück zum Test'|Zum Test zurückkehren| +|`login_bookletSelectPromptNull`|Nachricht für den Fall, dass Booklet(s) beendet wurden und keine weiteren zur Verfügung stehen|Beendet. Es können keine weiteren Testhefte gestartet werden.| +|`login_bookletSelectPromptOne`|Aufforderung, den einen gefundenen Test anzuklicken (auf Schalter klicken)|Bitte klicke auf die Schaltfläche auf der linken Seite, um den Test zu starten!| +|`login_bookletSelectPromptMany`|Aufforderung, aus der Liste der gefundenen Tests einen auszusuchen (auf Schalter klicken)|Bitte klicke auf eine der Schaltflächen auf der linken Seite, um einen Test zu starten!| +|`login_codeInputPrompt`|Aufforderung, Code einzugeben (bei einem zweistufigen Login-Prozess)|Bitte Log-in eingeben, der auf dem Zettel steht!| +|`login_codeInputTitle`|Titel des Eingabeformulares für den Code|Log-in eingeben| +|`booklet_msgPresentationNotCompleteTitleNext`|Titel der Nachricht (Dialogbox), dass nicht weitergeblättert werden kann, solange die Präsentation des Aufgabeninhaltes nicht abgeschlossen ist|Weiterblättern nicht möglich!| +|`booklet_msgPresentationNotCompleteTextNext`|Nachrichttext, dass nicht weitergeblättert werden kann, solange die Präsentation des Aufgabeninhaltes nicht abgeschlossen ist|Du kannst erst weiterblättern, wenn Audio-Dateien vollständig abgespielt wurden und wenn du in allen Fenstern bis ganz nach unten gescrollt hast.| +|`booklet_msgPresentationNotCompleteTitlePrev`|Titel der Nachricht (Dialogbox), dass nicht zurückgeblättert werden kann, solange die Präsentation des Aufgabeninhaltes nicht abgeschlossen ist|Zurückblättern - Warnung| +|`booklet_msgPresentationNotCompleteTextPrev`|Nachrichttext, dass nicht zurückgeblättert werden kann, solange die Präsentation des Aufgabeninhaltes nicht abgeschlossen ist|Eine Audio-Datei ist noch nicht bis zu Ende abgespielt oder Seiten wurden noch nicht vollständig gezeigt. Wenn du jetzt zurückblätterst, kannst Du später Audio-Dateien nicht nocheinmal starten.| +|`booklet_codeToEnterTitle`|Titel der Dialogbox für die Eingabe eines Freigabewortes|Freigabewort| +|`booklet_codeToEnterPrompt`|Aufforderung für die Eingabe eines Freigabewortes (Dialog-Box)|Bitte gib das Freigabewort ein, das angesagt wurde!| +|`booklet_msgSoonTimeOver5Minutes`|Nachricht, dass für die Bearbeitung eines Abschnittes noch 5 min Zeit sind|Du hast noch 5 Minuten Zeit für die Bearbeitung der Aufgaben in diesem Abschnitt.| +|`booklet_msgSoonTimeOver1Minute`|Nachricht, dass für die Bearbeitung eines Abschnittes noch 1 min Zeit ist|Du hast noch 1 Minute Zeit für die Bearbeitung der Aufgaben in diesem Abschnitt.| +|`booklet_msgTimerStarted`|Nachricht, dass der Timer für die Bearbeitung eines Abschnittes gestartet wurde|Die Bearbeitungszeit für diesen Abschnitt hat begonnen: | +|`booklet_msgTimerCancelled`|Nachricht, dass die Bearbeitung eines Abschnittes mit Timer abgebrochen wurde|Die Bearbeitung des Abschnittes wurde abgebrochen.| +|`booklet_msgTimeOver`|Nachricht, dass die Bearbeitungszeit für einen Abschnitt abgelaufen ist.|Die Bearbeitung des Abschnittes ist beendet.| +|`booklet_warningLeaveTimerBlockTitle`|Titel für Warnung (Dialogbox) vor dem vorzeitigen Verlassen eines Abschnittes mit Timer|Aufgabenabschnitt verlassen?| +|`booklet_warningLeaveTimerBlockPrompt`|Warnung vor dem vorzeitigen Verlassen eines Abschnittes mit Timer|Wenn du jetzt weiterblätterst, beendest du vorzeitig die Bearbeitung dieses Aufgabenabschnitts und du kannst nicht mehr zurück.| +|`booklet_tasklisttitle`|Titel für die Auflistung der Aufgaben (Schalter)|Aufgaben| +|`booklet_warningLeaveTestTitle`|Titel für Warnung (Dialogbox) vor dem vorzeitigen Verlassen des Tests|Test verlassen?| +|`booklet_warningLeaveTestPrompt`|Warnung vor dem vorzeitigen Verlassen des Tests|Der Test ist noch nicht beendet. Möchtest Du den Test trotzdem verlassen?| +|`syscheck_questionsintro`|Aufforderung, die Fragen (Questionnaire) zu beantworten|Bitte bearbeiten Sie die nachfolgenden Fragen.| +|`booklet_errormessage`|Nachricht an die Testperson, wenn ein schwerer Fehler aufgetreten ist|Es ist ein schwerer Fehler aufgetreten. Bitte rufe die Aufsichtsperson und beschreibe das Problem!| +|`booklet_pausedmessage`|Nachricht an die Testperson, wenn der Test vom System unterbrochen wurde|Der Test wurde kurz angehalten.| diff --git a/src/app/app.interceptor.ts b/src/app/app.interceptor.ts index d3de6b8f..871c67f6 100644 --- a/src/app/app.interceptor.ts +++ b/src/app/app.interceptor.ts @@ -101,6 +101,7 @@ export class AuthInterceptor implements HttpInterceptor { category: "PROBLEM" }); if (goToLoginPage) { + MainDataService.resetAuthData(); const state: RouterState = this.router.routerState; const snapshot: RouterStateSnapshot = state.snapshot; this.router.navigate(['/r/login', snapshot.url]); diff --git a/src/app/config/test-config.json b/src/app/config/booklet-config.json similarity index 100% rename from src/app/config/test-config.json rename to src/app/config/booklet-config.json diff --git a/src/app/config/booklet-config.md b/src/app/config/booklet-config.md new file mode 100644 index 00000000..9a9b007b --- /dev/null +++ b/src/app/config/booklet-config.md @@ -0,0 +1,25 @@ +# Booklet config +There are some configuration parameters for adjusting the behaviour during the test.This +document describes the ways to bring the parameters to the application and lists +all possible keys. + +### Configuration file on the server +There is one file on the server where the application looks for booklet definitions: +``` +/config/bookletDefintions.json +``` +This configuration is loaded at (re)start of the application and is applied for +all booklets, if no other configuration is found. This is a simple JSON file with +key value pairs. Example: +``` +{ + "force_responses_complete": "OFF", + "unit_navibuttons": "ARROWS_ONLY", +... +} +``` +The adminstrator of the server can upload this file. We aim at providing an +administration feature of the super-admin section of the application to manage +this configuration. + +### List of parameters diff --git a/src/app/config/booklet-config.ts b/src/app/config/booklet-config.ts new file mode 100644 index 00000000..63ee44b6 --- /dev/null +++ b/src/app/config/booklet-config.ts @@ -0,0 +1,57 @@ +export class BookletConfig { + // this file is generated by 'generateBookletConfigClass' script from 'app/config/booklet-config.json' + // do not change anything here directly! + + loading_mode: "LAZY" | "EAGER" = "LAZY"; + log_mode: "OFF" | "LEAN" | "RICH" = "RICH"; + page_navibuttons: "OFF" | "MERGED" | "SEPARATE_TOP" | "SEPARATE_BOTTOM" = "SEPARATE_BOTTOM"; + unit_navibuttons: "OFF" | "ARROWS_ONLY" | "FULL" = "FULL"; + unit_menu: "OFF" | "ENABLED_ONLY" | "FULL" = "ENABLED_ONLY"; + force_presentation_complete: "OFF" | "ON" = "OFF"; + force_responses_complete: "OFF" | "SOME" | "COMPLETE" | "COMPLETE_AND_VALID" = "OFF"; + + public setFromKeyValuePairs(config) { + if (config) { + if (config['loading_mode']) { this.loading_mode = config['loading_mode']} + if (config['log_mode']) { this.log_mode = config['log_mode']} + if (config['page_navibuttons']) { this.page_navibuttons = config['page_navibuttons']} + if (config['unit_navibuttons']) { this.unit_navibuttons = config['unit_navibuttons']} + if (config['unit_menu']) { this.unit_menu = config['unit_menu']} + if (config['force_presentation_complete']) { this.force_presentation_complete = config['force_presentation_complete']} + if (config['force_responses_complete']) { this.force_responses_complete = config['force_responses_complete']} + } + } + + public setFromXml(bookletConfigElement: Element) { + if (bookletConfigElement) { + const bookletConfigs = Array.prototype.slice.call(bookletConfigElement.childNodes).filter(function (e) { return e.nodeType === 1; }); + for (let childIndex = 0; childIndex < bookletConfigs.length; childIndex++) { + const configKey = bookletConfigs[childIndex].getAttribute('key'); + const configValue = bookletConfigs[childIndex].textContent; + switch (configKey) { + case 'loading_mode': + this.loading_mode = configValue; + break; + case 'log_mode': + this.log_mode = configValue; + break; + case 'page_navibuttons': + this.page_navibuttons = configValue; + break; + case 'unit_navibuttons': + this.unit_navibuttons = configValue; + break; + case 'unit_menu': + this.unit_menu = configValue; + break; + case 'force_presentation_complete': + this.force_presentation_complete = configValue; + break; + case 'force_responses_complete': + this.force_responses_complete = configValue; + break; + } + } + } + } +} diff --git a/src/app/config/custom-texts.json b/src/app/config/custom-texts.json index f1087e03..bb523bab 100644 --- a/src/app/config/custom-texts.json +++ b/src/app/config/custom-texts.json @@ -21,7 +21,7 @@ }, "booklet_warningLeaveTimerBlockTextPrompt": { "label": "Schalterbeschriftung für 'Zurück zum Test'", - "defaultvalue": "Du verlässt einen zeitbeschränkten Bereich uns kannst nicht zurückkehren. Trotzdem weiterblättern?" + "defaultvalue": "Du verlässt einen zeitbeschränkten Bereich und kannst nicht zurückkehren. Trotzdem weiterblättern?" }, "login_testReturnButtonLabel": { "label": "Schalterbeschriftung für 'Zurück zum Test'", @@ -108,8 +108,8 @@ "defaultvalue": "Test verlassen?" }, "booklet_warningLeaveTestPrompt": { - "label": "Der Test ist noch nicht beendet. Möchtest Du den Test trotzdem verlassen?", - "defaultvalue": "Aufgaben" + "label": "Warnung vor dem vorzeitigen Verlassen des Tests", + "defaultvalue": "Der Test ist noch nicht beendet. Möchtest Du den Test trotzdem verlassen?" }, "syscheck_questionsintro": { "label": "Aufforderung, die Fragen (Questionnaire) zu beantworten", diff --git a/src/app/config/custom-texts.md b/src/app/config/custom-texts.md new file mode 100644 index 00000000..397c3db8 --- /dev/null +++ b/src/app/config/custom-texts.md @@ -0,0 +1,65 @@ +# CustomTexts +This application enables changes of texts during runtime. It's an implementation +of the CustomTextPipe/CustomTextService +of [iqb-components](https://github.com/iqb-berlin/iqb-components). The idea is, that +there might be some cases where the standard titles, prompts or explanations are not +suitable for the specific environment the iqb-testcenter application is run in. One +could change the source code and rebuild the application, but for minor changes we +use this text replacement feature 'custom texts'. + +This document +describes the ways to bring the custom texts to the application and lists +all possible keys. + +### Configuration file on the server +There is one file on the server where the application looks for custom texts: +``` +/config/customTexts.json +``` +These custom texts are loaded at (re)start of the application and the replacement starts +as soon as possible. This is a simple JSON file with key value pairs. Example: +``` +{ + "login_testEndButtonText": "Test beenden", + "login_bookletSelectPrompt": "Bitte wählen", +... +} +``` +The adminstrator of the server can upload this file. We aim at providing an +administration feature of the super-admin section of the application to manage +these texts. + +### Configuration via login configuration +For some tests, the test authority might like to change standard titles, prompts or explanations +furthermore depending on the testtaker. For example, the questionnaire for teachers +will use 'Please contact the administrator of the survey' and the booklet for students +will prompt 'Please ask the test proctor'. + +The login configuration goes with the XML file for the longin(s). There is one optional +section 'CustomTexts' in every login file. Text replacements in this section will apply +for every login of this file. Example: +``` +<CustomTexts> + <CustomText key="login_testEndButtonText">Test beenden</CustomText> + <CustomText key="login_bookletSelectPrompt">Bitte wählen</CustomText> +... +</CustomTexts> +``` +### Configuration of System check +In the definition file for system checks, there is also one place to define text +replacements: +``` +<Config> + <UploadSpeed ... + <DownloadSpeed ... + <CustomText key="syscheck_questionsintro">...</CustomText> + <CustomText key="app_intro1">...</CustomText> +... +</Config> +``` + + + +### List of possible replacements +| Key | Used for | Default | +| :------------- | :---------- | :----------- | diff --git a/src/app/maindata.service.ts b/src/app/maindata.service.ts index 9dea8b3a..4d6214bc 100644 --- a/src/app/maindata.service.ts +++ b/src/app/maindata.service.ts @@ -44,6 +44,13 @@ export class MainDataService { return myReturn; } + static resetAuthData() { + const storageEntry = localStorage.getItem(localStorageAuthDataKey); + if (storageEntry) { + localStorage.removeItem(localStorageAuthDataKey); + } + } + static getTestConfig(): KeyValuePairs { let myReturn: KeyValuePairs = null; const storageEntry = localStorage.getItem(localStorageTestConfigKey); diff --git a/src/app/test-controller/test-config.ts b/src/app/test-controller/test-config.ts index db071678..eee1352a 100644 --- a/src/app/test-controller/test-config.ts +++ b/src/app/test-controller/test-config.ts @@ -1,17 +1,8 @@ -// @ts-ignore -import testConfigDefinition from '../config/test-config.json'; import {RunModeKey} from "./test-controller.interfaces"; +import {BookletConfig} from "../config/booklet-config"; -export class TestConfig { - definition = testConfigDefinition; - loading_mode: "LAZY" | "EAGER" = testConfigDefinition.loading_mode.defaultvalue; - log_mode: "OFF" | "LEAN" | "RICH" = testConfigDefinition.log_mode.defaultvalue; - page_navibuttons: "OFF" | "MERGED" | "SEPARATE_TOP" | "SEPARATE_BOTTOM" = testConfigDefinition.page_navibuttons.defaultvalue; - unit_navibuttons: "OFF" | "ARROWS_ONLY" | "FULL" = testConfigDefinition.unit_navibuttons.defaultvalue; - unit_menu: "OFF" | "ENABLED_ONLY" | "FULL" = testConfigDefinition.unit_menu.defaultvalue; - force_presentation_complete: "ON" | "OFF" = testConfigDefinition.force_presentation_complete.defaultvalue; - force_responses_complete: "OFF" | "SOME" | "COMPLETE" | "COMPLETE_AND_VALID" = testConfigDefinition.force_responses_complete.defaultvalue; +export class TestConfig extends BookletConfig { // default for RunModeKey.DEMO canReview = false; saveResponses = false; @@ -22,6 +13,7 @@ export class TestConfig { modeLabel = "Demo"; constructor(loginMode: RunModeKey = RunModeKey.DEMO) { + super(); if (loginMode !== RunModeKey.DEMO) { switch (loginMode) { case RunModeKey.HOT_RESTART: @@ -57,107 +49,4 @@ export class TestConfig { } } } - - public setFromKeyValuePairs(config) { - if (config) { - if (config['loading_mode']) { this.loading_mode = config['loading_mode']} - if (config['log_mode']) { this.log_mode = config['log_mode']} - if (config['page_navibuttons']) { this.page_navibuttons = config['page_navibuttons']} - if (config['unit_navibuttons']) { this.unit_navibuttons = config['unit_navibuttons']} - if (config['unit_menu']) { this.unit_menu = config['unit_menu']} - if (config['force_presentation_complete']) { this.force_presentation_complete = config['force_presentation_complete']} - if (config['force_responses_complete']) { this.force_responses_complete = config['force_responses_complete']} - } - } - - public setFromXml(bookletConfigElement: Element) { - if (bookletConfigElement) { - const bookletConfigs = TestConfig.getChildElements(bookletConfigElement); - for (let childIndex = 0; childIndex < bookletConfigs.length; childIndex++) { - const configParameter = bookletConfigs[childIndex].getAttribute('parameter'); - - // TODO remove old version - switch (bookletConfigs[childIndex].nodeName) { - // ---------------------- - case 'NavPolicy': - if (configParameter) { - if (configParameter.toUpperCase() === 'NextOnlyIfPresentationComplete'.toUpperCase()) { - this.force_presentation_complete = "ON" - } - } - break; - case 'NavButtons': - if (configParameter) { - switch (configParameter.toUpperCase()) { - case 'ON': - this.unit_navibuttons = "FULL"; - break; - case 'OFF': - this.unit_navibuttons = "OFF"; - break; - case 'ARROWSONLY': - this.unit_navibuttons = "ARROWS_ONLY"; - break; - } - } - break; - case 'PageNavBar': - if (configParameter) { - if (configParameter.toUpperCase() === 'OFF') { - this.page_navibuttons = "OFF" - } - } - break; - case 'Logging': - if (configParameter) { - if (configParameter.toUpperCase() === 'OFF') { - this.log_mode = "OFF" - } - } - break; - case 'Loading': - if (configParameter) { - if (configParameter.toUpperCase() === 'EAGER') { - this.loading_mode = "EAGER" - } - } - break; - case 'Config': - const configKey = bookletConfigs[childIndex].getAttribute('key'); - const configValue = bookletConfigs[childIndex].textContent; - if (configKey) { - switch (configKey) { - case 'loading_mode': - this.loading_mode = configValue; - break; - case 'log_mode': - this.log_mode = configValue; - break; - case 'page_navibuttons': - this.page_navibuttons = configValue; - break; - case 'unit_navibuttons': - this.unit_navibuttons = configValue; - break; - case 'unit_menu': - this.unit_menu = configValue; - break; - case 'force_presentation_complete': - this.force_presentation_complete = configValue; - break; - case 'force_responses_complete': - this.force_responses_complete = configValue; - break; - } - } - break; - } - } - } - } - - private static getChildElements(element) { - return Array.prototype.slice.call(element.childNodes) - .filter(function (e) { return e.nodeType === 1; }); - } } diff --git a/src/scripts/findCustomTexts.js b/src/scripts/findCustomTexts.js index 31c27858..b6010f86 100644 --- a/src/scripts/findCustomTexts.js +++ b/src/scripts/findCustomTexts.js @@ -2,8 +2,14 @@ // listing of all used keys for customText const fs = require("fs"); +const definitionFilename = '../app/config/custom-texts.json'; +const startFolder = '../app'; +const mdSourceFilename = '../app/config/custom-texts.md'; +const mdTargetFilename = '../../docs/custom-texts.md'; + let foundKeys = {}; let foundSourceFiles = []; +let foundError = false; function analyse ( fileName, isHtml ) { const fileContent = fs.readFileSync(fileName, 'utf8').toString(); @@ -46,9 +52,9 @@ function takeFolder(sourceFolder ) { } } -takeFolder('../app'); +takeFolder(startFolder); -const defaults = JSON.parse(fs.readFileSync('../app/config/custom-texts.json')); +const defaults = JSON.parse(fs.readFileSync(definitionFilename)); console.log(); console.log('\x1b[33m%s\x1b[0m', 'used keys:'); @@ -56,6 +62,7 @@ for (const k of Object.keys(foundKeys)) { if (defaults[k]) { console.log(` ${k}: ${foundKeys[k]}`); } else { + foundError = true; console.log('\x1b[31m%s\x1b[0m', ` ${k}: ${foundKeys[k]}`) } } @@ -74,5 +81,15 @@ for (const k of Object.keys(defaults)) { } } -console.log(); +if (!foundError) { + console.log(''); + console.log('writing markdown'); + let mdContent = fs.readFileSync(mdSourceFilename, 'utf8').toString(); + for (const k of Object.keys(defaults)) { + mdContent += '|`' + k + '`|' + defaults[k].label + '|' + defaults[k].defaultvalue + '|' + '\n'; + } + fs.writeFileSync(mdTargetFilename, mdContent, "utf8"); +} + +console.log(''); console.log('done.'); diff --git a/src/scripts/generateBookletConfigClass.js b/src/scripts/generateBookletConfigClass.js new file mode 100644 index 00000000..7315af41 --- /dev/null +++ b/src/scripts/generateBookletConfigClass.js @@ -0,0 +1,58 @@ +// generates booklet-config.ts as class with all data from JSON: + +const fs = require("fs"); +const definitionFilename = '../app/config/booklet-config.json'; +const targetTsFilename = '../app/config/booklet-config.ts'; +const mdSourceFilename = '../app/config/booklet-config.md'; +const mdTargetFilename = '../../docs/booklet-config.md'; + +console.log(''); +console.log('writing TypeScript'); + +const definition = JSON.parse(fs.readFileSync(definitionFilename)); + +let fileContent = "export class BookletConfig {\n"; +fileContent += "\t// this file is generated by 'generateBookletConfigClass' script from 'app/config/booklet-config.json'\n"; +fileContent += "\t// do not change anything here directly!\n\n"; + +for (const k of Object.keys(definition)) { + fileContent += '\t' + k + ': "' + Object.keys(definition[k].options).join('" | "') + '" = "' + definition[k].defaultvalue + '";\n'; +} + +fileContent += "\n\tpublic setFromKeyValuePairs(config) {\n"; +fileContent += "\t\tif (config) {\n"; +for (const k of Object.keys(definition)) { + fileContent += "\t\t\tif (config['" + k + "']) { this." + k + " = config['" + k + "']}\n"; +} +fileContent += "\t\t}\n\t}\n"; + +fileContent += "\n\tpublic setFromXml(bookletConfigElement: Element) {\n"; +fileContent += "\t\tif (bookletConfigElement) {\n"; +fileContent += "\t\t\tconst bookletConfigs = Array.prototype.slice.call(bookletConfigElement.childNodes).filter(function (e) { return e.nodeType === 1; });\n"; +fileContent += "\t\t\tfor (let childIndex = 0; childIndex < bookletConfigs.length; childIndex++) {\n"; +fileContent += "\t\t\t\tconst configKey = bookletConfigs[childIndex].getAttribute('key');\n"; +fileContent += "\t\t\t\tconst configValue = bookletConfigs[childIndex].textContent;\n"; +fileContent += "\t\t\t\tswitch (configKey) {\n"; +for (const k of Object.keys(definition)) { + fileContent += "\t\t\t\t\tcase '" + k + "':\n\t\t\t\t\t\tthis." + k + " = configValue;\n\t\t\t\t\t\tbreak;\n"; +} +fileContent += "\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n"; + + +fileContent += "}\n"; +fs.writeFileSync(targetTsFilename, fileContent, "utf8"); + +console.log(''); +console.log('writing markdown'); +let mdContent = fs.readFileSync(mdSourceFilename, 'utf8').toString(); +for (const k of Object.keys(definition)) { + mdContent += '\n####`' + k + '`\n' + definition[k].label + '\n'; + for (const o of Object.keys(definition[k].options)) { + mdContent += ' * "' + o + ((o === definition[k].defaultvalue) ? '" (default): ' : '": ') + definition[k].options[o] + '\n'; + } +} + +fs.writeFileSync(mdTargetFilename, mdContent, "utf8"); + +console.log(''); +console.log('done.'); -- GitLab