diff --git a/public/StorylinesSlideSchema.json b/public/StorylinesSlideSchema.json index 9b728cb4..24f4249e 100644 --- a/public/StorylinesSlideSchema.json +++ b/public/StorylinesSlideSchema.json @@ -30,10 +30,6 @@ "width": { "type": "number", "description": "The width of the panel inside the slide (between 0 and 100)." - }, - "customStyles": { - "type": "string", - "description": "Additional CSS styles to apply to the panel." } }, "minItems": 1, @@ -65,8 +61,13 @@ "type": "string", "description": "The colour of the text. Defaults to black.", "default": "#000000" + }, + "customStyles": { + "type": "string", + "description": "Additional CSS styles to apply to the panel." } }, + "additionalProperties": false, "required": ["content", "type", "title"] }, @@ -103,8 +104,13 @@ "type": "string", "description": "The colour of the text. Defaults to black.", "default": "#000000" + }, + "customStyles": { + "type": "string", + "description": "Additional CSS styles to apply to the panel." } }, + "additionalProperties": false, "required": ["content", "type", "children", "title"] }, @@ -112,7 +118,10 @@ "type": "object", "description": "A child screen of a dynamic panel. Contains an ID and a panel config.", "properties": { - "id": "string", + "id": { + "type": "string", + "description": "An ID representing a dynamic child." + }, "panel": { "oneOf": [ { @@ -130,6 +139,7 @@ ] } }, + "additionalProperties": false, "required": ["id", "panel"] }, @@ -182,8 +192,42 @@ "title": { "type": "string", "description": "A title that is displayed centered above this map." + }, + "timeSlider": { + "type": "object", + "description": "Configuration for a time slider on the map.", + "properties": { + "range": { + "type": "array", + "items": { + "type": "number" + } + }, + "start": { + "type": "array", + "items": { + "type": "number" + } + }, + "attribute": { + "type": "string" + }, + "layers": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false, + "required": ["range", "start", "attribute"] + }, + "customStyles": { + "type": "string", + "description": "Additional CSS styles to apply to the panel." } }, + "additionalProperties": false, "required": ["config", "type"] }, @@ -205,8 +249,17 @@ }, "options": { "$ref": "#/$defs/chartOptions" + }, + "name": { + "type": "string", + "description": "The name of the chart." + }, + "customStyles": { + "type": "string", + "description": "Additional CSS styles to apply to the panel." } }, + "additionalProperties": false, "required": ["src", "type"] }, @@ -214,6 +267,10 @@ "type": "object", "description": "A multimedia image component.", "properties": { + "id": { + "type": "string", + "description": "The image ID." + }, "width": { "type": "number", "description": "The image width." @@ -245,8 +302,17 @@ "type": { "type": "string", "enum": ["image"] + }, + "fullscreen": { + "type": "boolean", + "description": "Specifies whether the image can be fullscreened or not." + }, + "customStyles": { + "type": "string", + "description": "Additional CSS styles to apply to the panel." } }, + "additionalProperties": false, "required": ["src", "type"] }, @@ -289,8 +355,13 @@ "type": { "type": "string", "enum": ["video"] + }, + "customStyles": { + "type": "string", + "description": "Additional CSS styles to apply to the panel." } }, + "additionalProperties": false, "required": ["src", "type", "videoType"] }, @@ -333,11 +404,21 @@ "type": "text", "description": "A caption to display below the slideshow." }, + "userCreated": { + "type": "boolean", + "description": "Specifies whether this slideshow was automatically created from an image panel or if this is actually a slideshow panel.", + "default": false + }, "type": { "type": "string", "enum": ["slideshow"] + }, + "customStyles": { + "type": "string", + "description": "Additional CSS styles to apply to the panel." } }, + "additionalProperties": false, "required": ["items", "type"] }, diff --git a/src/components/helpers/custom-editor.vue b/src/components/helpers/custom-editor.vue index 8c3166a1..47fbc7fa 100644 --- a/src/components/helpers/custom-editor.vue +++ b/src/components/helpers/custom-editor.vue @@ -1,20 +1,65 @@ @@ -39,7 +84,11 @@ export default class CustomEditorV extends Vue { edited = false; jsonValidator = require('jsonschema').Validator; + jsonError = ''; validator: Validator = new this.jsonValidator(); + validatorErrors: any = []; + showErrors = false; + storylinesSchema = ''; mounted(): void { @@ -50,6 +99,7 @@ export default class CustomEditorV extends Vue { // eslint-disable-next-line @typescript-eslint/no-explicit-any (res: any) => { this.storylinesSchema = res; + this.validate(); }, (err) => { console.error(err); @@ -59,21 +109,23 @@ export default class CustomEditorV extends Vue { this.updatedConfig = this.config; } - onJsonSave(): void { + validate(): void { // TODO: add any missing properties in schema as required (e.g. chart options) const checkValidation = this.validator.validate(this.updatedConfig, this.storylinesSchema); - if (checkValidation.valid) { - this.$emit('config-edited', this.updatedConfig, true); - } else { - // TODO: add FR translation for alert message - alert('Attempted to save a custom config that violates the Storylines schema.'); - console.error(checkValidation.errors); + this.validatorErrors = checkValidation.errors; + if (this.jsonError) { + this.validatorErrors.push(this.jsonError); } } saveChanges(): void { this.$emit('config-edited', this.updatedConfig); this.edited = false; + + // If the user saves or leaves the advanced editor page with errors, give them a warning. + if (this.validatorErrors.length !== 0) { + alert(this.$t('editor.slides.advanced.error')); + } } } diff --git a/src/lang/lang.csv b/src/lang/lang.csv index 9b4d8001..d5a3bbc1 100644 --- a/src/lang/lang.csv +++ b/src/lang/lang.csv @@ -134,6 +134,10 @@ editor.slides.leftPanel,Left panel,1,Panneau de gauche,1 editor.slides.rightPanel,Right panel,1,Panneau de droite,1 editor.slides.fullscreenPanel,Fullscreen panel,1,Panneau plein écran,1 editor.slides.advanced,Advanced,1,Avancé,0 +editor.slides.advanced.good,Configuration adheres to Storylines schema.,1,La configuration adhère au schéma Storylines.,0 +editor.slides.advanced.broken,This configuration violates the Storylines schema.,1,Cette configuration viole le schéma Storylines.,0 +editor.slides.advanced.details,Click here for more details.,1,Cliquez ici pour plus de détails.,0 +editor.slides.advanced.error,This configuration contains one or more errors. Leaving it as-is may cause unexpected behaviour in the editor and published product.,1,Cette configuration contient une ou plusieurs erreurs. La laisser telle quelle peut entraîner un comportement inattendu dans l'éditeur et dans le produit publié.,0 editor.slides.contentType,Content type,1,Type de contenu,1 editor.slides.content,Content,1,Contenu,1 editor.slides.select,Please select a slide to edit,1,Veuillez sélectionner une diapositive à modifier,1