diff --git a/cypress/e2e/datasets/datasets-publish.cy.js b/cypress/e2e/datasets/datasets-publish.cy.js index d55a09442..14a1f29b3 100644 --- a/cypress/e2e/datasets/datasets-publish.cy.js +++ b/cypress/e2e/datasets/datasets-publish.cy.js @@ -37,7 +37,7 @@ describe("Datasets", () => { cy.get("#abstractInput").type("some abstract text"); - cy.get("#publishButton").click(); + cy.get("#saveAndContinueButton").click(); cy.get("#doiRow").should("exist"); }); diff --git a/cypress/e2e/published-data/published-data.cy.js b/cypress/e2e/published-data/published-data.cy.js new file mode 100644 index 000000000..cb866ced5 --- /dev/null +++ b/cypress/e2e/published-data/published-data.cy.js @@ -0,0 +1,572 @@ +import { testData } from "../../fixtures/testData"; + +describe("Datasets general", () => { + const title = "publishedDataTitle"; + const abstract = "publishedDataAbstract"; + const userPublishedDataTitle = "userSpecificPublishedDataTitle"; + const userPublishedDataAbstract = "userSpecificPublishedDataAbstract"; + beforeEach(() => { + cy.login(Cypress.env("username"), Cypress.env("password")); + }); + + after(() => { + cy.removeDatasets(); + }); + + describe("Published data creation, update and registration", () => { + it("should be able to create new published data in private state", () => { + cy.createDataset("raw"); + + cy.visit("/datasets"); + + cy.get(".dataset-table mat-table mat-header-row").should("exist"); + + cy.finishedLoading(); + + cy.get('[data-cy="text-search"] input[type="search"]') + .clear() + .type("Cypress"); + + cy.isLoading(); + + cy.get(".dataset-table mat-row input[type='checkbox']").first().click(); + + cy.get("#addToBatchButton").click(); + + cy.get("#cartOnHeaderButton").click(); + + cy.get("a.button").click(); + + cy.get("#publishButton").click(); + + cy.get("#titleInput").type(title); + + cy.get("#abstractInput").type(abstract); + + cy.get("#saveAndContinueButton").click(); + + cy.get("#doiRow").should("exist"); + + cy.get("[data-cy='status']").contains("private"); + }); + + it("should prevent leaving published data form unsaved", () => { + cy.createDataset("raw"); + + cy.visit("/datasets"); + + cy.get(".dataset-table mat-table mat-header-row").should("exist"); + + cy.finishedLoading(); + + cy.get('[data-cy="text-search"] input[type="search"]') + .clear() + .type("Cypress"); + + cy.isLoading(); + + cy.get(".dataset-table mat-row input[type='checkbox']").first().click(); + + cy.get("#addToBatchButton").click(); + + cy.get("#cartOnHeaderButton").click(); + + cy.get("a.button").click(); + + cy.get("#publishButton").click(); + + cy.get("#titleInput").type(title); + + cy.get("#abstractInput").type(abstract); + + cy.get("#cancelButton").click(); + + cy.on("window:confirm", (str) => { + expect(str).to.equal( + "You have unsaved changes. Press Cancel to go back and save these changes, or OK to leave without saving.", + ); + + return false; + }); + + cy.get("#saveButton").click(); + + cy.get("#cancelButton").click(); + + cy.get('[data-cy="batch-table"] mat-row').should("exist"); + }); + + it("should be able to edit dataset list after creating the published data", () => { + cy.createDataset("raw"); + cy.createDataset("raw"); + + cy.visit("/datasets"); + + cy.get(".dataset-table mat-table mat-header-row").should("exist"); + + cy.finishedLoading(); + + cy.get('[data-cy="text-search"] input[type="search"]') + .clear() + .type("Cypress"); + + cy.isLoading(); + + cy.get(".dataset-table mat-row input[type='checkbox']").first().click(); + + cy.get("#addToBatchButton").click(); + + cy.get("#cartOnHeaderButton").click(); + + cy.get("a.button").click(); + + cy.get("#publishButton").click(); + + cy.get("#titleInput").type(title); + + cy.get("#abstractInput").type(abstract); + + cy.get("#saveButton").click(); + + cy.get("#cancelButton").click(); + + cy.get('[data-cy="batch-table"] mat-row').should("exist"); + + cy.visit("/datasets"); + + cy.get(".dataset-table mat-table mat-header-row").should("exist"); + + cy.finishedLoading(); + + cy.get('[data-cy="text-search"] input[type="search"]') + .clear() + .type("Cypress"); + + cy.isLoading(); + + cy.get(".dataset-table mat-row input[type='checkbox']").last().click(); + + cy.get("#addToBatchButton").click(); + + cy.get("#cartOnHeaderButton").click(); + + cy.get("a.button").click(); + + cy.get('[data-cy="batch-table"] mat-row').its("length").should("eq", 2); + + cy.get("#saveChangesButton").click(); + + cy.get('[data-cy="editPublishedDataForm"]').should("exist"); + cy.get("#titleInput").should("have.value", title); + cy.get("#abstractInput").should("have.value", abstract); + }); + + it("other users should not be able to see private published data that they do not own", () => { + cy.login(Cypress.env("guestUsername"), Cypress.env("guestPassword")); + const title = "some title text"; + + cy.visit("/publishedDatasets"); + + cy.get("app-publisheddata-dashboard mat-table mat-header-row").should( + "exist", + ); + + cy.finishedLoading(); + + cy.get('input[formcontrolname="globalSearch"]').clear().type(title); + + cy.isLoading(); + + cy.get("app-publisheddata-dashboard mat-table mat-row").should( + "not.contain", + title, + ); + }); + + it("should not be able to publish invalid private published data", () => { + cy.visit("/publishedDatasets"); + + cy.get("app-publisheddata-dashboard mat-table mat-header-row").should( + "exist", + ); + + cy.finishedLoading(); + + cy.get('input[formcontrolname="globalSearch"]').clear().type(title); + + cy.isLoading(); + + cy.get("app-publisheddata-dashboard mat-table mat-row") + .contains(title) + .first() + .click(); + + cy.get('[data-cy="status"]').contains("private"); + + cy.get('[data-cy="publishButton"]').click(); + + cy.get("simple-snack-bar").should( + "contain", + 'Publishing Failed. metadata requires property "creators"', + ); + }); + + it("admins should be able to edit their private published data", () => { + const creatorName = "Creator name"; + const resourceType = "resource type"; + const publisherName = "publisher name"; + const publisherIndetifierScheme = "publisher identifier scheme"; + cy.visit("/publishedDatasets"); + + cy.get("app-publisheddata-dashboard mat-table mat-header-row").should( + "exist", + ); + + cy.finishedLoading(); + + cy.get('input[formcontrolname="globalSearch"]').clear().type(title); + + cy.isLoading(); + + cy.get("app-publisheddata-dashboard mat-table mat-row") + .contains(title) + .first() + .click(); + + cy.get('[data-cy="status"]').contains("private"); + + cy.get("#editBtn").click(); + + cy.get('[data-cy="editPublishedDataForm"]').should("exist"); + + cy.get('[data-cy="metadata"]').click(); + cy.get("jsonforms").should("exist"); + + cy.get("button.save-and-continue").should("be.disabled"); + + cy.get('[aria-label="Add to Creators button"]').click(); + + cy.get('[aria-label="Add to Creators button"]') + .closest(".array-layout") + .find('input[id^="#/properties/name"]') + .first() + .clear() + .type(creatorName); + + cy.get('[id="#/properties/resourceType"]').clear().type(resourceType); + + cy.get('[ng-reflect-path="publisher"]') + .parent() + .find('[id="#/properties/name"]') + .clear() + .type(publisherName); + + cy.get('[ng-reflect-path="publisher"]') + .parent() + .should("contain", "is a required property"); + cy.get('[ng-reflect-path="publisher"]') + .parent() + .find('input[id="#/properties/publisherIdentifierScheme"]') + .clear() + .type(publisherIndetifierScheme); + + cy.get("button.save-and-continue").should("not.be.disabled"); + + cy.get("button.save-and-continue").click(); + + cy.get('[data-cy="status"]').contains("private"); + + cy.get('[data-cy="showHideMetadata"]').click(); + + cy.get("ngx-json-viewer section").contains("metadata").click(); + + cy.get("ngx-json-viewer section").contains(creatorName); + cy.get("ngx-json-viewer section").contains(publisherName); + cy.get("ngx-json-viewer section").contains(publisherIndetifierScheme); + cy.get("ngx-json-viewer section").contains(resourceType); + }); + + it("should be able to edit dataset list after creating the published data", () => { + const newDatasetName = "Test dataset name"; + cy.createDataset("raw", newDatasetName); + cy.visit("/publishedDatasets"); + + cy.get("app-publisheddata-dashboard mat-table mat-header-row").should( + "exist", + ); + + cy.finishedLoading(); + + cy.get('input[formcontrolname="globalSearch"]').clear().type(title); + + cy.isLoading(); + + cy.get("app-publisheddata-dashboard mat-table mat-row") + .contains(title) + .first() + .click(); + + cy.get('[data-cy="status"]').contains("private"); + + cy.get('[data-cy="editDatasetList"]').click(); + + cy.get('[data-cy="batch-table"] mat-row').should("exist"); + + cy.visit("/datasets"); + + cy.get(".dataset-table mat-table mat-header-row").should("exist"); + + cy.finishedLoading(); + + cy.get('[data-cy="text-search"] input[type="search"]') + .clear() + .type(newDatasetName); + + cy.isLoading(); + + cy.get(".dataset-table mat-row input[type='checkbox']").first().click(); + + cy.get("#addToBatchButton").click(); + + cy.get("#cartOnHeaderButton").click(); + + cy.get("a.button").click(); + + cy.get('[data-cy="batch-table"] mat-row').its("length").should("eq", 3); + + cy.get("#saveChangesButton").click(); + }); + + it("should be able to publish their private published data", () => { + cy.visit("/publishedDatasets"); + + cy.get("app-publisheddata-dashboard mat-table mat-header-row").should( + "exist", + ); + + cy.finishedLoading(); + + cy.get('input[formcontrolname="globalSearch"]').clear().type(title); + + cy.isLoading(); + + cy.get("app-publisheddata-dashboard mat-table mat-row") + .contains(title) + .first() + .click(); + + cy.get('[data-cy="status"]').contains("private"); + + cy.get('[data-cy="publishButton"]').click(); + + cy.get('[data-cy="status"]').contains("public"); + }); + + it("should not be able to edit dataset list on a published data that is public", () => { + cy.visit("/publishedDatasets"); + + cy.get("app-publisheddata-dashboard mat-table mat-header-row").should( + "exist", + ); + + cy.finishedLoading(); + + cy.get('input[formcontrolname="globalSearch"]').clear().type(title); + + cy.isLoading(); + + cy.get("app-publisheddata-dashboard mat-table mat-row") + .contains(title) + .first() + .click(); + + cy.get('[data-cy="status"]').contains("public"); + + cy.get("#editDatasetList").should("not.exist"); + }); + + it("other users should be able to see public published data that they do not own", () => { + cy.login(Cypress.env("guestUsername"), Cypress.env("guestPassword")); + cy.visit("/publishedDatasets"); + + cy.get("app-publisheddata-dashboard mat-table mat-header-row").should( + "exist", + ); + + cy.finishedLoading(); + + cy.get('input[formcontrolname="globalSearch"]').clear().type(title); + + cy.isLoading(); + + cy.get("app-publisheddata-dashboard mat-table mat-row").should( + "contain", + title, + ); + }); + + it("should be able to register their public published data", () => { + cy.visit("/publishedDatasets"); + + cy.get("app-publisheddata-dashboard mat-table mat-header-row").should( + "exist", + ); + + cy.finishedLoading(); + + cy.get('input[formcontrolname="globalSearch"]').clear().type(title); + + cy.isLoading(); + + cy.get("app-publisheddata-dashboard mat-table mat-row") + .contains(title) + .first() + .click(); + + cy.get('[data-cy="status"]').contains("public"); + + cy.get('[data-cy="registerButton"]').click(); + + cy.get('[data-cy="status"]').contains("registered"); + }); + + it("regular users should be able to create and edit their private published data but not after it gets public", () => { + cy.login(Cypress.env("guestUsername"), Cypress.env("guestPassword")); + const creatorName = "Creator name"; + const resourceType = "resource type"; + const publisherName = "publisher name"; + const publisherIndetifierScheme = "publisher identifier scheme"; + cy.createDataset("raw"); + + cy.visit("/datasets"); + + cy.get(".dataset-table mat-table mat-header-row").should("exist"); + + cy.finishedLoading(); + + cy.get('[data-cy="text-search"] input[type="search"]') + .clear() + .type("Cypress"); + + cy.isLoading(); + + cy.get(".dataset-table mat-row input[type='checkbox']").first().click(); + + cy.get("#addToBatchButton").click(); + + cy.get("#cartOnHeaderButton").click(); + + cy.get("a.button").click(); + + cy.get("#publishButton").click(); + + cy.get("#titleInput").type(userPublishedDataTitle); + + cy.get("#abstractInput").type(userPublishedDataAbstract); + + cy.get("#saveAndContinueButton").click(); + + cy.get("#doiRow").should("exist"); + + cy.get("[data-cy='status']").contains("private"); + + cy.get("#editBtn").click(); + + cy.get('[data-cy="editPublishedDataForm"]').should("exist"); + + cy.get('[data-cy="metadata"]').click(); + cy.get("jsonforms").should("exist"); + + cy.get("button.save-and-continue").should("be.disabled"); + + cy.get('[aria-label="Add to Creators button"]').click(); + + cy.get('[aria-label="Add to Creators button"]') + .closest(".array-layout") + .find('input[id^="#/properties/name"]') + .first() + .clear() + .type(creatorName); + + cy.get('[id="#/properties/resourceType"]').clear().type(resourceType); + + cy.get('[ng-reflect-path="publisher"]') + .parent() + .find('[id="#/properties/name"]') + .clear() + .type(publisherName); + + cy.get('[ng-reflect-path="publisher"]') + .parent() + .should("contain", "is a required property"); + cy.get('[ng-reflect-path="publisher"]') + .parent() + .find('input[id="#/properties/publisherIdentifierScheme"]') + .clear() + .type(publisherIndetifierScheme); + + cy.get("button.save-and-continue").should("not.be.disabled"); + + cy.get("button.save-and-continue").click(); + + cy.get('[data-cy="status"]').contains("private"); + + cy.get('[data-cy="publishButton"]').click(); + + cy.get('[data-cy="status"]').contains("public"); + + cy.get("#editBtn").should("not.exist"); + }); + + it("admins should be able to edit public published data", () => { + const newCreatorName = "new creator name"; + cy.visit("/publishedDatasets"); + + cy.get("app-publisheddata-dashboard mat-table mat-header-row").should( + "exist", + ); + + cy.finishedLoading(); + + cy.get('input[formcontrolname="globalSearch"]') + .clear() + .type(userPublishedDataTitle); + + cy.isLoading(); + + cy.get("app-publisheddata-dashboard mat-table mat-row") + .contains(userPublishedDataTitle) + .first() + .click(); + + cy.get('[data-cy="status"]').contains("public"); + + cy.get("#editBtn").click(); + + cy.get('[data-cy="editPublishedDataForm"]').should("exist"); + + cy.get('[data-cy="metadata"]').click(); + cy.get("jsonforms").should("exist"); + + cy.get("button.save-and-continue").should("not.be.disabled"); + + cy.get('[aria-label="Add to Creators button"]') + .closest(".array-layout") + .find('input[id^="#/properties/name"]') + .first() + .clear() + .type(newCreatorName); + + cy.get("button.save-and-continue").should("not.be.disabled"); + + cy.get("button.save-and-continue").click(); + + cy.get('[data-cy="status"]').contains("public"); + + cy.get('[data-cy="showHideMetadata"]').click(); + + cy.get("ngx-json-viewer section").contains("metadata").click(); + cy.get("ngx-json-viewer section").contains(newCreatorName); + }); + }); +}); diff --git a/package-lock.json b/package-lock.json index cd40bb147..9614c007c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,9 @@ "@angular/platform-server": "^19.2.8", "@angular/router": "^19.2.8", "@angular/service-worker": "^19.2.8", + "@jsonforms/angular": "^3.5.1", + "@jsonforms/angular-material": "^3.5.1", + "@jsonforms/core": "^3.5.1", "@ngbracket/ngx-layout": "^16.0.0", "@ngrx/effects": "^19.1.0", "@ngrx/operators": "^19.1.0", @@ -4126,6 +4129,70 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jsonforms/angular": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@jsonforms/angular/-/angular-3.5.1.tgz", + "integrity": "sha512-qbMblz/G/kWOol1n6iMYUA81ndzQe80p788VyMsm6dJ5edTrqpvWVK8vjLkzWZtH5kbFrg/nkYaI/f6XsP1Chw==", + "dependencies": { + "lodash": "^4.17.21" + }, + "peerDependencies": { + "@angular/core": "^18.0.0 || ^19.0.0", + "@angular/forms": "^18.0.0 || ^19.0.0", + "@jsonforms/core": "3.5.1", + "rxjs": "^6.6.0 || ^7.4.0" + } + }, + "node_modules/@jsonforms/angular-material": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@jsonforms/angular-material/-/angular-material-3.5.1.tgz", + "integrity": "sha512-x2j3B3XG1uL3aU8gzo3iRSSRPuRBzceI4Do1itXn016h3S1JT5sDtI7NWvZ+K6TQN4YGuWypaXuBm2y686DKpw==", + "dependencies": { + "hammerjs": "2.0.8", + "lodash": "^4.17.21" + }, + "peerDependencies": { + "@angular/animations": "^18.0.0 || ^19.0.0", + "@angular/cdk": "^18.0.0 || ^19.0.0", + "@angular/common": "^18.0.0 || ^19.0.0", + "@angular/core": "^18.0.0 || ^19.0.0", + "@angular/forms": "^18.0.0 || ^19.0.0", + "@angular/material": "^18.0.0 || ^19.0.0", + "@angular/platform-browser": "^18.0.0 || ^19.0.0", + "@angular/router": "^18.0.0 || ^19.0.0", + "@jsonforms/angular": "3.5.1", + "@jsonforms/core": "3.5.1", + "dayjs": "^1.11.10", + "rxjs": "^6.6.0 || ^7.4.0" + } + }, + "node_modules/@jsonforms/core": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@jsonforms/core/-/core-3.5.1.tgz", + "integrity": "sha512-Jrq/UcfvKsAprLJ+9TMFa8pKsfdyv3dAw85XstSNRcjDT19LreBlhVqIvTvtgZidg8Iet3yqy5xlNnB+XyrvrQ==", + "dependencies": { + "@types/json-schema": "^7.0.3", + "ajv": "^8.6.1", + "ajv-formats": "^2.1.0", + "lodash": "^4.17.21" + } + }, + "node_modules/@jsonforms/core/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/@jsonjoy.com/base64": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", @@ -6128,8 +6195,7 @@ "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" }, "node_modules/@types/lodash": { "version": "4.17.16", @@ -7205,7 +7271,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -10611,8 +10676,7 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-diff": { "version": "1.3.0", @@ -10670,7 +10734,6 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", - "dev": true, "funding": [ { "type": "github", @@ -11326,6 +11389,14 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "node_modules/hammerjs": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", + "integrity": "sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -12697,8 +12768,7 @@ "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -13565,8 +13635,7 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "node_modules/lodash-es": { "version": "4.17.21", @@ -16164,7 +16233,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, "engines": { "node": ">=0.10.0" } diff --git a/package.json b/package.json index 4b661b41a..886d67ab6 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,9 @@ "@angular/platform-server": "^19.2.8", "@angular/router": "^19.2.8", "@angular/service-worker": "^19.2.8", + "@jsonforms/angular": "^3.5.1", + "@jsonforms/angular-material": "^3.5.1", + "@jsonforms/core": "^3.5.1", "@ngbracket/ngx-layout": "^16.0.0", "@ngrx/effects": "^19.1.0", "@ngrx/operators": "^19.1.0", diff --git a/src/app/app-routing/lazy/datasets-routing/datasets.routing.module.ts b/src/app/app-routing/lazy/datasets-routing/datasets.routing.module.ts index d1637dbd5..6715b60a4 100644 --- a/src/app/app-routing/lazy/datasets-routing/datasets.routing.module.ts +++ b/src/app/app-routing/lazy/datasets-routing/datasets.routing.module.ts @@ -1,6 +1,7 @@ import { NgModule } from "@angular/core"; import { RouterModule, Routes } from "@angular/router"; import { AuthGuard } from "app-routing/auth.guard"; +import { leavingPageGuard } from "app-routing/pending-changes.guard"; import { BatchViewComponent } from "datasets/batch-view/batch-view.component"; import { DashboardComponent } from "datasets/dashboard/dashboard.component"; import { DatablocksComponent } from "datasets/datablocks-table/datablocks-table.component"; @@ -21,6 +22,7 @@ const routes: Routes = [ path: "batch/publish", component: PublishComponent, canActivate: [AuthGuard], + canDeactivate: [leavingPageGuard], }, { path: ":id", diff --git a/src/app/app-routing/lazy/publisheddata-routing/publisheddata.routing.module.ts b/src/app/app-routing/lazy/publisheddata-routing/publisheddata.routing.module.ts index f8e37f935..a14e5fec2 100644 --- a/src/app/app-routing/lazy/publisheddata-routing/publisheddata.routing.module.ts +++ b/src/app/app-routing/lazy/publisheddata-routing/publisheddata.routing.module.ts @@ -1,6 +1,7 @@ import { NgModule } from "@angular/core"; import { RouterModule, Routes } from "@angular/router"; import { AuthGuard } from "app-routing/auth.guard"; +import { leavingPageGuard } from "app-routing/pending-changes.guard"; import { PublisheddataDashboardComponent } from "publisheddata/publisheddata-dashboard/publisheddata-dashboard.component"; import { PublisheddataDetailsComponent } from "publisheddata/publisheddata-details/publisheddata-details.component"; import { PublisheddataEditComponent } from "publisheddata/publisheddata-edit/publisheddata-edit.component"; @@ -20,6 +21,7 @@ const routes: Routes = [ path: ":id/edit", component: PublisheddataEditComponent, canActivate: [AuthGuard], + canDeactivate: [leavingPageGuard], }, ]; @NgModule({ diff --git a/src/app/datasets/batch-view/batch-view.component.html b/src/app/datasets/batch-view/batch-view.component.html index cce14bc9f..15a49a181 100644 --- a/src/app/datasets/batch-view/batch-view.component.html +++ b/src/app/datasets/batch-view/batch-view.component.html @@ -1,11 +1,45 @@