diff --git a/.eslintrc.json b/.eslintrc.json
index f93cd6e7bf..97d9fbec73 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -50,7 +50,12 @@
}
}
],
+ "rules": {
+ "prettier/prettier": "error"
+ },
+ "plugins": ["prettier"],
"extends": [
- "plugin:storybook/recommended"
+ "plugin:storybook/recommended",
+ "prettier"
]
}
diff --git a/.github/workflows/master-push.yml b/.github/workflows/master-push.yml
index 5436506d5c..8e2b17ee24 100644
--- a/.github/workflows/master-push.yml
+++ b/.github/workflows/master-push.yml
@@ -65,18 +65,3 @@ jobs:
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: snyk.sarif
- run-e2e-tests:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - name: Cypress run
- uses: cypress-io/github-action@v4
- with:
- command: npm run e2e
- env:
- # pass the Dashboard record key as an environment variable
- CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
- # pass GitHub token to allow accurately detecting a build vs a re-run build
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- # pass the project ID from the secrets through environment variable
- CYPRESS_PROJECT_ID: ${{ secrets.CYPRESS_PROJECT_ID }}
diff --git a/.github/workflows/pull-request-update.yml b/.github/workflows/pull-request-update.yml
index a205fcff60..a93fbca683 100644
--- a/.github/workflows/pull-request-update.yml
+++ b/.github/workflows/pull-request-update.yml
@@ -73,15 +73,3 @@ jobs:
cd /var/docker/pr-${{ github.event.number }}
docker compose pull
docker compose up -d
- run-e2e-tests:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - name: Cypress run
- uses: cypress-io/github-action@v5
- with:
- command: npm run e2e
- env:
- COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title }}
- # pass GitHub token to allow accurately detecting a build vs a re-run build
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 0000000000..0567403f9e
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,16 @@
+{
+ "overrides": [
+ {
+ "files": "*.html",
+ "options": {
+ "parser": "html"
+ }
+ },
+ {
+ "files": "*.component.html",
+ "options": {
+ "parser": "angular"
+ }
+ }
+ ]
+}
diff --git a/build/Dockerfile b/build/Dockerfile
index 5407c2439a..71006776cc 100644
--- a/build/Dockerfile
+++ b/build/Dockerfile
@@ -70,7 +70,7 @@ RUN if [ "$SENTRY_AUTH_TOKEN" != "" ] ; then \
### PROD image
-FROM nginx:1.25.2-alpine
+FROM nginx:1.25.3-alpine
COPY ./build/default.conf /etc/nginx/templates/default.conf
COPY --from=builder /app/dist/ /usr/share/nginx/html
# The port on which the app will run in the Docker container
diff --git a/doc/compodoc_sources/concepts/configuration.md b/doc/compodoc_sources/concepts/configuration.md
index 442393ebdc..863f5fc87e 100644
--- a/doc/compodoc_sources/concepts/configuration.md
+++ b/doc/compodoc_sources/concepts/configuration.md
@@ -35,7 +35,9 @@ The config service provides a behavior subject which will notify all subscribers
This can be used for core tasks like setting up the routes or creating the navigation bar.
Top-level "view" components (i.e. components that are used to define a whole page, not just some building block for a part or section)
-receive their config data through the standard Angular router and can access it by injecting `ActivatedRoute`.
+receive their config data automatically assigned as `@Input()` properties mapped from config object property name to an identical component class property.
+This is handled by the `RoutedViewComponent` internally.
+(If needed for special cases, you can also access it through the standard Angular router and can access it by injecting `ActivatedRoute`.)
### Storing config in DB
diff --git a/doc/compodoc_sources/concepts/entities.md b/doc/compodoc_sources/concepts/entities.md
new file mode 100644
index 0000000000..0a26de0dae
--- /dev/null
+++ b/doc/compodoc_sources/concepts/entities.md
@@ -0,0 +1,10 @@
+# Entities & Entity Schema
+-----
+For us, an "Entity" is an object in the database (and a representation of something in the user's real world, e.g. a "Child" or "School").
+Entities are at the core of the Aam Digital platform and the primary way to customize the system is to adapt and add new entity types.
+
+The Entity Schema defines the data structure as well as how it is displayed in the UI.
+Entity instances also have some generic functionality inherited from the `Entity` base class.
+
+------
+_see the sub-pages here for details of the various concepts related to the Entity system_
diff --git a/doc/compodoc_sources/concepts/entity-anonymization.md b/doc/compodoc_sources/concepts/entity-anonymization.md
new file mode 100644
index 0000000000..421b176ea0
--- /dev/null
+++ b/doc/compodoc_sources/concepts/entity-anonymization.md
@@ -0,0 +1,39 @@
+# Archive / Anonymize Entities
+-----
+Any entity can be archived (i.e. marked as inactive and hidden from UI by default) or anonymized (i.e. discarding most data and keeping a few selected properties for statistical reports).
+This is often preferable to deleting a record completely. Deleting data also affects statistical reports, even for previous time periods.
+By anonymizing records, all personal identifiable data can be removed and the remaining stub record can be stored indefinitely, as it is not subject to data protection regulations like GDPR anymore.
+
+Anonymization is configured as part of the entity schema.
+Data of fields that are not explicitly marked to be retained during anonymization is always deleted (anonymization by default).
+
+To keep some data even after the user "anonymized" a record, configure the `anonymize` property of the `@DatabaseField` decorator:
+- `anonymize: "retain"` will keep this field unchanged and prevent it from being deleted
+- `anonymize: "retain-anonymized"` will trigger a special "partial" deletion that depends on the dataType (e.g. date types will be changed to 1st July of the given year, thereby largely removing details but keeping data to calculate a rough age)
+
+
+## Cascading anonymization / deletion
+Relationships between entities are automatically handled when the user anonymizes or deletes an entity.
+Any related entities that reference the anonymized/deleted entity are checked
+and - depending on their configured role - may be updated or anonymized as well.
+
+The logic follows the scenarios shown below:
+
+
+
+## Data Protection & GDPR regarding anonymization / pseudonomyzation
+The "anonymize" function is implemented specifically for data protection rules requiring to delete personal data.
+According to the EU's "General Data Protection Regulation" (GDPR) "anonymous" data does not fall under its regulations:
+
+- GDPR is not applicable to anonymous data: "The principles of data protection should therefore not apply to [...] personal data rendered anonymous in such a manner that the data subject is not or no longer identifiable." [GDPR Recital 26 ](https://gdpr-info.eu/recitals/no-26/)
+ - "To determine whether a natural person is identifiable, account should be taken of all the means reasonably likely to be used, such as singling out, either by the controller or by another person to identify the natural person directly or indirectly."
+ - "To ascertain whether means are reasonably likely to be used to identify the natural person, account should be taken of all objective factors, such as the costs of and the amount of time required for identification, taking into consideration the available technology at the time of the processing and technological developments."
+- "Pseudonymisation enables the personal data to become unidentifiable unless more information is available whereas anonymization allows the processing of personal data to irreversibly prevent re-identification." [source ](https://www.privacycompany.eu/blogpost-en/what-are-the-differences-between-anonymisation-and-pseudonymisation)
+- _also see this [good overview of anonymization misunderstandings and considerations](https://edps.europa.eu/system/files/2021-04/21-04-27_aepd-edps_anonymisation_en_5.pdf)_
+
+In the case of records being retained "anonymized" in Aam Digital, we provide a context that makes re-identification even harder:
+- only authorized users of the system can access even the anonymized record (where only a few properties have been retained). Unless the organisation actively shares the data, it remains as securely protected as the personal data managed in Aam Digital.
+- those authorized users with access to the anonymized records (and therefor a theoretical chance to attempt re-identification) are team members of an organization. They have been screened to be responsible persons and are usually legally bound to keep information confidential.
+- by default only a few, explicitly selected properties in anonymized records are retained (data minimization by default). As such, both re-identification likelihood and the impact in case of re-identification are reduced as far as possible.
+
+--> If our anonymization process is configured thoughfully on a case by case basis to only retain a few data fields that are not easy indirect identifiers, it seems reasonably unlikely that the person can be identified after the anonymization process. Therefore, GDPR should not apply to these records and it is legitimate to retain these for statistical reporting.
diff --git a/doc/compodoc_sources/concepts/entity-schema-system.md b/doc/compodoc_sources/concepts/entity-schema-system.md
index cd9a715ae1..9d55ab7aad 100644
--- a/doc/compodoc_sources/concepts/entity-schema-system.md
+++ b/doc/compodoc_sources/concepts/entity-schema-system.md
@@ -1,8 +1,6 @@
# Entity Schema
-----
The Entity Schema defines details of the properties of an entity type.
-(An "entity" is an object of a certain type that users work with and save to the database, like "Child" or "School")
-
We define an entity type and its schema in code through a plain TypeScript class and some custom annotations.
Read more on the background and practical considerations in [How to create a new Entity Type](../how-to-guides/create-a-new-entity-type.html).
@@ -45,9 +43,16 @@ providing these through Angular dependency injection using `multi: true`.
Also see: [How to create a new Datatype](../how-to-guides/create-a-new-datatype.html).
-## Schema options
+### Schema options
The schema definitions contains information regarding the schema transformation as well as how a property can be displayed.
The [EntitySchemaField](../../interfaces/EntitySchemaField.html) interface shows all configuration options.
If the `editComponent` and the `viewComponent` are not set, the default components of this property's datatype will be used.
The `description` field allows adding further explanation which will be displayed as a tooltip.
+
+
+## Generic Entity functionalities
+
+### Metadata (created, updated)
+Each record automatically holds basic data of timestamp and user who created and last updated the record.
+(see `Entity` class)
diff --git a/doc/compodoc_sources/concepts/extendability.md b/doc/compodoc_sources/concepts/extendability.md
index ac6b8a8c29..de01065883 100644
--- a/doc/compodoc_sources/concepts/extendability.md
+++ b/doc/compodoc_sources/concepts/extendability.md
@@ -19,6 +19,7 @@ The following aspects are specifically designed to be extended:
- defining a screen completely, including data loaded, etc. and hook it into the platforms navigation and overall layout
- **Sub-Views**
- defining a screen to display custom details for the entity currently loaded in the active route. The core platform takes care of passing the current entity and config details to the view as inputs.
+ - *also see [How to create an Entity Details Panel](../how-to-guides/create-an-entity-details-panel.html)*
- **Dashboard Widgets**
- filling the given card template with custom data and visualization
- **Filters**
diff --git a/doc/compodoc_sources/how-to-guides/create-entity-details-panel.md b/doc/compodoc_sources/how-to-guides/create-entity-details-panel.md
new file mode 100644
index 0000000000..c288856047
--- /dev/null
+++ b/doc/compodoc_sources/how-to-guides/create-entity-details-panel.md
@@ -0,0 +1,46 @@
+# How to create an Entity Details Panel Component
+Aam Digital as a platform takes care of loading the relevant entity and configs for an "Entity Details View",
+which displays the information about a single entity (e.g. one specific student).
+The `EntityDetailsComponent` handles this initialization from the route.
+To display some details in a customized way, you can create "panel components" that receive a reference to the current entity and their config parameters as `@Input()` automatically.
+
+
+The tabs (in the config called "panels") within the Entity Details view can display one or more "panel components", as shown above.
+
+To make these components as re-usable and simple as possible, we do not load config from the route here.
+Instead, the components are initialized from config by the `DynamicComponentDirective`.
+This automatically sets `@Input()` properties to the value with the same name in the config object.
+
+Those background details aside, what that means for your implementation is:
+
+## Implementing a new Panel Component
+
+1. Create a new component class
+2. Add an `@Input() entity: Entity;`. This will always contain the entity object, whose Details View is currently being displayed. You should not load this yourself from the database.
+3. (If needed) Add more inputs for aspects that should be configurable about your component.
+(e.g. `@Input() showDescription: boolean;`, which you can use in your template or code to adapt the component.)
+These values are automatically set to whatever value is specified in the config object for your component at runtime in the database.
+4. Register the new component in its parent module, so that it can be loaded under its name through the config.
+
+An example config for the above:
+```json
+{
+ "component": "MySubView",
+ "config": { "showDescription": true }
+}
+```
+
+Use the `ComponentRegistry` to register your component,
+e.g. in its Module:
+```javascript
+export class MyModule {
+ constructor(components: ComponentRegistry) {
+ components.addAll([
+ [
+ "MySubView", // this is the name to use in the config document
+ () => import("./my-sub-view/my-sub-view.component").then((c) => c.MySubViewComponent),
+ ],
+ ]);
+ }
+}
+```
diff --git a/doc/compodoc_sources/summary.json b/doc/compodoc_sources/summary.json
index 90c9d2796e..244192ddaa 100644
--- a/doc/compodoc_sources/summary.json
+++ b/doc/compodoc_sources/summary.json
@@ -38,8 +38,18 @@
"file": "concepts/extendability.md"
},
{
- "title": "Entity Schema",
- "file": "concepts/entity-schema-system.md"
+ "title": "Entity System",
+ "file": "concepts/entities.md",
+ "children": [
+ {
+ "title": "Entity Schema",
+ "file": "concepts/entity-schema-system.md"
+ },
+ {
+ "title": "Archiving, Anonymizing and Deleting Entities",
+ "file": "concepts/entity-anonymization.md"
+ }
+ ]
},
{
"title": "Configuration",
@@ -75,6 +85,28 @@
"title": "How-To Guides",
"file": "how-to-guides/_index.md",
"children": [
+ {
+ "title": "Development Processes",
+ "file": "how-to-guides/contribute-code.md",
+ "children": [
+ {
+ "title": "Write Automated Unit Tests",
+ "file": "how-to-guides/write-unit-tests.md"
+ },
+ {
+ "title": "Write E2E Tests",
+ "file": "how-to-guides/write-e2e-tests.md"
+ },
+ {
+ "title": "Document Code",
+ "file": "how-to-guides/write-documentation.md"
+ },
+ {
+ "title": "Review a Pull Request",
+ "file": "how-to-guides/review-pull-request.md"
+ }
+ ]
+ },
{
"title": "Configure and Customize a System",
"file": "how-to-guides/configure-custom-system.md"
@@ -83,14 +115,14 @@
"title": "Navigate the Code Structure",
"file": "how-to-guides/navigate-code-structure.md"
},
- {
- "title": "Contribute Code to the Project",
- "file": "how-to-guides/contribute-code.md"
- },
{
"title": "Create a New Entity Type",
"file": "how-to-guides/create-new-entity-type.md"
},
+ {
+ "title": "Create an Entity Details Panel",
+ "file": "how-to-guides/create-entity-details-panel.md"
+ },
{
"title": "Create a New Datatype",
"file": "how-to-guides/create-new-datatype.md"
@@ -115,18 +147,6 @@
"title": "Log Errors",
"file": "how-to-guides/log-errors.md"
},
- {
- "title": "Write Automated Unit Tests",
- "file": "how-to-guides/write-unit-tests.md"
- },
- {
- "title": "Write E2E Tests",
- "file": "how-to-guides/write-e2e-tests.md"
- },
- {
- "title": "Document Code",
- "file": "how-to-guides/write-documentation.md"
- },
{
"title": "Use Queries and Indices",
"file": "how-to-guides/use-queries-and-indices.md"
@@ -135,25 +155,23 @@
"title": "Generate Demo Data",
"file": "how-to-guides/generate-demo-data.md"
},
- {
- "title": "Review a Pull Request",
- "file": "how-to-guides/review-pull-request.md"
- },
{
"title": "Format Data Export",
"file": "how-to-guides/exports.md"
},
{
- "title": "Build Localizable Components",
- "file": "how-to-guides/build-localizable-components.md"
- },
- {
- "title": "Work with XLF",
- "file": "how-to-guides/work-with-xlf.md"
- },
- {
- "title": "Add Another Language",
- "file": "how-to-guides/add-another-language.md"
+ "title": "Build localizable (translatable) UI",
+ "file": "how-to-guides/build-localizable-components.md",
+ "children": [
+ {
+ "title": "Work with XLF",
+ "file": "how-to-guides/work-with-xlf.md"
+ },
+ {
+ "title": "Add Another Language",
+ "file": "how-to-guides/add-another-language.md"
+ }
+ ]
}
]
},
diff --git a/doc/images/cascading-delete.png b/doc/images/cascading-delete.png
new file mode 100644
index 0000000000..178781d676
Binary files /dev/null and b/doc/images/cascading-delete.png differ
diff --git a/doc/images/entity-details-panels.png b/doc/images/entity-details-panels.png
new file mode 100644
index 0000000000..ab843106f4
Binary files /dev/null and b/doc/images/entity-details-panels.png differ
diff --git a/e2e/integration/MarkingChildAsDropout.cy.ts b/e2e/integration/MarkingChildAsDropout.cy.ts
deleted file mode 100644
index a0176beade..0000000000
--- a/e2e/integration/MarkingChildAsDropout.cy.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-describe("Scenario: Marking a child as dropout - E2E test", function () {
- before("GIVEN I am on the details page of a specific child", function () {
- // go to a child
- cy.visit("child");
- cy.get("tr").eq(2).click();
- });
-
- it("WHEN I select a dropout date for this child", () => {
- // click on "Dropout" menu
- cy.contains("div", "Dropout").click();
- // click on button with the content "Edit" in Dropout menu.
- cy.get(".form-buttons-wrapper:visible").contains("button", "Edit").click();
- // select today as the dropout date (which is initially marked as active)
- cy.get('[aria-label="Open calendar"]').filter(":visible").click();
- // without wait, sometimes the panel is still open after clicking
- cy.wait(100);
- cy.get(".mat-calendar-body-active:visible").click();
- // click on button with the content "Save"
- cy.get(".form-buttons-wrapper:visible").contains("button", "Save").click();
- // save the name of this Child to the variable
- cy.get(".mat-title > .remove-margin-bottom").invoke("text").as("childName");
- });
-
- it("THEN I should not see this child in the list of all children at first", function () {
- // click on "Children" menu in navigation
- cy.get('[ng-reflect-angulartics-label="Children"]').click();
- // type to the input "Filter" the name of child
- cy.get('[placeholder="e.g. name, age"]').type(this.childName, {
- force: true,
- });
- // find at this table the name of child and it should not exist
- cy.get("table").contains(this.childName.trim()).should("not.exist");
- });
-
- it("AND I should see the child when I activate the 'inactive' filter", function () {
- // click on the button with the content "Inactive"
- cy.contains("span", "Active").click();
- cy.contains("span", "Inactive").should("be.visible").click();
- // find at this table the name of child and it should exist
- cy.get("table").contains(this.childName.trim()).should("exist");
- });
-});
diff --git a/e2e/integration/RecordingAttendanceOfChild.cy.ts b/e2e/integration/RecordingAttendanceOfChild.cy.ts
index be757f8c59..b9737967ef 100644
--- a/e2e/integration/RecordingAttendanceOfChild.cy.ts
+++ b/e2e/integration/RecordingAttendanceOfChild.cy.ts
@@ -9,7 +9,6 @@ describe("Scenario: Recording attendance of a child - E2E test", function () {
});
it("AND I set the attendance of the specific child to 'present'", function () {
- cy.contains("button", "Show more").click({ scrollBehavior: "center" });
cy.contains("mat-card", "School Class")
.eq(0)
.click({ scrollBehavior: "center" });
@@ -30,7 +29,7 @@ describe("Scenario: Recording attendance of a child - E2E test", function () {
cy.get(".mat-calendar-body-active").should(
"have.css",
"background-color",
- "rgb(200, 230, 201)"
+ "rgb(200, 230, 201)",
);
});
});
diff --git a/package-lock.json b/package-lock.json
index 25c1411d36..9fe2449906 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,14 +10,14 @@
"license": "GPL-3.0",
"dependencies": {
"@angular/animations": "^16.2.1",
- "@angular/cdk": "^16.2.1",
+ "@angular/cdk": "^16.2.10",
"@angular/common": "^16.2.1",
"@angular/compiler": "^16.2.1",
"@angular/core": "^16.2.1",
"@angular/forms": "^16.2.1",
"@angular/localize": "^16.2.1",
- "@angular/material": "^16.2.1",
- "@angular/material-moment-adapter": "^16.2.1",
+ "@angular/material": "^16.2.10",
+ "@angular/material-moment-adapter": "^16.2.10",
"@angular/platform-browser": "^16.2.1",
"@angular/platform-browser-dynamic": "^16.2.1",
"@angular/router": "^16.2.1",
@@ -31,15 +31,15 @@
"@fortawesome/free-regular-svg-icons": "^6.4.2",
"@fortawesome/free-solid-svg-icons": "^6.4.2",
"@ngneat/until-destroy": "^10.0.0",
- "@sentry/browser": "^7.64.0",
+ "@sentry/browser": "^7.76.0",
"angulartics2": "^12.2.1",
"assert": "^2.0.0",
- "crypto-es": "^2.0.4",
+ "crypto-es": "^2.1.0",
"deep-object-diff": "^1.1.9",
- "flag-icons": "^6.10.0",
+ "flag-icons": "^6.11.2",
"hammerjs": "^2.0.8",
"json-query": "^2.2.2",
- "keycloak-js": "^22.0.1",
+ "keycloak-js": "^22.0.5",
"leaflet": "^1.9.4",
"lodash-es": "^4.17.21",
"md5": "^2.3.0",
@@ -91,6 +91,8 @@
"babel-loader": "^9.1.3",
"cypress": "13.1.0",
"eslint": "^8.47.0",
+ "eslint-config-prettier": "^9.0.0",
+ "eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-storybook": "^0.6.13",
"jasmine-core": "^5.1.0",
"jasmine-spec-reporter": "^7.0.0",
@@ -139,12 +141,12 @@
}
},
"node_modules/@angular-devkit/architect": {
- "version": "0.1602.2",
- "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.2.tgz",
- "integrity": "sha512-JFIeKKW7V2+/C8+pTReM6gfQkVU9l1IR1OCb9vvHWTRvuTr7E5h2L1rUInnmLiRWkEvkYfG29B+UPpYlkVl9oQ==",
+ "version": "0.1602.6",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.6.tgz",
+ "integrity": "sha512-b1NNV3yNg6Rt86ms20bJIroWUI8ihaEwv5k+EoijEXLoMs4eNs5PhqL+QE8rTj+q9pa1gSrWf2blXor2JGwf1g==",
"dev": true,
"dependencies": {
- "@angular-devkit/core": "16.2.2",
+ "@angular-devkit/core": "16.2.6",
"rxjs": "7.8.1"
},
"engines": {
@@ -154,15 +156,15 @@
}
},
"node_modules/@angular-devkit/build-angular": {
- "version": "16.2.2",
- "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-16.2.2.tgz",
- "integrity": "sha512-j2lni4mN6NaMLT85sJUPSz/pNuaTCAYG3EYUeuMRNkC5keH/f4W0Tiuq6DxY4OLEF1JnEnfkp+k0Z84mEti/xA==",
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-16.2.6.tgz",
+ "integrity": "sha512-QdU/q77K1P8CPEEZGxw1QqLcnA9ofboDWS7vcLRBmFmk2zydtLTApbK0P8GNDRbnmROOKkoaLo+xUTDJz9gvPA==",
"dev": true,
"dependencies": {
"@ampproject/remapping": "2.2.1",
- "@angular-devkit/architect": "0.1602.2",
- "@angular-devkit/build-webpack": "0.1602.2",
- "@angular-devkit/core": "16.2.2",
+ "@angular-devkit/architect": "0.1602.6",
+ "@angular-devkit/build-webpack": "0.1602.6",
+ "@angular-devkit/core": "16.2.6",
"@babel/core": "7.22.9",
"@babel/generator": "7.22.9",
"@babel/helper-annotate-as-pure": "7.22.5",
@@ -174,7 +176,7 @@
"@babel/runtime": "7.22.6",
"@babel/template": "7.22.5",
"@discoveryjs/json-ext": "0.5.7",
- "@ngtools/webpack": "16.2.2",
+ "@ngtools/webpack": "16.2.6",
"@vitejs/plugin-basic-ssl": "1.0.1",
"ansi-colors": "4.1.3",
"autoprefixer": "10.4.14",
@@ -204,7 +206,7 @@
"parse5-html-rewriting-stream": "7.0.0",
"picomatch": "2.3.1",
"piscina": "4.0.0",
- "postcss": "8.4.27",
+ "postcss": "8.4.31",
"postcss-loader": "7.3.3",
"resolve-url-loader": "5.0.0",
"rxjs": "7.8.1",
@@ -321,12 +323,12 @@
"dev": true
},
"node_modules/@angular-devkit/build-webpack": {
- "version": "0.1602.2",
- "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1602.2.tgz",
- "integrity": "sha512-V9+tsBgNrXJPeabq9vJzN3Cfz9joaNOxs6l6M4XItcMGmAtzvxxGZ7qS5uRH1RE+SOMpYyh9uPY4QMHRNRD/gA==",
+ "version": "0.1602.6",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1602.6.tgz",
+ "integrity": "sha512-BJPR6xdq7gRJ6bVWnZ81xHyH75j7lyLbegCXbvUNaM8TWVBkwWsSdqr2NQ717dNLLn5umg58SFpU/pWMq6CxMQ==",
"dev": true,
"dependencies": {
- "@angular-devkit/architect": "0.1602.2",
+ "@angular-devkit/architect": "0.1602.6",
"rxjs": "7.8.1"
},
"engines": {
@@ -340,9 +342,9 @@
}
},
"node_modules/@angular-devkit/core": {
- "version": "16.2.2",
- "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.2.tgz",
- "integrity": "sha512-6H4FsvP3rLJaGiWpIhCFPS7ZeNoM4sSrnFtRhhecu6s7MidzE4aqzuGdzJpzLammw1KL+DuTlN0gpLtM1Bvcwg==",
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.6.tgz",
+ "integrity": "sha512-iez/8NYXQT6fqVQLlKmZUIRkFUEZ88ACKbTwD4lBmk0+hXW+bQBxI7JOnE3C4zkcM2YeuTXIYsC5SebTKYiR4Q==",
"dev": true,
"dependencies": {
"ajv": "8.12.0",
@@ -367,12 +369,12 @@
}
},
"node_modules/@angular-devkit/schematics": {
- "version": "16.2.2",
- "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.2.tgz",
- "integrity": "sha512-KeXIlibVrQEwIKbR9GViLKc3m1SXi/xuSXgIvSv+22FNu5i91ScsAhYLe65sDUL6m6MM1XQQMS46XN1Z9bRqQw==",
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.6.tgz",
+ "integrity": "sha512-PhpRYHCJ3WvZXmng6Qk8TXeQf83jeBMAf7AIzI8h0fgeBocOl97Xf7bZpLg6GymiU+rVn15igQ4Rz9rKAay8bQ==",
"dev": true,
"dependencies": {
- "@angular-devkit/core": "16.2.2",
+ "@angular-devkit/core": "16.2.6",
"jsonc-parser": "3.2.0",
"magic-string": "0.30.1",
"ora": "5.4.1",
@@ -385,9 +387,9 @@
}
},
"node_modules/@angular-eslint/builder": {
- "version": "16.1.2",
- "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-16.1.2.tgz",
- "integrity": "sha512-Y95IBEWqzWA7SyIh5nlPuFasw/4lOILrAdY5Ji6tOpIJgNFoiR9K1UcH46i34r3384ApN8GEQJ7FlK6D6qCOJA==",
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-16.2.0.tgz",
+ "integrity": "sha512-SZjXOi3YIjuX2CocuRsR2QH6k1ca9lRO6IMm0YIYMmBPFCRP2KFHkL6aQnXM6DSaymQNN2TXfpuvUd45NxhU1w==",
"dev": true,
"dependencies": {
"@nx/devkit": "16.5.1",
@@ -399,18 +401,18 @@
}
},
"node_modules/@angular-eslint/bundled-angular-compiler": {
- "version": "16.1.2",
- "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-16.1.2.tgz",
- "integrity": "sha512-wDiHPFsKTijMcQUPNcoHOJ5kezIPCCbmDK6LHH7hAdAC/eDY9NHL5e4zQ2Xkf3/r1PFuwVLGTwwreEHlmeENDw==",
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-16.2.0.tgz",
+ "integrity": "sha512-ct9orDYxkMl2+uvM7UBfgV28Dq57V4dEs+Drh7cD673JIMa6sXbgmd0QEtm8W3cmyK/jcTzmuoufxbH7hOxd6g==",
"dev": true
},
"node_modules/@angular-eslint/eslint-plugin": {
- "version": "16.1.2",
- "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-16.1.2.tgz",
- "integrity": "sha512-lYVvoKUIOg/ez15yfN4zY2A++vnIeJe1xh2ADNTmmjSh2PFV24K9YOgrTbgrY3Ul9kzGDTBkvYqslq+IvMGdIw==",
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-16.2.0.tgz",
+ "integrity": "sha512-zdiAIox1T+B71HL+A8m+1jWdU34nvPGLhCRw/uZNwHzknsF4tYzNQ9W7T/SC/g/2s1yT2yNosEVNJSGSFvunJg==",
"dev": true,
"dependencies": {
- "@angular-eslint/utils": "16.1.2",
+ "@angular-eslint/utils": "16.2.0",
"@typescript-eslint/utils": "5.62.0"
},
"peerDependencies": {
@@ -419,17 +421,17 @@
}
},
"node_modules/@angular-eslint/eslint-plugin-template": {
- "version": "16.1.2",
- "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-16.1.2.tgz",
- "integrity": "sha512-2qsoUgPg9Qp4EVUJRwWcJ+8JMxBb0ma3pNBjFmY6LOd59igRYorJKfWep4Nln1EicYRDRsCLzeLHO976+b1yaQ==",
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-16.2.0.tgz",
+ "integrity": "sha512-YFdQ6hHX6NlQj0lfogZwfyKjU8pqkJU+Zsk0ehjlXP8VfKFVmDeQT5/Xr6Df9C8pveC3hvq6Jgd8vo67S9Enxg==",
"dev": true,
"dependencies": {
- "@angular-eslint/bundled-angular-compiler": "16.1.2",
- "@angular-eslint/utils": "16.1.2",
+ "@angular-eslint/bundled-angular-compiler": "16.2.0",
+ "@angular-eslint/utils": "16.2.0",
"@typescript-eslint/type-utils": "5.62.0",
"@typescript-eslint/utils": "5.62.0",
"aria-query": "5.3.0",
- "axobject-query": "3.1.1"
+ "axobject-query": "3.2.1"
},
"peerDependencies": {
"eslint": "^7.20.0 || ^8.0.0",
@@ -437,13 +439,13 @@
}
},
"node_modules/@angular-eslint/schematics": {
- "version": "16.1.2",
- "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-16.1.2.tgz",
- "integrity": "sha512-319i47NU6nfaAaQTQYN7k320proTIBCueWGt+fbT11210CMqQriFmD+B85AatCwQgMgLd8Rhs1/F7YL2OOhegA==",
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-16.2.0.tgz",
+ "integrity": "sha512-2JUVR7hAKx37mgWeDjvyWEMH5uSeeksYuaQT5wwlgIzgrO4BNFuqs6Rgyp2jiYa7BFMX/qHULSa+bSq5J5ceEA==",
"dev": true,
"dependencies": {
- "@angular-eslint/eslint-plugin": "16.1.2",
- "@angular-eslint/eslint-plugin-template": "16.1.2",
+ "@angular-eslint/eslint-plugin": "16.2.0",
+ "@angular-eslint/eslint-plugin-template": "16.2.0",
"@nx/devkit": "16.5.1",
"ignore": "5.2.4",
"nx": "16.5.1",
@@ -455,12 +457,12 @@
}
},
"node_modules/@angular-eslint/template-parser": {
- "version": "16.1.2",
- "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-16.1.2.tgz",
- "integrity": "sha512-vIkPOShVJLBEHYY3jISCVvJF3lXL//Y70J8T9lY2CBowgqp6AzzJ6cZU7JxrORN6b64rBUVvUtCGo8L36GvfuA==",
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-16.2.0.tgz",
+ "integrity": "sha512-v2jVKTy2wN7iM9nHpBkxLn2wfL8jSl4IlPrXThIqj8No2VHtpLQZPKuXbGPUXQX05VS2Mj5feScQ36ZVGS8Rbw==",
"dev": true,
"dependencies": {
- "@angular-eslint/bundled-angular-compiler": "16.1.2",
+ "@angular-eslint/bundled-angular-compiler": "16.2.0",
"eslint-scope": "^7.0.0"
},
"peerDependencies": {
@@ -469,12 +471,12 @@
}
},
"node_modules/@angular-eslint/utils": {
- "version": "16.1.2",
- "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-16.1.2.tgz",
- "integrity": "sha512-2yfEK3BPSJsUhP4JCz0EB6ktu4E4+/zc9qdtZvPWNF/eww2J/oYVPjY47C/HVg4MXpjJTI8vbdkvcnxrICIkfw==",
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-16.2.0.tgz",
+ "integrity": "sha512-NxMRwnlIgzmbJQfWkfd9y3Sz0hzjFdK5LH44i+3D5NhpPdZ6SzwHAjMYWoYsmmNQX5tlDXoicYF9Mz9Wz8DJ/A==",
"dev": true,
"dependencies": {
- "@angular-eslint/bundled-angular-compiler": "16.1.2",
+ "@angular-eslint/bundled-angular-compiler": "16.2.0",
"@typescript-eslint/utils": "5.62.0"
},
"peerDependencies": {
@@ -483,9 +485,9 @@
}
},
"node_modules/@angular/animations": {
- "version": "16.2.5",
- "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-16.2.5.tgz",
- "integrity": "sha512-2reD50S9zWvhewRvwl320iuRICN9s0fI+3nKULlwcyJ0praLRhJ1SnaAK3NEEu7MWo3n9sb3iVTzA6S9qZRJ4g==",
+ "version": "16.2.9",
+ "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-16.2.9.tgz",
+ "integrity": "sha512-J+nsc2x/ZQuh+YwwTzxXUrV+7SBpJq6DDStfTFkZls9PWGRj9fjqQeRCWrfNLllpxopAEjhFkoyK06oSjcwqAw==",
"dependencies": {
"tslib": "^2.3.0"
},
@@ -493,13 +495,13 @@
"node": "^16.14.0 || >=18.10.0"
},
"peerDependencies": {
- "@angular/core": "16.2.5"
+ "@angular/core": "16.2.9"
}
},
"node_modules/@angular/cdk": {
- "version": "16.2.4",
- "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-16.2.4.tgz",
- "integrity": "sha512-Hnh7Gs+gAkBnRYIMkDXRElEPAmBFas37isIfOtiqEmkgmSPFxsPpDOXK1soXeDk8U+yNmDWnO0fcHPp/pobHCw==",
+ "version": "16.2.10",
+ "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-16.2.10.tgz",
+ "integrity": "sha512-kOQrPxSMPi66aM9XfwZIjQXhH+q0PkhK4BNMHB9RkvaaQ34ovOrKaGsT7t0+sjlVhiwTiy2mB1Qgz6NlIB0ZZw==",
"dependencies": {
"tslib": "^2.3.0"
},
@@ -513,15 +515,15 @@
}
},
"node_modules/@angular/cli": {
- "version": "16.2.2",
- "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.2.tgz",
- "integrity": "sha512-PmhR/NMVVCiATXxHLkVCV781Q5aa5DaYye9+plZGX3rdKTilEunRNIfT13w7IuRfa0K/pKZj6PJU1S6yb7sqZg==",
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.6.tgz",
+ "integrity": "sha512-9poPvUEmlufOAW1Cjk+aA5e2x3mInLtbYYSL/EYviDN2ugmavsSIvxAE/WLnxq6cPWqhNDbHDaqvcmqkcFM3Cw==",
"dev": true,
"dependencies": {
- "@angular-devkit/architect": "0.1602.2",
- "@angular-devkit/core": "16.2.2",
- "@angular-devkit/schematics": "16.2.2",
- "@schematics/angular": "16.2.2",
+ "@angular-devkit/architect": "0.1602.6",
+ "@angular-devkit/core": "16.2.6",
+ "@angular-devkit/schematics": "16.2.6",
+ "@schematics/angular": "16.2.6",
"@yarnpkg/lockfile": "1.1.0",
"ansi-colors": "4.1.3",
"ini": "4.1.1",
@@ -547,9 +549,9 @@
}
},
"node_modules/@angular/common": {
- "version": "16.2.5",
- "resolved": "https://registry.npmjs.org/@angular/common/-/common-16.2.5.tgz",
- "integrity": "sha512-MCPSZfPXTEqdkswPczivwjqV117YeVjObtyxZsDAwrTZHzYBtfQreQG1XJ1IRRgDncznP6ke0mdH9LyD2LgZKQ==",
+ "version": "16.2.9",
+ "resolved": "https://registry.npmjs.org/@angular/common/-/common-16.2.9.tgz",
+ "integrity": "sha512-5Lh5KsxCkaoBDeSAghKNF5lCi0083ug4X2X7wnafsSd6Z3xt/rDjH9hDOP5SF5IDLtCVjJgHfs3cCLSTjRuNwg==",
"dependencies": {
"tslib": "^2.3.0"
},
@@ -557,14 +559,14 @@
"node": "^16.14.0 || >=18.10.0"
},
"peerDependencies": {
- "@angular/core": "16.2.5",
+ "@angular/core": "16.2.9",
"rxjs": "^6.5.3 || ^7.4.0"
}
},
"node_modules/@angular/compiler": {
- "version": "16.2.5",
- "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-16.2.5.tgz",
- "integrity": "sha512-DpLfWWZFk4lbr81W7sLRt15+/nbyyqTvz+UmGcrSfKBTSbV0VSoUjC3XZeIdPWoIgQXiKUCpaC0YXw0BjaOl0g==",
+ "version": "16.2.9",
+ "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-16.2.9.tgz",
+ "integrity": "sha512-lh799pnbdvzTVShJHOY1JC6c1pwBsZC4UIgB3Itklo9dskGybQma/gP+lE6RhqM4FblNfaaBXGlCMUuY8HkmEQ==",
"dependencies": {
"tslib": "^2.3.0"
},
@@ -572,7 +574,7 @@
"node": "^16.14.0 || >=18.10.0"
},
"peerDependencies": {
- "@angular/core": "16.2.5"
+ "@angular/core": "16.2.9"
},
"peerDependenciesMeta": {
"@angular/core": {
@@ -581,9 +583,9 @@
}
},
"node_modules/@angular/compiler-cli": {
- "version": "16.2.5",
- "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-16.2.5.tgz",
- "integrity": "sha512-6TtyFxro4iukVXhLlzxz7sVCMfAlNQhSYnizIJRSW31uQ0Uku8rjlUmX1tCAmhW6CacLumiz2tcy04Xn/QFWyw==",
+ "version": "16.2.9",
+ "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-16.2.9.tgz",
+ "integrity": "sha512-ecH2oOlijJdDqioD9IfgdqJGoRRHI6hAx5rwBxIaYk01ywj13KzvXWPrXbCIupeWtV/XUZUlbwf47nlmL5gxZg==",
"dependencies": {
"@babel/core": "7.22.5",
"@jridgewell/sourcemap-codec": "^1.4.14",
@@ -603,7 +605,7 @@
"node": "^16.14.0 || >=18.10.0"
},
"peerDependencies": {
- "@angular/compiler": "16.2.5",
+ "@angular/compiler": "16.2.9",
"typescript": ">=4.9.3 <5.2"
}
},
@@ -645,9 +647,9 @@
}
},
"node_modules/@angular/core": {
- "version": "16.2.5",
- "resolved": "https://registry.npmjs.org/@angular/core/-/core-16.2.5.tgz",
- "integrity": "sha512-Po2LMUnPg23D2qI7EYaoA4x3lRswx9nxfpwROzfFPbMNJ3JVbTK0HkTD2dFPGxRua2UjfJTb1um23tEGO4OGMQ==",
+ "version": "16.2.9",
+ "resolved": "https://registry.npmjs.org/@angular/core/-/core-16.2.9.tgz",
+ "integrity": "sha512-chvPX29ZBcMDuh7rLIgb0Cru6oJ/0FaqRzfOI3wT4W2F9W1HOlCtipovzmPYaUAmXBWfVP4EBO9TOWnpog0S0w==",
"dependencies": {
"tslib": "^2.3.0"
},
@@ -660,9 +662,9 @@
}
},
"node_modules/@angular/forms": {
- "version": "16.2.5",
- "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-16.2.5.tgz",
- "integrity": "sha512-iYJImRji1OiYIcC2mDBcXhtvPfAoEGT+HqZpivu+/ZPLuf+QegC9+ktJw90SQXR+xccmpkUb9MsJ52SN2MgkPA==",
+ "version": "16.2.9",
+ "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-16.2.9.tgz",
+ "integrity": "sha512-rxlg2iNJNBH/uc7b5YqybfYc8BkLzzPv1d/nMsQUlY0O2UV2zwNRpcIiWbWd7+ZaKjcyPynVe9FsXC8wgWIABw==",
"dependencies": {
"tslib": "^2.3.0"
},
@@ -670,16 +672,16 @@
"node": "^16.14.0 || >=18.10.0"
},
"peerDependencies": {
- "@angular/common": "16.2.5",
- "@angular/core": "16.2.5",
- "@angular/platform-browser": "16.2.5",
+ "@angular/common": "16.2.9",
+ "@angular/core": "16.2.9",
+ "@angular/platform-browser": "16.2.9",
"rxjs": "^6.5.3 || ^7.4.0"
}
},
"node_modules/@angular/localize": {
- "version": "16.2.5",
- "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-16.2.5.tgz",
- "integrity": "sha512-vDtrBlbWOqtATqaBv3gmxBT0e8TfxwW+4J47S8u5Pbi1ZAnQfDkD9MNivC6/CAifFMcxN1pH8NALwLXOUga1PA==",
+ "version": "16.2.9",
+ "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-16.2.9.tgz",
+ "integrity": "sha512-t5002NgBj+wjd81IXwg+yc2ypaBk6OWLAka1GXmWua3x7hwGw1yMtPFmzOE1cCNdXgWlluLxWclFjCUrAbGEww==",
"dependencies": {
"@babel/core": "7.22.5",
"fast-glob": "3.3.0",
@@ -694,8 +696,8 @@
"node": "^16.14.0 || >=18.10.0"
},
"peerDependencies": {
- "@angular/compiler": "16.2.5",
- "@angular/compiler-cli": "16.2.5"
+ "@angular/compiler": "16.2.9",
+ "@angular/compiler-cli": "16.2.9"
}
},
"node_modules/@angular/localize/node_modules/@babel/core": {
@@ -751,9 +753,9 @@
}
},
"node_modules/@angular/material": {
- "version": "16.2.4",
- "resolved": "https://registry.npmjs.org/@angular/material/-/material-16.2.4.tgz",
- "integrity": "sha512-TIZ/0MKObn5YU9n/VReghJJKqgkqyzrWVNEJ8UgOP6MV5o+kAbqLSmlDJEyjLIwJF0vPnJ3UP6qbEOfEi1OLaA==",
+ "version": "16.2.10",
+ "resolved": "https://registry.npmjs.org/@angular/material/-/material-16.2.10.tgz",
+ "integrity": "sha512-0XhMwbcxpEESL11mVO8ycwxa+Jlh+8egOSRleD30zFUesqBA5EhtRpH8cqtna03f/xxtRq00Q315igMIMNiOSg==",
"dependencies": {
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
"@material/auto-init": "15.0.0-canary.bc9ae6c9c.0",
@@ -806,7 +808,7 @@
},
"peerDependencies": {
"@angular/animations": "^16.0.0 || ^17.0.0",
- "@angular/cdk": "16.2.4",
+ "@angular/cdk": "16.2.10",
"@angular/common": "^16.0.0 || ^17.0.0",
"@angular/core": "^16.0.0 || ^17.0.0",
"@angular/forms": "^16.0.0 || ^17.0.0",
@@ -815,22 +817,22 @@
}
},
"node_modules/@angular/material-moment-adapter": {
- "version": "16.2.4",
- "resolved": "https://registry.npmjs.org/@angular/material-moment-adapter/-/material-moment-adapter-16.2.4.tgz",
- "integrity": "sha512-2kmSsgrSOzWf7B8lU6xJYYdvr0h++/BbyPWODK8g3cC9odtvIDxxZYnixmgBSgpnproLKwW/XGvbLlMUVzqc7Q==",
+ "version": "16.2.10",
+ "resolved": "https://registry.npmjs.org/@angular/material-moment-adapter/-/material-moment-adapter-16.2.10.tgz",
+ "integrity": "sha512-Gus+TPy/RRuB+48fNeT9eMLfx0ZkQHw4Z9o0V3FoTFKa5JTfS4pHf+HoYFpcn6Ge+Y3MMt17dp+fyKAQSV9FSA==",
"dependencies": {
"tslib": "^2.3.0"
},
"peerDependencies": {
"@angular/core": "^16.0.0 || ^17.0.0",
- "@angular/material": "16.2.4",
+ "@angular/material": "16.2.10",
"moment": "^2.18.1"
}
},
"node_modules/@angular/platform-browser": {
- "version": "16.2.5",
- "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-16.2.5.tgz",
- "integrity": "sha512-p+1GH/M4Vwoyp7brKkNBcMTxscoZxA1zehetFlNr8kArXWiISgPolyqOVzvT6cycYKu5uSRLnvHOTDss6xrAuA==",
+ "version": "16.2.9",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-16.2.9.tgz",
+ "integrity": "sha512-9Je7+Jmx0AOyRzBBumraVJG3M0R6YbT4c9jTUbLGJCcPxwDI3/u2ZzvW3rBqpmrDaqLxN5f1LcZeTZx287QeqQ==",
"dependencies": {
"tslib": "^2.3.0"
},
@@ -838,9 +840,9 @@
"node": "^16.14.0 || >=18.10.0"
},
"peerDependencies": {
- "@angular/animations": "16.2.5",
- "@angular/common": "16.2.5",
- "@angular/core": "16.2.5"
+ "@angular/animations": "16.2.9",
+ "@angular/common": "16.2.9",
+ "@angular/core": "16.2.9"
},
"peerDependenciesMeta": {
"@angular/animations": {
@@ -849,9 +851,9 @@
}
},
"node_modules/@angular/platform-browser-dynamic": {
- "version": "16.2.5",
- "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-16.2.5.tgz",
- "integrity": "sha512-kzC4z/KmLss8Du9uM1Q16r+3EqDExKKHnrb3G3tuEQ1jTvYCysdWoooVSBmtIlQUw13znpBm1B7XLoyviFvnwA==",
+ "version": "16.2.9",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-16.2.9.tgz",
+ "integrity": "sha512-ztpo0939vTZ/5CWVSvo41Yl6YPoTZ0If+yTrs7dk1ce0vFgaZXMlc+y5ZwjJIiMM5CvHbhL48Uk+HJNIojP98A==",
"dependencies": {
"tslib": "^2.3.0"
},
@@ -859,16 +861,16 @@
"node": "^16.14.0 || >=18.10.0"
},
"peerDependencies": {
- "@angular/common": "16.2.5",
- "@angular/compiler": "16.2.5",
- "@angular/core": "16.2.5",
- "@angular/platform-browser": "16.2.5"
+ "@angular/common": "16.2.9",
+ "@angular/compiler": "16.2.9",
+ "@angular/core": "16.2.9",
+ "@angular/platform-browser": "16.2.9"
}
},
"node_modules/@angular/router": {
- "version": "16.2.5",
- "resolved": "https://registry.npmjs.org/@angular/router/-/router-16.2.5.tgz",
- "integrity": "sha512-5IXhe6G7zYFUwHSfUgPw+I/q6M1AcfSyaOVcjMFQ94bVSWEMq5KrGCDc8HQtkdw7GqJ4txwbyQKSKp7khpqShQ==",
+ "version": "16.2.9",
+ "resolved": "https://registry.npmjs.org/@angular/router/-/router-16.2.9.tgz",
+ "integrity": "sha512-5vrJNMblTDx3WC3dtaqLddWNtR0P9iwpqffeZL1uobBIwP4hbJx+8Dos3TwxGR4hnopFKahoDQ5nC0NOQslyog==",
"dependencies": {
"tslib": "^2.3.0"
},
@@ -876,16 +878,16 @@
"node": "^16.14.0 || >=18.10.0"
},
"peerDependencies": {
- "@angular/common": "16.2.5",
- "@angular/core": "16.2.5",
- "@angular/platform-browser": "16.2.5",
+ "@angular/common": "16.2.9",
+ "@angular/core": "16.2.9",
+ "@angular/platform-browser": "16.2.9",
"rxjs": "^6.5.3 || ^7.4.0"
}
},
"node_modules/@angular/service-worker": {
- "version": "16.2.5",
- "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-16.2.5.tgz",
- "integrity": "sha512-rHSFkrzyOunWwAQNtTC01ry2inrutlCad8MChK+fHCAhD2maWbNHtIelXR5ylojx7EyTUY0TPL30D60z2mXbwA==",
+ "version": "16.2.9",
+ "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-16.2.9.tgz",
+ "integrity": "sha512-f7CRhSyOkSW2SeV0uQTigcprA2mi3Xw5xfl/ywEYqpVvgJI0dNyoclgF9pVA37geozhKBK7mhmw/FKK22BNvlg==",
"dependencies": {
"tslib": "^2.3.0"
},
@@ -896,8 +898,8 @@
"node": "^16.14.0 || >=18.10.0"
},
"peerDependencies": {
- "@angular/common": "16.2.5",
- "@angular/core": "16.2.5"
+ "@angular/common": "16.2.9",
+ "@angular/core": "16.2.9"
}
},
"node_modules/@assemblyscript/loader": {
@@ -936,29 +938,29 @@
}
},
"node_modules/@babel/compat-data": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
- "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==",
+ "version": "7.23.2",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz",
+ "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/core": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.17.tgz",
- "integrity": "sha512-2EENLmhpwplDux5PSsZnSbnSkB3tZ6QTksgO25xwEL7pIDcNOMhF5v/s6RzwjMZzZzw9Ofc30gHv5ChCC8pifQ==",
+ "version": "7.23.2",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz",
+ "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.22.13",
- "@babel/generator": "^7.22.15",
+ "@babel/generator": "^7.23.0",
"@babel/helper-compilation-targets": "^7.22.15",
- "@babel/helper-module-transforms": "^7.22.17",
- "@babel/helpers": "^7.22.15",
- "@babel/parser": "^7.22.16",
+ "@babel/helper-module-transforms": "^7.23.0",
+ "@babel/helpers": "^7.23.2",
+ "@babel/parser": "^7.23.0",
"@babel/template": "^7.22.15",
- "@babel/traverse": "^7.22.17",
- "@babel/types": "^7.22.17",
- "convert-source-map": "^1.7.0",
+ "@babel/traverse": "^7.23.2",
+ "@babel/types": "^7.23.0",
+ "convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
"json5": "^2.2.3",
@@ -973,11 +975,11 @@
}
},
"node_modules/@babel/core/node_modules/@babel/generator": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz",
- "integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
+ "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
"dependencies": {
- "@babel/types": "^7.22.15",
+ "@babel/types": "^7.23.0",
"@jridgewell/gen-mapping": "^0.3.2",
"@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
@@ -999,6 +1001,11 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@babel/core/node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="
+ },
"node_modules/@babel/core/node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
@@ -1127,9 +1134,9 @@
}
},
"node_modules/@babel/helper-define-polyfill-provider": {
- "version": "0.4.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz",
- "integrity": "sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw==",
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.3.tgz",
+ "integrity": "sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==",
"dev": true,
"dependencies": {
"@babel/helper-compilation-targets": "^7.22.6",
@@ -1143,20 +1150,33 @@
}
},
"node_modules/@babel/helper-environment-visitor": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
- "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==",
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
+ "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-function-name": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
- "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
+ "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
"dependencies": {
- "@babel/template": "^7.22.5",
- "@babel/types": "^7.22.5"
+ "@babel/template": "^7.22.15",
+ "@babel/types": "^7.23.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-function-name/node_modules/@babel/template": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+ "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+ "dependencies": {
+ "@babel/code-frame": "^7.22.13",
+ "@babel/parser": "^7.22.15",
+ "@babel/types": "^7.22.15"
},
"engines": {
"node": ">=6.9.0"
@@ -1174,12 +1194,12 @@
}
},
"node_modules/@babel/helper-member-expression-to-functions": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.15.tgz",
- "integrity": "sha512-qLNsZbgrNh0fDQBCPocSL8guki1hcPvltGDv/NxvUoABwFq7GkKSu1nRXeJkVZc+wJvne2E0RKQz+2SQrz6eAA==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz",
+ "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==",
"dev": true,
"dependencies": {
- "@babel/types": "^7.22.15"
+ "@babel/types": "^7.23.0"
},
"engines": {
"node": ">=6.9.0"
@@ -1197,15 +1217,15 @@
}
},
"node_modules/@babel/helper-module-transforms": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.17.tgz",
- "integrity": "sha512-XouDDhQESrLHTpnBtCKExJdyY4gJCdrvH2Pyv8r8kovX2U8G0dRUOT45T9XlbLtuu9CLXP15eusnkprhoPV5iQ==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz",
+ "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==",
"dependencies": {
- "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-module-imports": "^7.22.15",
"@babel/helper-simple-access": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
- "@babel/helper-validator-identifier": "^7.22.15"
+ "@babel/helper-validator-identifier": "^7.22.20"
},
"engines": {
"node": ">=6.9.0"
@@ -1236,14 +1256,14 @@
}
},
"node_modules/@babel/helper-remap-async-to-generator": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.17.tgz",
- "integrity": "sha512-bxH77R5gjH3Nkde6/LuncQoLaP16THYPscurp1S8z7S9ZgezCyV3G8Hc+TZiCmY8pz4fp8CvKSgtJMW0FkLAxA==",
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz",
+ "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==",
"dev": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.22.5",
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-wrap-function": "^7.22.17"
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-wrap-function": "^7.22.20"
},
"engines": {
"node": ">=6.9.0"
@@ -1253,13 +1273,13 @@
}
},
"node_modules/@babel/helper-replace-supers": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz",
- "integrity": "sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==",
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz",
+ "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==",
"dev": true,
"dependencies": {
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-member-expression-to-functions": "^7.22.5",
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-member-expression-to-functions": "^7.22.15",
"@babel/helper-optimise-call-expression": "^7.22.5"
},
"engines": {
@@ -1312,9 +1332,9 @@
}
},
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
- "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ==",
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
+ "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
"engines": {
"node": ">=6.9.0"
}
@@ -1328,14 +1348,14 @@
}
},
"node_modules/@babel/helper-wrap-function": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.17.tgz",
- "integrity": "sha512-nAhoheCMlrqU41tAojw9GpVEKDlTS8r3lzFmF0lP52LwblCPbuFSO7nGIZoIcoU5NIm1ABrna0cJExE4Ay6l2Q==",
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz",
+ "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==",
"dev": true,
"dependencies": {
"@babel/helper-function-name": "^7.22.5",
"@babel/template": "^7.22.15",
- "@babel/types": "^7.22.17"
+ "@babel/types": "^7.22.19"
},
"engines": {
"node": ">=6.9.0"
@@ -1356,13 +1376,13 @@
}
},
"node_modules/@babel/helpers": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.15.tgz",
- "integrity": "sha512-7pAjK0aSdxOwR+CcYAqgWOGy5dcfvzsTIfFTb2odQqW47MDfv14UaJDY6eng8ylM2EaeKXdxaSWESbkmaQHTmw==",
+ "version": "7.23.2",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz",
+ "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==",
"dependencies": {
"@babel/template": "^7.22.15",
- "@babel/traverse": "^7.22.15",
- "@babel/types": "^7.22.15"
+ "@babel/traverse": "^7.23.2",
+ "@babel/types": "^7.23.0"
},
"engines": {
"node": ">=6.9.0"
@@ -1382,11 +1402,11 @@
}
},
"node_modules/@babel/highlight": {
- "version": "7.22.13",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
- "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
+ "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
"dependencies": {
- "@babel/helper-validator-identifier": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.20",
"chalk": "^2.4.2",
"js-tokens": "^4.0.0"
},
@@ -1395,9 +1415,9 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.22.16",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
- "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
+ "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
"bin": {
"parser": "bin/babel-parser.js"
},
@@ -1508,6 +1528,23 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-proposal-private-methods": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz",
+ "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==",
+ "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-proposal-private-property-in-object": {
"version": "7.21.0-placeholder-for-preset-env.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
@@ -1833,14 +1870,14 @@
}
},
"node_modules/@babel/plugin-transform-async-generator-functions": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.15.tgz",
- "integrity": "sha512-jBm1Es25Y+tVoTi5rfd5t1KLmL8ogLKpXszboWOTTtGFGz2RKnQe2yn7HbZ+kb/B8N0FVSGQo874NSlOU1T4+w==",
+ "version": "7.23.2",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.2.tgz",
+ "integrity": "sha512-BBYVGxbDVHfoeXbOwcagAkOQAm9NxoTdMGfTqghu1GrvadSaw6iW3Je6IcL5PNOw8VwjxqBECXy50/iCQSY/lQ==",
"dev": true,
"dependencies": {
- "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-remap-async-to-generator": "^7.22.9",
+ "@babel/helper-remap-async-to-generator": "^7.22.20",
"@babel/plugin-syntax-async-generators": "^7.8.4"
},
"engines": {
@@ -1883,9 +1920,9 @@
}
},
"node_modules/@babel/plugin-transform-block-scoping": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.15.tgz",
- "integrity": "sha512-G1czpdJBZCtngoK1sJgloLiOHUnkb/bLZwqVZD8kXmq0ZnVfTTWUcs9OWtp0mBtYJ+4LQY1fllqBkOIPhXmFmw==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz",
+ "integrity": "sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
@@ -1970,9 +2007,9 @@
}
},
"node_modules/@babel/plugin-transform-destructuring": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.15.tgz",
- "integrity": "sha512-HzG8sFl1ZVGTme74Nw+X01XsUTqERVQ6/RLHo3XjGRzm7XD6QTtfS3NJotVgCGy8BzkDqRjRBD8dAyJn5TuvSQ==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.0.tgz",
+ "integrity": "sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
@@ -2174,12 +2211,12 @@
}
},
"node_modules/@babel/plugin-transform-modules-amd": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz",
- "integrity": "sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.0.tgz",
+ "integrity": "sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw==",
"dev": true,
"dependencies": {
- "@babel/helper-module-transforms": "^7.22.5",
+ "@babel/helper-module-transforms": "^7.23.0",
"@babel/helper-plugin-utils": "^7.22.5"
},
"engines": {
@@ -2190,12 +2227,12 @@
}
},
"node_modules/@babel/plugin-transform-modules-commonjs": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.15.tgz",
- "integrity": "sha512-jWL4eh90w0HQOTKP2MoXXUpVxilxsB2Vl4ji69rSjS3EcZ/v4sBmn+A3NpepuJzBhOaEBbR7udonlHHn5DWidg==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz",
+ "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==",
"dev": true,
"dependencies": {
- "@babel/helper-module-transforms": "^7.22.15",
+ "@babel/helper-module-transforms": "^7.23.0",
"@babel/helper-plugin-utils": "^7.22.5",
"@babel/helper-simple-access": "^7.22.5"
},
@@ -2207,15 +2244,15 @@
}
},
"node_modules/@babel/plugin-transform-modules-systemjs": {
- "version": "7.22.11",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.11.tgz",
- "integrity": "sha512-rIqHmHoMEOhI3VkVf5jQ15l539KrwhzqcBO6wdCNWPWc/JWt9ILNYNUssbRpeq0qWns8svuw8LnMNCvWBIJ8wA==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.0.tgz",
+ "integrity": "sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg==",
"dev": true,
"dependencies": {
"@babel/helper-hoist-variables": "^7.22.5",
- "@babel/helper-module-transforms": "^7.22.9",
+ "@babel/helper-module-transforms": "^7.23.0",
"@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.5"
+ "@babel/helper-validator-identifier": "^7.22.20"
},
"engines": {
"node": ">=6.9.0"
@@ -2355,9 +2392,9 @@
}
},
"node_modules/@babel/plugin-transform-optional-chaining": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.15.tgz",
- "integrity": "sha512-ngQ2tBhq5vvSJw2Q2Z9i7ealNkpDMU0rGWnHPKqRZO0tzZ5tlaoz4hDvhXioOoaE0X2vfNss1djwg0DXlfu30A==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.0.tgz",
+ "integrity": "sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5",
@@ -2789,15 +2826,15 @@
}
},
"node_modules/@babel/preset-typescript": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.22.15.tgz",
- "integrity": "sha512-HblhNmh6yM+cU4VwbBRpxFhxsTdfS1zsvH9W+gEjD0ARV9+8B4sNfpI6GuhePti84nuvhiwKS539jKPFHskA9A==",
+ "version": "7.23.2",
+ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.2.tgz",
+ "integrity": "sha512-u4UJc1XsS1GhIGteM8rnGiIvf9rJpiVgMEeCnwlLA7WJPC+jcXWJAGxYmeqs5hOZD8BbAfnV5ezBOxQbb4OUxA==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5",
"@babel/helper-validator-option": "^7.22.15",
"@babel/plugin-syntax-jsx": "^7.22.5",
- "@babel/plugin-transform-modules-commonjs": "^7.22.15",
+ "@babel/plugin-transform-modules-commonjs": "^7.23.0",
"@babel/plugin-transform-typescript": "^7.22.15"
},
"engines": {
@@ -2976,18 +3013,18 @@
}
},
"node_modules/@babel/traverse": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.17.tgz",
- "integrity": "sha512-xK4Uwm0JnAMvxYZxOVecss85WxTEIbTa7bnGyf/+EgCL5Zt3U7htUpEOWv9detPlamGKuRzCqw74xVglDWpPdg==",
+ "version": "7.23.2",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
+ "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
"dependencies": {
"@babel/code-frame": "^7.22.13",
- "@babel/generator": "^7.22.15",
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-function-name": "^7.22.5",
+ "@babel/generator": "^7.23.0",
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-function-name": "^7.23.0",
"@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
- "@babel/parser": "^7.22.16",
- "@babel/types": "^7.22.17",
+ "@babel/parser": "^7.23.0",
+ "@babel/types": "^7.23.0",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@@ -2996,11 +3033,11 @@
}
},
"node_modules/@babel/traverse/node_modules/@babel/generator": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz",
- "integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
+ "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
"dependencies": {
- "@babel/types": "^7.22.15",
+ "@babel/types": "^7.23.0",
"@jridgewell/gen-mapping": "^0.3.2",
"@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
@@ -3010,12 +3047,12 @@
}
},
"node_modules/@babel/types": {
- "version": "7.22.17",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
- "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
+ "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
"dependencies": {
"@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.15",
+ "@babel/helper-validator-identifier": "^7.22.20",
"to-fast-properties": "^2.0.0"
},
"engines": {
@@ -3060,47 +3097,47 @@
}
},
"node_modules/@compodoc/compodoc": {
- "version": "1.1.21",
- "resolved": "https://registry.npmjs.org/@compodoc/compodoc/-/compodoc-1.1.21.tgz",
- "integrity": "sha512-/FDlwRgKzmkGuorDnURuCzoGY6rZ0KY7Mj5/PwnEjMs0y1CRRPHBJC9I0yVIjn8j8gxVy8PPc6dna0lY1MWwhg==",
+ "version": "1.1.22",
+ "resolved": "https://registry.npmjs.org/@compodoc/compodoc/-/compodoc-1.1.22.tgz",
+ "integrity": "sha512-NmcEe9GDP90jtDKPlBU/PMyvVt6RjsGvraniVOH6Qgrm472FZu6tQotGd6mFQyqBabWS0uI2X3isuFJz1/Yj5Q==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
- "@angular-devkit/schematics": "^16.0.1",
- "@babel/core": "^7.21.8",
- "@babel/preset-env": "^7.21.5",
+ "@angular-devkit/schematics": "14.2.12",
+ "@babel/core": "^7.23.2",
+ "@babel/plugin-proposal-private-methods": "^7.18.6",
+ "@babel/preset-env": "^7.23.2",
"@compodoc/live-server": "^1.2.3",
"@compodoc/ngd-transformer": "^2.1.3",
"chalk": "4.1.2",
"cheerio": "^1.0.0-rc.12",
"chokidar": "^3.5.3",
"colors": "1.4.0",
- "commander": "^10.0.1",
- "cosmiconfig": "^8.1.3",
- "decache": "^4.6.1",
+ "commander": "^11.1.0",
+ "cosmiconfig": "^8.3.6",
+ "decache": "^4.6.2",
"fancy-log": "^2.0.0",
- "fast-glob": "^3.2.12",
+ "fast-glob": "^3.3.1",
"fs-extra": "^11.1.1",
- "glob": "^10.2.4",
- "handlebars": "^4.7.7",
- "html-entities": "^2.3.3",
- "i18next": "^22.4.15",
- "inside": "^1.0.0",
+ "glob": "^10.3.10",
+ "handlebars": "^4.7.8",
+ "html-entities": "^2.4.0",
+ "i18next": "^23.5.1",
"json5": "^2.2.3",
"lodash": "^4.17.21",
"loglevel": "^1.8.1",
"loglevel-plugin-prefix": "^0.8.4",
"lunr": "^2.3.9",
- "marked": "4.3.0",
+ "marked": "7.0.3",
"minimist": "^1.2.8",
"opencollective-postinstall": "^2.0.3",
"os-name": "4.0.1",
"pdfjs-dist": "2.12.313",
"pdfmake": "^0.2.7",
- "semver": "^7.5.1",
+ "semver": "^7.5.4",
"traverse": "^0.6.7",
- "ts-morph": "^18.0.0",
- "uuid": "^9.0.0"
+ "ts-morph": "^20.0.0",
+ "uuid": "^9.0.1"
},
"bin": {
"compodoc": "bin/index-cli.js"
@@ -3109,6 +3146,183 @@
"node": ">= 14.0.0"
}
},
+ "node_modules/@compodoc/compodoc/node_modules/@angular-devkit/core": {
+ "version": "14.2.12",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-14.2.12.tgz",
+ "integrity": "sha512-tg1+deEZdm3fgk2BQ6y7tujciL6qhtN5Ums266lX//kAZeZ4nNNXTBT+oY5xgfjvmLbW+xKg0XZrAS0oIRKY5g==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "8.11.0",
+ "ajv-formats": "2.1.1",
+ "jsonc-parser": "3.1.0",
+ "rxjs": "6.6.7",
+ "source-map": "0.7.4"
+ },
+ "engines": {
+ "node": "^14.15.0 || >=16.10.0",
+ "npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
+ "yarn": ">= 1.13.0"
+ },
+ "peerDependencies": {
+ "chokidar": "^3.5.2"
+ },
+ "peerDependenciesMeta": {
+ "chokidar": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@compodoc/compodoc/node_modules/@angular-devkit/schematics": {
+ "version": "14.2.12",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-14.2.12.tgz",
+ "integrity": "sha512-MN5yGR+SSSPPBBVMf4cifDJn9u0IYvxiHst+HWokH2AkBYy+vB1x8jYES2l1wkiISD7nvjTixfqX+Y95oMBoLg==",
+ "dev": true,
+ "dependencies": {
+ "@angular-devkit/core": "14.2.12",
+ "jsonc-parser": "3.1.0",
+ "magic-string": "0.26.2",
+ "ora": "5.4.1",
+ "rxjs": "6.6.7"
+ },
+ "engines": {
+ "node": "^14.15.0 || >=16.10.0",
+ "npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
+ "yarn": ">= 1.13.0"
+ }
+ },
+ "node_modules/@compodoc/compodoc/node_modules/@babel/preset-env": {
+ "version": "7.23.2",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.2.tgz",
+ "integrity": "sha512-BW3gsuDD+rvHL2VO2SjAUNTBe5YrjsTiDyqamPDWY723na3/yPQ65X5oQkFVJZ0o50/2d+svm1rkPoJeR1KxVQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.23.2",
+ "@babel/helper-compilation-targets": "^7.22.15",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-validator-option": "^7.22.15",
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.15",
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.15",
+ "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
+ "@babel/plugin-syntax-import-assertions": "^7.22.5",
+ "@babel/plugin-syntax-import-attributes": "^7.22.5",
+ "@babel/plugin-syntax-import-meta": "^7.10.4",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5",
+ "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
+ "@babel/plugin-transform-arrow-functions": "^7.22.5",
+ "@babel/plugin-transform-async-generator-functions": "^7.23.2",
+ "@babel/plugin-transform-async-to-generator": "^7.22.5",
+ "@babel/plugin-transform-block-scoped-functions": "^7.22.5",
+ "@babel/plugin-transform-block-scoping": "^7.23.0",
+ "@babel/plugin-transform-class-properties": "^7.22.5",
+ "@babel/plugin-transform-class-static-block": "^7.22.11",
+ "@babel/plugin-transform-classes": "^7.22.15",
+ "@babel/plugin-transform-computed-properties": "^7.22.5",
+ "@babel/plugin-transform-destructuring": "^7.23.0",
+ "@babel/plugin-transform-dotall-regex": "^7.22.5",
+ "@babel/plugin-transform-duplicate-keys": "^7.22.5",
+ "@babel/plugin-transform-dynamic-import": "^7.22.11",
+ "@babel/plugin-transform-exponentiation-operator": "^7.22.5",
+ "@babel/plugin-transform-export-namespace-from": "^7.22.11",
+ "@babel/plugin-transform-for-of": "^7.22.15",
+ "@babel/plugin-transform-function-name": "^7.22.5",
+ "@babel/plugin-transform-json-strings": "^7.22.11",
+ "@babel/plugin-transform-literals": "^7.22.5",
+ "@babel/plugin-transform-logical-assignment-operators": "^7.22.11",
+ "@babel/plugin-transform-member-expression-literals": "^7.22.5",
+ "@babel/plugin-transform-modules-amd": "^7.23.0",
+ "@babel/plugin-transform-modules-commonjs": "^7.23.0",
+ "@babel/plugin-transform-modules-systemjs": "^7.23.0",
+ "@babel/plugin-transform-modules-umd": "^7.22.5",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5",
+ "@babel/plugin-transform-new-target": "^7.22.5",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11",
+ "@babel/plugin-transform-numeric-separator": "^7.22.11",
+ "@babel/plugin-transform-object-rest-spread": "^7.22.15",
+ "@babel/plugin-transform-object-super": "^7.22.5",
+ "@babel/plugin-transform-optional-catch-binding": "^7.22.11",
+ "@babel/plugin-transform-optional-chaining": "^7.23.0",
+ "@babel/plugin-transform-parameters": "^7.22.15",
+ "@babel/plugin-transform-private-methods": "^7.22.5",
+ "@babel/plugin-transform-private-property-in-object": "^7.22.11",
+ "@babel/plugin-transform-property-literals": "^7.22.5",
+ "@babel/plugin-transform-regenerator": "^7.22.10",
+ "@babel/plugin-transform-reserved-words": "^7.22.5",
+ "@babel/plugin-transform-shorthand-properties": "^7.22.5",
+ "@babel/plugin-transform-spread": "^7.22.5",
+ "@babel/plugin-transform-sticky-regex": "^7.22.5",
+ "@babel/plugin-transform-template-literals": "^7.22.5",
+ "@babel/plugin-transform-typeof-symbol": "^7.22.5",
+ "@babel/plugin-transform-unicode-escapes": "^7.22.10",
+ "@babel/plugin-transform-unicode-property-regex": "^7.22.5",
+ "@babel/plugin-transform-unicode-regex": "^7.22.5",
+ "@babel/plugin-transform-unicode-sets-regex": "^7.22.5",
+ "@babel/preset-modules": "0.1.6-no-external-plugins",
+ "@babel/types": "^7.23.0",
+ "babel-plugin-polyfill-corejs2": "^0.4.6",
+ "babel-plugin-polyfill-corejs3": "^0.8.5",
+ "babel-plugin-polyfill-regenerator": "^0.5.3",
+ "core-js-compat": "^3.31.0",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@compodoc/compodoc/node_modules/@babel/preset-env/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@compodoc/compodoc/node_modules/@babel/preset-modules": {
+ "version": "0.1.6-no-external-plugins",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz",
+ "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/types": "^7.4.4",
+ "esutils": "^2.0.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/@compodoc/compodoc/node_modules/ajv": {
+ "version": "8.11.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
+ "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
"node_modules/@compodoc/compodoc/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@@ -3149,6 +3363,48 @@
"node": ">=8"
}
},
+ "node_modules/@compodoc/compodoc/node_modules/jsonc-parser": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.1.0.tgz",
+ "integrity": "sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==",
+ "dev": true
+ },
+ "node_modules/@compodoc/compodoc/node_modules/magic-string": {
+ "version": "0.26.2",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.2.tgz",
+ "integrity": "sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A==",
+ "dev": true,
+ "dependencies": {
+ "sourcemap-codec": "^1.4.8"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@compodoc/compodoc/node_modules/marked": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.3.tgz",
+ "integrity": "sha512-ev2uM40p0zQ/GbvqotfKcSWEa59fJwluGZj5dcaUOwDRrB1F3dncdXy8NWUApk4fi8atU3kTBOwjyjZ0ud0dxw==",
+ "dev": true,
+ "bin": {
+ "marked": "bin/marked.js"
+ },
+ "engines": {
+ "node": ">= 16"
+ }
+ },
+ "node_modules/@compodoc/compodoc/node_modules/rxjs": {
+ "version": "6.6.7",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
+ "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^1.9.0"
+ },
+ "engines": {
+ "npm": ">=2.0.0"
+ }
+ },
"node_modules/@compodoc/compodoc/node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -3161,6 +3417,12 @@
"node": ">=8"
}
},
+ "node_modules/@compodoc/compodoc/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
"node_modules/@compodoc/live-server": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@compodoc/live-server/-/live-server-1.2.3.tgz",
@@ -3761,9 +4023,9 @@
}
},
"node_modules/@eslint-community/regexpp": {
- "version": "4.8.1",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.1.tgz",
- "integrity": "sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ==",
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz",
+ "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==",
"dev": true,
"engines": {
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
@@ -3815,9 +4077,9 @@
"dev": true
},
"node_modules/@eslint/eslintrc/node_modules/globals": {
- "version": "13.21.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz",
- "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==",
+ "version": "13.23.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
+ "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
"dev": true,
"dependencies": {
"type-fest": "^0.20.2"
@@ -3860,18 +4122,18 @@
}
},
"node_modules/@eslint/js": {
- "version": "8.49.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.49.0.tgz",
- "integrity": "sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==",
+ "version": "8.51.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz",
+ "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@faker-js/faker": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.0.2.tgz",
- "integrity": "sha512-Uo3pGspElQW91PCvKSIAXoEgAUlRnH29sX2/p89kg7sP1m2PzCufHINd0FhTXQf6DYGiUlVncdSPa2F9wxed2A==",
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.2.0.tgz",
+ "integrity": "sha512-VacmzZqVxdWdf9y64lDOMZNDMM/FQdtM9IsaOPKOm2suYwEatb8VkdHqOzXcDnZbk7YDE2BmsJmy/2Hmkn563g==",
"funding": [
{
"type": "opencollective",
@@ -3890,22 +4152,22 @@
"dev": true
},
"node_modules/@floating-ui/core": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.4.1.tgz",
- "integrity": "sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ==",
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.0.tgz",
+ "integrity": "sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg==",
"dev": true,
"dependencies": {
- "@floating-ui/utils": "^0.1.1"
+ "@floating-ui/utils": "^0.1.3"
}
},
"node_modules/@floating-ui/dom": {
- "version": "1.5.2",
- "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.2.tgz",
- "integrity": "sha512-6ArmenS6qJEWmwzczWyhvrXRdI/rI78poBcW0h/456+onlabit+2G+QxHx5xTOX60NBJQXjsCLFbW2CmsXpUog==",
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.3.tgz",
+ "integrity": "sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==",
"dev": true,
"dependencies": {
- "@floating-ui/core": "^1.4.1",
- "@floating-ui/utils": "^0.1.1"
+ "@floating-ui/core": "^1.4.2",
+ "@floating-ui/utils": "^0.1.3"
}
},
"node_modules/@floating-ui/react-dom": {
@@ -3922,9 +4184,9 @@
}
},
"node_modules/@floating-ui/utils": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.2.tgz",
- "integrity": "sha512-ou3elfqG/hZsbmF4bxeJhPHIf3G2pm0ujc39hYEZrfVqt7Vk/Zji6CXc3W0pmYM8BW1g40U+akTl9DKZhFhInQ==",
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz",
+ "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==",
"dev": true
},
"node_modules/@foliojs-fork/fontkit": {
@@ -3945,23 +4207,6 @@
"unicode-trie": "^2.0.0"
}
},
- "node_modules/@foliojs-fork/fontkit/node_modules/deep-equal": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
- "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
- "dev": true,
- "dependencies": {
- "is-arguments": "^1.0.4",
- "is-date-object": "^1.0.1",
- "is-regex": "^1.0.4",
- "object-is": "^1.0.1",
- "object-keys": "^1.1.1",
- "regexp.prototype.flags": "^1.2.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/@foliojs-fork/linebreak": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@foliojs-fork/linebreak/-/linebreak-1.1.1.tgz",
@@ -4469,9 +4714,9 @@
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
},
"node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.19",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz",
- "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==",
+ "version": "0.3.20",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
+ "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
@@ -5282,9 +5527,9 @@
}
},
"node_modules/@ngtools/webpack": {
- "version": "16.2.2",
- "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.2.2.tgz",
- "integrity": "sha512-BDZ2yyXdzVE8kILOM0lhRpmKlvfLMluuZvqVa1r5dHkjCLbyOo1jXoYTCXvrQ2JU5GXc/MBBLXwmIHgtPWk8/A==",
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.2.6.tgz",
+ "integrity": "sha512-d8ZlZL6dOtWmHdjG9PTGBkdiJMcsXD2tp6WeFRVvTEuvCI3XvKsUXBvJDE+mZOhzn5pUEYt+1TR5DHjDZbME3w==",
"dev": true,
"engines": {
"node": "^16.14.0 || >=18.10.0",
@@ -5726,20 +5971,20 @@
}
},
"node_modules/@percy/cli": {
- "version": "1.27.1",
- "resolved": "https://registry.npmjs.org/@percy/cli/-/cli-1.27.1.tgz",
- "integrity": "sha512-2rU4NFe8TshV2sF+fs8bseGNohpLuRILW4t/Is7PCFYAitla1nvO0mndy0INct5VWc2KKewnq+2ZQONx3iNXLw==",
+ "version": "1.27.3",
+ "resolved": "https://registry.npmjs.org/@percy/cli/-/cli-1.27.3.tgz",
+ "integrity": "sha512-GyAIk9wm32cheYAeVyY6nOkDcGgSeG7wgLhZJWzi0gVhFE9W04sudWa++7akEqpGLMnTM2Q4OZv5P3cy1F9iPA==",
"dev": true,
"dependencies": {
- "@percy/cli-app": "1.27.1",
- "@percy/cli-build": "1.27.1",
- "@percy/cli-command": "1.27.1",
- "@percy/cli-config": "1.27.1",
- "@percy/cli-exec": "1.27.1",
- "@percy/cli-snapshot": "1.27.1",
- "@percy/cli-upload": "1.27.1",
- "@percy/client": "1.27.1",
- "@percy/logger": "1.27.1"
+ "@percy/cli-app": "1.27.3",
+ "@percy/cli-build": "1.27.3",
+ "@percy/cli-command": "1.27.3",
+ "@percy/cli-config": "1.27.3",
+ "@percy/cli-exec": "1.27.3",
+ "@percy/cli-snapshot": "1.27.3",
+ "@percy/cli-upload": "1.27.3",
+ "@percy/client": "1.27.3",
+ "@percy/logger": "1.27.3"
},
"bin": {
"percy": "bin/run.cjs"
@@ -5749,39 +5994,39 @@
}
},
"node_modules/@percy/cli-app": {
- "version": "1.27.1",
- "resolved": "https://registry.npmjs.org/@percy/cli-app/-/cli-app-1.27.1.tgz",
- "integrity": "sha512-Pat2BogPUmyciURUWbI1PQtUdPlhUrnS6aEVO1gNrulDeYF6j4LgD4SycCTj5L/xJijMXa3qFkZwW1VSdx97Yg==",
+ "version": "1.27.3",
+ "resolved": "https://registry.npmjs.org/@percy/cli-app/-/cli-app-1.27.3.tgz",
+ "integrity": "sha512-RUSzWTRkG4hjUy7dzu+zlKVlbXEcj3yoiFTpjrmUxoK5QMVQtZfDdkHfJNSI51w1ZRzuxmO5x5uqFRpgUKh8QQ==",
"dev": true,
"dependencies": {
- "@percy/cli-command": "1.27.1",
- "@percy/cli-exec": "1.27.1"
+ "@percy/cli-command": "1.27.3",
+ "@percy/cli-exec": "1.27.3"
},
"engines": {
"node": ">=14"
}
},
"node_modules/@percy/cli-build": {
- "version": "1.27.1",
- "resolved": "https://registry.npmjs.org/@percy/cli-build/-/cli-build-1.27.1.tgz",
- "integrity": "sha512-EtktlYj4kzsBkrBSOVLKrvZWew/nq9mw/Z2m8mU4Jf7Pc779rQGUVCuI8PBhOI59c3JTjnY8KVaaj4Y+z9X+fg==",
+ "version": "1.27.3",
+ "resolved": "https://registry.npmjs.org/@percy/cli-build/-/cli-build-1.27.3.tgz",
+ "integrity": "sha512-F7vWMmXipINDO9kvDyaPaIeUZlZLfIbg74oRaAJUOVH2nkf0FNSPy7Dy/MEsFWAiKNeW7/UwHjuYl+I/yMBZPw==",
"dev": true,
"dependencies": {
- "@percy/cli-command": "1.27.1"
+ "@percy/cli-command": "1.27.3"
},
"engines": {
"node": ">=14"
}
},
"node_modules/@percy/cli-command": {
- "version": "1.27.1",
- "resolved": "https://registry.npmjs.org/@percy/cli-command/-/cli-command-1.27.1.tgz",
- "integrity": "sha512-LK9YwE7qr67EtShVVjc20aJaRF8BFjZ8VWneLVoN73IYgpwBq96J4AUomoqfRpPNkpKvv6wDZFpr30xFokbrHA==",
+ "version": "1.27.3",
+ "resolved": "https://registry.npmjs.org/@percy/cli-command/-/cli-command-1.27.3.tgz",
+ "integrity": "sha512-aU76lu2a2/N/BUSsXpLXRzeJeXzmAcA3s9EFDeMNDMZY/7dV6wlLX9r7n931UD3bIhdlkl1o7COXIIATtPymJQ==",
"dev": true,
"dependencies": {
- "@percy/config": "1.27.1",
- "@percy/core": "1.27.1",
- "@percy/logger": "1.27.1"
+ "@percy/config": "1.27.3",
+ "@percy/core": "1.27.3",
+ "@percy/logger": "1.27.3"
},
"bin": {
"percy-cli-readme": "bin/readme.js"
@@ -5791,24 +6036,24 @@
}
},
"node_modules/@percy/cli-config": {
- "version": "1.27.1",
- "resolved": "https://registry.npmjs.org/@percy/cli-config/-/cli-config-1.27.1.tgz",
- "integrity": "sha512-bEzXfdP+RRxHekZ5pULsuuKHL0K9E81IFcEqZ8DcE3gnrpWQnIFPP2fTHF6WgWuXYHzJnsoIIm90LaWYc4+BJQ==",
+ "version": "1.27.3",
+ "resolved": "https://registry.npmjs.org/@percy/cli-config/-/cli-config-1.27.3.tgz",
+ "integrity": "sha512-+gUZUlbpgllux0yJnCFYMuNn1kItfIP9F1AIYqdqFM9KLixodMCWAXDUQ4V4EVLDjOR7fD3NKmyoFUFJgwcIww==",
"dev": true,
"dependencies": {
- "@percy/cli-command": "1.27.1"
+ "@percy/cli-command": "1.27.3"
},
"engines": {
"node": ">=14"
}
},
"node_modules/@percy/cli-exec": {
- "version": "1.27.1",
- "resolved": "https://registry.npmjs.org/@percy/cli-exec/-/cli-exec-1.27.1.tgz",
- "integrity": "sha512-8xB7Iq3fh+QfuViUeZQXZeJNoFzDf0IhYUhhlEDXPcL2sgjrLiy9QHBdq6Yn3/8gHlDJyzpkej6hzFqERYZs1g==",
+ "version": "1.27.3",
+ "resolved": "https://registry.npmjs.org/@percy/cli-exec/-/cli-exec-1.27.3.tgz",
+ "integrity": "sha512-PuSxfZKWx9BoeCbt5U1Edc+fv5kb/mYr+9sgoBsoHmwe5iNIgYKx6D+wmNK7FHgc82mycNLaEguew2JwJXlPew==",
"dev": true,
"dependencies": {
- "@percy/cli-command": "1.27.1",
+ "@percy/cli-command": "1.27.3",
"cross-spawn": "^7.0.3",
"which": "^2.0.2"
},
@@ -5817,12 +6062,12 @@
}
},
"node_modules/@percy/cli-snapshot": {
- "version": "1.27.1",
- "resolved": "https://registry.npmjs.org/@percy/cli-snapshot/-/cli-snapshot-1.27.1.tgz",
- "integrity": "sha512-hVYATkHSN6Mz67LuP5QqRvdblg+kLb9dqGlaMJZI0CtuQYRtkbrlPz5yII9SJGMyUYMQHbZKsc68eT7+LZHKbA==",
+ "version": "1.27.3",
+ "resolved": "https://registry.npmjs.org/@percy/cli-snapshot/-/cli-snapshot-1.27.3.tgz",
+ "integrity": "sha512-HU7p5FLJ1W+QM3mbq8MFyqukthFnxPXrBAC7O0Dh4GfxXfdThV1HOdXqCEZ1pj1b3XkEM5SvvLKc7mClnc4D1Q==",
"dev": true,
"dependencies": {
- "@percy/cli-command": "1.27.1",
+ "@percy/cli-command": "1.27.3",
"yaml": "^2.0.0"
},
"engines": {
@@ -5830,12 +6075,12 @@
}
},
"node_modules/@percy/cli-upload": {
- "version": "1.27.1",
- "resolved": "https://registry.npmjs.org/@percy/cli-upload/-/cli-upload-1.27.1.tgz",
- "integrity": "sha512-4Kcft6ceuWy+Q5T4PKJXI63/QxCRFtCJUoU0QYrWo6TKKsescdE7/zWy6YESqHIm+XzBhZFYHwdYRsIbnjqUqQ==",
+ "version": "1.27.3",
+ "resolved": "https://registry.npmjs.org/@percy/cli-upload/-/cli-upload-1.27.3.tgz",
+ "integrity": "sha512-sqzOAMqFKXhpuXDGAK5zUf5Aw/xgBbAP4o4y43dRBi6gIgf8DiiLuc+avyfcKm+2lW5cUTG9SPETVCpu03WozQ==",
"dev": true,
"dependencies": {
- "@percy/cli-command": "1.27.1",
+ "@percy/cli-command": "1.27.3",
"fast-glob": "^3.2.11",
"image-size": "^1.0.0"
},
@@ -5844,25 +6089,25 @@
}
},
"node_modules/@percy/client": {
- "version": "1.27.1",
- "resolved": "https://registry.npmjs.org/@percy/client/-/client-1.27.1.tgz",
- "integrity": "sha512-GvjrGUaVdjMwx8ODDja3Kdb6tXYxRxv4PLXfXg0Wbn5jIfcjicojOc0mSGxcLvRGu5tmKrE3fusMhYYtKlLihg==",
+ "version": "1.27.3",
+ "resolved": "https://registry.npmjs.org/@percy/client/-/client-1.27.3.tgz",
+ "integrity": "sha512-AuVpiuknK8OiDIN7BpkDRTYx6yAQVI4TjLFy/QmfZDK0PQMH+2dNIBi/pXooC5Ac64I7BYVqdaUk2IbdxEXbqQ==",
"dev": true,
"dependencies": {
- "@percy/env": "1.27.1",
- "@percy/logger": "1.27.1"
+ "@percy/env": "1.27.3",
+ "@percy/logger": "1.27.3"
},
"engines": {
"node": ">=14"
}
},
"node_modules/@percy/config": {
- "version": "1.27.1",
- "resolved": "https://registry.npmjs.org/@percy/config/-/config-1.27.1.tgz",
- "integrity": "sha512-O7GgSrpjPeRmUmPWpFrg7368lWTJj8BtKY18Ztpq2j7bef5HCFi0AxvuOjwIH/GEwzGm/cI7ZK2kA/XGTOtpsg==",
+ "version": "1.27.3",
+ "resolved": "https://registry.npmjs.org/@percy/config/-/config-1.27.3.tgz",
+ "integrity": "sha512-hxp/zQz/3IQcyBbMkmvvnlkwMn9tgYFAOAFtZqECruqQ1M9XE10uYtWjvVwt9s4rlJEB4PWFvAV4c04/CT6ugQ==",
"dev": true,
"dependencies": {
- "@percy/logger": "1.27.1",
+ "@percy/logger": "1.27.3",
"ajv": "^8.6.2",
"cosmiconfig": "^8.0.0",
"yaml": "^2.0.0"
@@ -5872,17 +6117,17 @@
}
},
"node_modules/@percy/core": {
- "version": "1.27.1",
- "resolved": "https://registry.npmjs.org/@percy/core/-/core-1.27.1.tgz",
- "integrity": "sha512-/XsOCk/XHYf9MAqcituMGrYeITiav9BW1oGM0LfmU1Gne/YnEvur4JwpJ4uJ0OrNennwIqMuAVM9Y5y/xfZ39w==",
+ "version": "1.27.3",
+ "resolved": "https://registry.npmjs.org/@percy/core/-/core-1.27.3.tgz",
+ "integrity": "sha512-LK+7dVLRQdVEQUG6Qn61awLbdYmazLwXWYg2UHqEWrbRIygkhoe+n3pPTwzxjiJxJsYYlelx/gDzGwjYzvV4aA==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
- "@percy/client": "1.27.1",
- "@percy/config": "1.27.1",
- "@percy/dom": "1.27.1",
- "@percy/logger": "1.27.1",
- "@percy/webdriver-utils": "1.27.1",
+ "@percy/client": "1.27.3",
+ "@percy/config": "1.27.3",
+ "@percy/dom": "1.27.3",
+ "@percy/logger": "1.27.3",
+ "@percy/webdriver-utils": "1.27.3",
"content-disposition": "^0.5.4",
"cross-spawn": "^7.0.3",
"extract-zip": "^2.0.1",
@@ -5898,45 +6143,45 @@
}
},
"node_modules/@percy/dom": {
- "version": "1.27.1",
- "resolved": "https://registry.npmjs.org/@percy/dom/-/dom-1.27.1.tgz",
- "integrity": "sha512-duYA3ATjADtn05VuGIfezgdCq+8ASwcY6Mzk857DzFIlJd/6T2P8v1dy66RRp78efzmIMtRroGy9SqWonlaAEA==",
+ "version": "1.27.3",
+ "resolved": "https://registry.npmjs.org/@percy/dom/-/dom-1.27.3.tgz",
+ "integrity": "sha512-QVSmogZhlVjy5mzqSesWbS5hjV8+1gMtAXSLtfRjdkZGQ/h2rnDbRZUW4PoJQ9ZpxBZegU5/W9LFvEO3FMVelA==",
"dev": true
},
"node_modules/@percy/env": {
- "version": "1.27.1",
- "resolved": "https://registry.npmjs.org/@percy/env/-/env-1.27.1.tgz",
- "integrity": "sha512-Og0vQfV9zJftYYOY3PVtu+r7Ut/xr72BP3jH3rkeQJHnFKLkwemGbJpgSpMz7IbzWXSxYONkNfUtLvXwEsRpAw==",
+ "version": "1.27.3",
+ "resolved": "https://registry.npmjs.org/@percy/env/-/env-1.27.3.tgz",
+ "integrity": "sha512-f9NwjAmcN6HEfJ2/32fmBwUJ3xjn/JXmGUKqmSvw0L3WZuvKaYRpYtaI+n0B6NsujZ4R+KUEGr0jczEoQ62UEg==",
"dev": true,
"dependencies": {
- "@percy/logger": "1.27.1"
+ "@percy/logger": "1.27.3"
},
"engines": {
"node": ">=14"
}
},
"node_modules/@percy/logger": {
- "version": "1.27.1",
- "resolved": "https://registry.npmjs.org/@percy/logger/-/logger-1.27.1.tgz",
- "integrity": "sha512-jH++paKzIY94fQYQBEedVTfO36I8WBqm2RNl/xzsnLuAwNEX5+JUsaPcbLrwRzhn/tCv+8h9xEBuE9nj23krIA==",
+ "version": "1.27.3",
+ "resolved": "https://registry.npmjs.org/@percy/logger/-/logger-1.27.3.tgz",
+ "integrity": "sha512-Z/XoEakUHVBivZqmRwFTwiOWT6v5nJgQ6V9aNs2FzjcpyFlJAFZTmHv8+craDKehmnND3tp8FGdPe34Ty0JhEQ==",
"dev": true,
"engines": {
"node": ">=14"
}
},
"node_modules/@percy/sdk-utils": {
- "version": "1.27.1",
- "resolved": "https://registry.npmjs.org/@percy/sdk-utils/-/sdk-utils-1.27.1.tgz",
- "integrity": "sha512-I12rBQYySyt8VILgYnI19obYtkaIPuFR07HVBrHLsRHiLUf92XzAtTI482qrnYwybCgU9mb9o3Kb7KtMJ0nalA==",
+ "version": "1.27.3",
+ "resolved": "https://registry.npmjs.org/@percy/sdk-utils/-/sdk-utils-1.27.3.tgz",
+ "integrity": "sha512-IhNx5VaYsKiHaFYFbX6BsVb4bNWojNrKyDa9aRF1afAWAeVWHd1Jq/XeVfMDNCrYcsrA+pYDPSXfb+N5cpAeGQ==",
"dev": true,
"engines": {
"node": ">=14"
}
},
"node_modules/@percy/storybook": {
- "version": "4.3.6",
- "resolved": "https://registry.npmjs.org/@percy/storybook/-/storybook-4.3.6.tgz",
- "integrity": "sha512-tLAVH86schBfq4NTMNIEDVABTnuVbrx9IKL7s5/2ONZqKsgJfgVBPBjSF38A1HyomSnD2mwYzZ1xR76G3usyxA==",
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/@percy/storybook/-/storybook-4.3.7.tgz",
+ "integrity": "sha512-8Tu0EZfZ7Y0suw5iElXjJSMzcyO9pE9IQfzlbbE2tHj8yeQqokOeVNYKPcuKNR21iJfBSFH1fYQZAE1qGuOv+w==",
"dev": true,
"dependencies": {
"@percy/cli-command": "^1.24.0",
@@ -5948,13 +6193,13 @@
}
},
"node_modules/@percy/webdriver-utils": {
- "version": "1.27.1",
- "resolved": "https://registry.npmjs.org/@percy/webdriver-utils/-/webdriver-utils-1.27.1.tgz",
- "integrity": "sha512-bPj16YmvV84egtMHyYEhlGYjwJTk0f6vopcbCYWgMgvQp78Y/RKwRm8ZpWZfW2rTqElNRudrhKdqcEeaG6qd9g==",
+ "version": "1.27.3",
+ "resolved": "https://registry.npmjs.org/@percy/webdriver-utils/-/webdriver-utils-1.27.3.tgz",
+ "integrity": "sha512-yV+7nc8aUPQHP1KnWwTndVHqvgs4xzCA8ObzRFuAaKSTC/hBgpI5ceCDv3aSM03ZtXk4f06AWtsgpU5BYpoP1A==",
"dev": true,
"dependencies": {
- "@percy/config": "1.27.1",
- "@percy/sdk-utils": "1.27.1"
+ "@percy/config": "1.27.3",
+ "@percy/sdk-utils": "1.27.3"
},
"engines": {
"node": ">=14"
@@ -5970,6 +6215,56 @@
"node": ">=14"
}
},
+ "node_modules/@pkgr/utils": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz",
+ "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "fast-glob": "^3.3.0",
+ "is-glob": "^4.0.3",
+ "open": "^9.1.0",
+ "picocolors": "^1.0.0",
+ "tslib": "^2.6.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
+ "node_modules/@pkgr/utils/node_modules/define-lazy-prop": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
+ "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@pkgr/utils/node_modules/open": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz",
+ "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==",
+ "dev": true,
+ "dependencies": {
+ "default-browser": "^4.0.0",
+ "define-lazy-prop": "^3.0.0",
+ "is-inside-container": "^1.0.0",
+ "is-wsl": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/@radix-ui/number": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.1.tgz",
@@ -6634,13 +6929,13 @@
}
},
"node_modules/@schematics/angular": {
- "version": "16.2.2",
- "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.2.tgz",
- "integrity": "sha512-OqPhpodkQx9pzSz7H2AGeEbf3ut6WOkJFP2YlX2JIGholfG/0FQMJmfTEyRoFXCBeVIDGt3sOmlfK7An0PS8uA==",
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.6.tgz",
+ "integrity": "sha512-fM09WPqST+nhVGV5Q3fhG7WKo96kgSVMsbz3wGS0DmTn4zge7ZWnrW3VvbxnMapmGoKa9DFPqdqNln4ADcdIMQ==",
"dev": true,
"dependencies": {
- "@angular-devkit/core": "16.2.2",
- "@angular-devkit/schematics": "16.2.2",
+ "@angular-devkit/core": "16.2.6",
+ "@angular-devkit/schematics": "16.2.6",
"jsonc-parser": "3.2.0"
},
"engines": {
@@ -6650,76 +6945,73 @@
}
},
"node_modules/@sentry-internal/tracing": {
- "version": "7.69.0",
- "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.69.0.tgz",
- "integrity": "sha512-4BgeWZUj9MO6IgfO93C9ocP3+AdngqujF/+zB2rFdUe+y9S6koDyUC7jr9Knds/0Ta72N/0D6PwhgSCpHK8s0Q==",
+ "version": "7.76.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.76.0.tgz",
+ "integrity": "sha512-QQVIv+LS2sbGf/e5P2dRisHzXpy02dAcLqENLPG4sZ9otRaFNjdFYEqnlJ4qko+ORpJGQEQp/BX7Q/qzZQHlAg==",
"dependencies": {
- "@sentry/core": "7.69.0",
- "@sentry/types": "7.69.0",
- "@sentry/utils": "7.69.0",
- "tslib": "^2.4.1 || ^1.9.3"
+ "@sentry/core": "7.76.0",
+ "@sentry/types": "7.76.0",
+ "@sentry/utils": "7.76.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/browser": {
- "version": "7.69.0",
- "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.69.0.tgz",
- "integrity": "sha512-5ls+zu2PrMhHCIIhclKQsWX5u6WH0Ez5/GgrCMZTtZ1d70ukGSRUvpZG9qGf5Cw1ezS1LY+1HCc3whf8x8lyPw==",
+ "version": "7.76.0",
+ "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.76.0.tgz",
+ "integrity": "sha512-83xA+cWrBhhkNuMllW5ucFsEO2NlUh2iBYtmg07lp3fyVW+6+b1yMKRnc4RFArJ+Wcq6UO+qk2ZEvrSAts1wEw==",
"dependencies": {
- "@sentry-internal/tracing": "7.69.0",
- "@sentry/core": "7.69.0",
- "@sentry/replay": "7.69.0",
- "@sentry/types": "7.69.0",
- "@sentry/utils": "7.69.0",
- "tslib": "^2.4.1 || ^1.9.3"
+ "@sentry-internal/tracing": "7.76.0",
+ "@sentry/core": "7.76.0",
+ "@sentry/replay": "7.76.0",
+ "@sentry/types": "7.76.0",
+ "@sentry/utils": "7.76.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/core": {
- "version": "7.69.0",
- "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.69.0.tgz",
- "integrity": "sha512-V6jvK2lS8bhqZDMFUtvwe2XvNstFQf5A+2LMKCNBOV/NN6eSAAd6THwEpginabjet9dHsNRmMk7WNKvrUfQhZw==",
+ "version": "7.76.0",
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.76.0.tgz",
+ "integrity": "sha512-M+ptkCTeCNf6fn7p2MmEb1Wd9/JXUWxIT/0QEc+t11DNR4FYy1ZP2O9Zb3Zp2XacO7ORrlL3Yc+VIfl5JTgjfw==",
"dependencies": {
- "@sentry/types": "7.69.0",
- "@sentry/utils": "7.69.0",
- "tslib": "^2.4.1 || ^1.9.3"
+ "@sentry/types": "7.76.0",
+ "@sentry/utils": "7.76.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/replay": {
- "version": "7.69.0",
- "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.69.0.tgz",
- "integrity": "sha512-oUqWyBPFUgShdVvgJtV65EQH9pVDmoYVQMOu59JI6FHVeL3ald7R5Mvz6GaNLXsirvvhp0yAkcAd2hc5Xi6hDw==",
+ "version": "7.76.0",
+ "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.76.0.tgz",
+ "integrity": "sha512-OACT7MfMHC/YGKnKST8SF1d6znr3Yu8fpUpfVVh2t9TNeh3+cQJVTOliHDqLy+k9Ljd5FtitgSn4IHtseCHDLQ==",
"dependencies": {
- "@sentry/core": "7.69.0",
- "@sentry/types": "7.69.0",
- "@sentry/utils": "7.69.0"
+ "@sentry-internal/tracing": "7.76.0",
+ "@sentry/core": "7.76.0",
+ "@sentry/types": "7.76.0",
+ "@sentry/utils": "7.76.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry/types": {
- "version": "7.69.0",
- "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.69.0.tgz",
- "integrity": "sha512-zPyCox0mzitzU6SIa1KIbNoJAInYDdUpdiA+PoUmMn2hFMH1llGU/cS7f4w/mAsssTlbtlBi72RMnWUCy578bw==",
+ "version": "7.76.0",
+ "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.76.0.tgz",
+ "integrity": "sha512-vj6z+EAbVrKAXmJPxSv/clpwS9QjPqzkraMFk2hIdE/kii8s8kwnkBwTSpIrNc8GnzV3qYC4r3qD+BXDxAGPaw==",
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/utils": {
- "version": "7.69.0",
- "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.69.0.tgz",
- "integrity": "sha512-4eBixe5Y+0EGVU95R4NxH3jkkjtkE4/CmSZD4In8SCkWGSauogePtq6hyiLsZuP1QHdpPb9Kt0+zYiBb2LouBA==",
+ "version": "7.76.0",
+ "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.76.0.tgz",
+ "integrity": "sha512-40jFD+yfQaKpFYINghdhovzec4IEpB7aAuyH/GtE7E0gLpcqnC72r55krEIVILfqIR2Mlr5OKUzyeoCyWAU/yw==",
"dependencies": {
- "@sentry/types": "7.69.0",
- "tslib": "^2.4.1 || ^1.9.3"
+ "@sentry/types": "7.76.0"
},
"engines": {
"node": ">=8"
@@ -6786,19 +7078,19 @@
"dev": true
},
"node_modules/@storybook/addon-actions": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-7.4.1.tgz",
- "integrity": "sha512-ZCrBUpCAxgMCrcMGvBOhh+8uUZ9HhoCIOfV1XiaTXpE9Y2lqIqfRsc18E/ST3zN25Waf/LcJPJF2Dp/VSSoGpA==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-7.5.0.tgz",
+ "integrity": "sha512-eeHIFpZXGyhkfmrbHRf3rndL+ppFqlKTgN74y+UfFaAWNUhV3caXxRbHV3BbcPSLkRAsNShBH9hTNTlUAHSVjA==",
"dev": true,
"dependencies": {
- "@storybook/client-logger": "7.4.1",
- "@storybook/components": "7.4.1",
- "@storybook/core-events": "7.4.1",
+ "@storybook/client-logger": "7.5.0",
+ "@storybook/components": "7.5.0",
+ "@storybook/core-events": "7.5.0",
"@storybook/global": "^5.0.0",
- "@storybook/manager-api": "7.4.1",
- "@storybook/preview-api": "7.4.1",
- "@storybook/theming": "7.4.1",
- "@storybook/types": "7.4.1",
+ "@storybook/manager-api": "7.5.0",
+ "@storybook/preview-api": "7.5.0",
+ "@storybook/theming": "7.5.0",
+ "@storybook/types": "7.5.0",
"dequal": "^2.0.2",
"lodash": "^4.17.21",
"polished": "^4.2.2",
@@ -6826,19 +7118,19 @@
}
},
"node_modules/@storybook/addon-backgrounds": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-7.4.1.tgz",
- "integrity": "sha512-srmY6S9RAYkApjy49lYwKMFDpRp1XCws0pwHV0QoRBl7zibqUwr3PexkryK0uopPDhnfZRtRykPG5gzePNntmA==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-7.5.0.tgz",
+ "integrity": "sha512-Yu/eFHZIfyAhK28GKKcIBwj/9+hRem8pSdI3N0FJuOhErmaE0zg6VDUBzkgLa/Fn9SwC5PNyAeLAtxssg1KSNg==",
"dev": true,
"dependencies": {
- "@storybook/client-logger": "7.4.1",
- "@storybook/components": "7.4.1",
- "@storybook/core-events": "7.4.1",
+ "@storybook/client-logger": "7.5.0",
+ "@storybook/components": "7.5.0",
+ "@storybook/core-events": "7.5.0",
"@storybook/global": "^5.0.0",
- "@storybook/manager-api": "7.4.1",
- "@storybook/preview-api": "7.4.1",
- "@storybook/theming": "7.4.1",
- "@storybook/types": "7.4.1",
+ "@storybook/manager-api": "7.5.0",
+ "@storybook/preview-api": "7.5.0",
+ "@storybook/theming": "7.5.0",
+ "@storybook/types": "7.5.0",
"memoizerific": "^1.11.3",
"ts-dedent": "^2.0.0"
},
@@ -6860,21 +7152,21 @@
}
},
"node_modules/@storybook/addon-controls": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-7.4.1.tgz",
- "integrity": "sha512-KlCYprhBerAKItVQKpexR1oParTbNDOZpJbonG+uldZ12FV7kkrTEGD1vwoLtYTLy+QXIGg4MI1cmUpd39LrLg==",
- "dev": true,
- "dependencies": {
- "@storybook/blocks": "7.4.1",
- "@storybook/client-logger": "7.4.1",
- "@storybook/components": "7.4.1",
- "@storybook/core-common": "7.4.1",
- "@storybook/core-events": "7.4.1",
- "@storybook/manager-api": "7.4.1",
- "@storybook/node-logger": "7.4.1",
- "@storybook/preview-api": "7.4.1",
- "@storybook/theming": "7.4.1",
- "@storybook/types": "7.4.1",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-7.5.0.tgz",
+ "integrity": "sha512-X56Pd+0GH1A8ddVsziJQaJ8qCaxsWK0aLCKH5li9GLtnyIGHvd5+KvvfYEbjTkeJv3d9J7X0D4uTAH1/dsmI8w==",
+ "dev": true,
+ "dependencies": {
+ "@storybook/blocks": "7.5.0",
+ "@storybook/client-logger": "7.5.0",
+ "@storybook/components": "7.5.0",
+ "@storybook/core-common": "7.5.0",
+ "@storybook/core-events": "7.5.0",
+ "@storybook/manager-api": "7.5.0",
+ "@storybook/node-logger": "7.5.0",
+ "@storybook/preview-api": "7.5.0",
+ "@storybook/theming": "7.5.0",
+ "@storybook/types": "7.5.0",
"lodash": "^4.17.21",
"ts-dedent": "^2.0.0"
},
@@ -6896,26 +7188,26 @@
}
},
"node_modules/@storybook/addon-docs": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-7.4.1.tgz",
- "integrity": "sha512-rhLeIX30Z/UsCp7tKtUJyGXWJ2Wggtkl+n6hyaW3orQlSQbsndqJ1rGIs0lHScrDv0dKwT2Dcp2WaEXWHRmgEw==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-7.5.0.tgz",
+ "integrity": "sha512-lgrum81iJT+i85kO3uOR4wR1t05x4SmJLCB2cyYohCIafiOiV4FuyYFhvT9N6UhHByOfrWgpipKgKg6zsmV2eg==",
"dev": true,
"dependencies": {
"@jest/transform": "^29.3.1",
"@mdx-js/react": "^2.1.5",
- "@storybook/blocks": "7.4.1",
- "@storybook/client-logger": "7.4.1",
- "@storybook/components": "7.4.1",
- "@storybook/csf-plugin": "7.4.1",
- "@storybook/csf-tools": "7.4.1",
+ "@storybook/blocks": "7.5.0",
+ "@storybook/client-logger": "7.5.0",
+ "@storybook/components": "7.5.0",
+ "@storybook/csf-plugin": "7.5.0",
+ "@storybook/csf-tools": "7.5.0",
"@storybook/global": "^5.0.0",
"@storybook/mdx2-csf": "^1.0.0",
- "@storybook/node-logger": "7.4.1",
- "@storybook/postinstall": "7.4.1",
- "@storybook/preview-api": "7.4.1",
- "@storybook/react-dom-shim": "7.4.1",
- "@storybook/theming": "7.4.1",
- "@storybook/types": "7.4.1",
+ "@storybook/node-logger": "7.5.0",
+ "@storybook/postinstall": "7.5.0",
+ "@storybook/preview-api": "7.5.0",
+ "@storybook/react-dom-shim": "7.5.0",
+ "@storybook/theming": "7.5.0",
+ "@storybook/types": "7.5.0",
"fs-extra": "^11.1.0",
"remark-external-links": "^8.0.0",
"remark-slug": "^6.0.0",
@@ -6931,24 +7223,24 @@
}
},
"node_modules/@storybook/addon-essentials": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-7.4.1.tgz",
- "integrity": "sha512-Ma63h7gQ2uQgMBvMYlrevurqtzbXFfyuHgYp1PZrhFUCuiC7f1yKkxp5X+jLcfXrG2IsPIuBxLBMYtSpRu6izA==",
- "dev": true,
- "dependencies": {
- "@storybook/addon-actions": "7.4.1",
- "@storybook/addon-backgrounds": "7.4.1",
- "@storybook/addon-controls": "7.4.1",
- "@storybook/addon-docs": "7.4.1",
- "@storybook/addon-highlight": "7.4.1",
- "@storybook/addon-measure": "7.4.1",
- "@storybook/addon-outline": "7.4.1",
- "@storybook/addon-toolbars": "7.4.1",
- "@storybook/addon-viewport": "7.4.1",
- "@storybook/core-common": "7.4.1",
- "@storybook/manager-api": "7.4.1",
- "@storybook/node-logger": "7.4.1",
- "@storybook/preview-api": "7.4.1",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-7.5.0.tgz",
+ "integrity": "sha512-CKPHdQBP6psTVb3NHsP8cWSUcAA4kwzT8SrJxKddn4ecqmWJWeZo5g5y3WuqVQHlv3edpluJLQYehcVibcljag==",
+ "dev": true,
+ "dependencies": {
+ "@storybook/addon-actions": "7.5.0",
+ "@storybook/addon-backgrounds": "7.5.0",
+ "@storybook/addon-controls": "7.5.0",
+ "@storybook/addon-docs": "7.5.0",
+ "@storybook/addon-highlight": "7.5.0",
+ "@storybook/addon-measure": "7.5.0",
+ "@storybook/addon-outline": "7.5.0",
+ "@storybook/addon-toolbars": "7.5.0",
+ "@storybook/addon-viewport": "7.5.0",
+ "@storybook/core-common": "7.5.0",
+ "@storybook/manager-api": "7.5.0",
+ "@storybook/node-logger": "7.5.0",
+ "@storybook/preview-api": "7.5.0",
"ts-dedent": "^2.0.0"
},
"funding": {
@@ -6961,14 +7253,14 @@
}
},
"node_modules/@storybook/addon-highlight": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-7.4.1.tgz",
- "integrity": "sha512-7fD3//+FHOankINRhPnAuW2gLNC7oJMT0eFD0sHrQPG5qMpR+T7u8mqyI05kPszyiY9U72LRfjrf8GL1Hac8gQ==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-7.5.0.tgz",
+ "integrity": "sha512-6SlEkGCZ/LnEcbN6oE2Au3fgI9VfULErWQ36bx+sV6WWTb1EoooiD7ZJJzobrcOAriSyfWoctO5DF4W+X9I8lg==",
"dev": true,
"dependencies": {
- "@storybook/core-events": "7.4.1",
+ "@storybook/core-events": "7.5.0",
"@storybook/global": "^5.0.0",
- "@storybook/preview-api": "7.4.1"
+ "@storybook/preview-api": "7.5.0"
},
"funding": {
"type": "opencollective",
@@ -6976,18 +7268,18 @@
}
},
"node_modules/@storybook/addon-measure": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-7.4.1.tgz",
- "integrity": "sha512-OFRBGlA8Bs04vJe2dAP2KK+Juus0JrdfLeeW0wm1RQGYCHJZb0awiI59wQ3rJLyS9IEDl95VaNgWrsyCu5YnIw==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-7.5.0.tgz",
+ "integrity": "sha512-zzHrQpn+burEr37hV1QV7yA1M33wBa38dUe+RLNYkS9g22BXYYZ/uVUhljpmA9DhZCUNJqYbXWi+ad4XMPE6+Q==",
"dev": true,
"dependencies": {
- "@storybook/client-logger": "7.4.1",
- "@storybook/components": "7.4.1",
- "@storybook/core-events": "7.4.1",
+ "@storybook/client-logger": "7.5.0",
+ "@storybook/components": "7.5.0",
+ "@storybook/core-events": "7.5.0",
"@storybook/global": "^5.0.0",
- "@storybook/manager-api": "7.4.1",
- "@storybook/preview-api": "7.4.1",
- "@storybook/types": "7.4.1",
+ "@storybook/manager-api": "7.5.0",
+ "@storybook/preview-api": "7.5.0",
+ "@storybook/types": "7.5.0",
"tiny-invariant": "^1.3.1"
},
"funding": {
@@ -7008,18 +7300,18 @@
}
},
"node_modules/@storybook/addon-outline": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-7.4.1.tgz",
- "integrity": "sha512-HnBQbHLTEHFzeuzNu39Hjol5cCOsXpb406oeD+u8wv6udfDYClg1QmVEaVKddgPooTy9Gv9ztpYlAaMBfSjnmQ==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-7.5.0.tgz",
+ "integrity": "sha512-iVcyFi2N2NEZRytUg8wSiXS9UE9wA8/prs/sIsQ7Y34vHm1UaqAd8KxCE/fhHFNYw4UyHEEDUyTfci/jNrNQYA==",
"dev": true,
"dependencies": {
- "@storybook/client-logger": "7.4.1",
- "@storybook/components": "7.4.1",
- "@storybook/core-events": "7.4.1",
+ "@storybook/client-logger": "7.5.0",
+ "@storybook/components": "7.5.0",
+ "@storybook/core-events": "7.5.0",
"@storybook/global": "^5.0.0",
- "@storybook/manager-api": "7.4.1",
- "@storybook/preview-api": "7.4.1",
- "@storybook/types": "7.4.1",
+ "@storybook/manager-api": "7.5.0",
+ "@storybook/preview-api": "7.5.0",
+ "@storybook/types": "7.5.0",
"ts-dedent": "^2.0.0"
},
"funding": {
@@ -7040,16 +7332,16 @@
}
},
"node_modules/@storybook/addon-toolbars": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-7.4.1.tgz",
- "integrity": "sha512-CWHMBCKomQ5JkoFmFD66uo5A2Xa4ER+DX2Kb0oX62s35mBaNOfJVois++i/2Or8BwOUl61x5/3UdPgN2rWHeSw==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-7.5.0.tgz",
+ "integrity": "sha512-RLONWIJE7myVL3DzWZDWnnmb53C1OitCiO3mDt678xyK5ZrFCOV9cznckXASx1wNJVt3P9OOW1N2UY7wul72+Q==",
"dev": true,
"dependencies": {
- "@storybook/client-logger": "7.4.1",
- "@storybook/components": "7.4.1",
- "@storybook/manager-api": "7.4.1",
- "@storybook/preview-api": "7.4.1",
- "@storybook/theming": "7.4.1"
+ "@storybook/client-logger": "7.5.0",
+ "@storybook/components": "7.5.0",
+ "@storybook/manager-api": "7.5.0",
+ "@storybook/preview-api": "7.5.0",
+ "@storybook/theming": "7.5.0"
},
"funding": {
"type": "opencollective",
@@ -7069,18 +7361,18 @@
}
},
"node_modules/@storybook/addon-viewport": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-7.4.1.tgz",
- "integrity": "sha512-3bdRPIFAqZcdGe3XSS9X4T3is6DP8FGytpU96SwnAllG3rI7kQHxmC7pn6mrdNMpLBHq47ZSABoRZZLq8bT/AA==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-7.5.0.tgz",
+ "integrity": "sha512-NXnjHQFKgeFsWOaJE0fl2THgejxDqx8axy4Prtc3ePcoVa/UrMu11G3iEcCaLhDJU7RDNM6CODgifYpH6gyKWg==",
"dev": true,
"dependencies": {
- "@storybook/client-logger": "7.4.1",
- "@storybook/components": "7.4.1",
- "@storybook/core-events": "7.4.1",
+ "@storybook/client-logger": "7.5.0",
+ "@storybook/components": "7.5.0",
+ "@storybook/core-events": "7.5.0",
"@storybook/global": "^5.0.0",
- "@storybook/manager-api": "7.4.1",
- "@storybook/preview-api": "7.4.1",
- "@storybook/theming": "7.4.1",
+ "@storybook/manager-api": "7.5.0",
+ "@storybook/preview-api": "7.5.0",
+ "@storybook/theming": "7.5.0",
"memoizerific": "^1.11.3",
"prop-types": "^15.7.2"
},
@@ -7101,46 +7393,27 @@
}
}
},
- "node_modules/@storybook/addons": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-7.4.1.tgz",
- "integrity": "sha512-sedMROyWFwlV6gtPHeOhps2/9UpcCmMLnYDhIueu2fAw/Djz0nYVNY2N6ZNiP/eqZISTLr9RzeBfAcymyjAJ2A==",
- "dev": true,
- "dependencies": {
- "@storybook/manager-api": "7.4.1",
- "@storybook/preview-api": "7.4.1",
- "@storybook/types": "7.4.1"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/storybook"
- },
- "peerDependencies": {
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
- "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
- }
- },
"node_modules/@storybook/angular": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/angular/-/angular-7.4.1.tgz",
- "integrity": "sha512-z4FUcNyLWlheXttfukshnGKMyW29NYmL/Uk7O5lq3DNb54WPZe6Q5QV9418L8jcnwe54LlEJZXlP6AlNNslxjQ==",
- "dev": true,
- "dependencies": {
- "@storybook/builder-webpack5": "7.4.1",
- "@storybook/cli": "7.4.1",
- "@storybook/client-logger": "7.4.1",
- "@storybook/core-common": "7.4.1",
- "@storybook/core-events": "7.4.1",
- "@storybook/core-server": "7.4.1",
- "@storybook/core-webpack": "7.4.1",
- "@storybook/docs-tools": "7.4.1",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/angular/-/angular-7.5.0.tgz",
+ "integrity": "sha512-TJdPTXaKazZjA+KaRzbzM8QET48J/Lqfk0wwaNamAY/KvXI6akKgeXJ3Y9SUsmNA9G3QnEMeFAFYvj95XGOwWQ==",
+ "dev": true,
+ "dependencies": {
+ "@storybook/builder-webpack5": "7.5.0",
+ "@storybook/cli": "7.5.0",
+ "@storybook/client-logger": "7.5.0",
+ "@storybook/core-common": "7.5.0",
+ "@storybook/core-events": "7.5.0",
+ "@storybook/core-server": "7.5.0",
+ "@storybook/core-webpack": "7.5.0",
+ "@storybook/docs-tools": "7.5.0",
"@storybook/global": "^5.0.0",
- "@storybook/manager-api": "7.4.1",
- "@storybook/node-logger": "7.4.1",
- "@storybook/preview-api": "7.4.1",
- "@storybook/telemetry": "7.4.1",
- "@storybook/types": "7.4.1",
- "@types/node": "^16.0.0",
+ "@storybook/manager-api": "7.5.0",
+ "@storybook/node-logger": "7.5.0",
+ "@storybook/preview-api": "7.5.0",
+ "@storybook/telemetry": "7.5.0",
+ "@storybook/types": "7.5.0",
+ "@types/node": "^18.0.0",
"@types/react": "^16.14.34",
"@types/react-dom": "^16.9.14",
"@types/semver": "^7.3.4",
@@ -7178,7 +7451,7 @@
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
"rxjs": "^6.0.0 || ^7.4.0",
"typescript": "^4.0.0 || ^5.0.0",
- "zone.js": "^0.8.29 || >= 0.9.0 < 1.0.0"
+ "zone.js": ">= 0.11.1 < 1.0.0"
},
"peerDependenciesMeta": {
"@angular/cli": {
@@ -7187,15 +7460,15 @@
}
},
"node_modules/@storybook/angular/node_modules/@types/node": {
- "version": "16.18.50",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.50.tgz",
- "integrity": "sha512-OiDU5xRgYTJ203v4cprTs0RwOCd5c5Zjv+K5P8KSqfiCsB1W3LcamTUMcnQarpq5kOYbhHfSOgIEJvdPyb5xyw==",
+ "version": "18.18.6",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.6.tgz",
+ "integrity": "sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==",
"dev": true
},
"node_modules/@storybook/angular/node_modules/@types/react": {
- "version": "16.14.46",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.46.tgz",
- "integrity": "sha512-Am4pyXMrr6cWWw/TN3oqHtEZl0j+G6Up/O8m65+xF/3ZaUgkv1GAtTPWw4yNRmH0HJXmur6xKCKoMo3rBGynuw==",
+ "version": "16.14.50",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.50.tgz",
+ "integrity": "sha512-7TWZ/HjhXsRK3BbhSFxTinbSft3sUXJAU3ONngT0rpcKJaIOlxkRke4bidqQTopUbEv1ApC5nlSEkIpX43MkTg==",
"dev": true,
"dependencies": {
"@types/prop-types": "*",
@@ -7204,22 +7477,22 @@
}
},
"node_modules/@storybook/blocks": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-7.4.1.tgz",
- "integrity": "sha512-allNTTuFcFK/DzGGQqFGPu/bH53wjM7lO9m/yHBtJv8Mi1aP745JqW0ucJMVb/aO2Y8vjkTIVa+meVIl02bfrg==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-7.5.0.tgz",
+ "integrity": "sha512-4poS7lQVKhitWKl0TPECMszOMtNamsbNvZdAZ188U/p1EzTrqLg+RT9HtsB8q8Y0owx29Nh5LdfhNOddpx23ig==",
"dev": true,
"dependencies": {
- "@storybook/channels": "7.4.1",
- "@storybook/client-logger": "7.4.1",
- "@storybook/components": "7.4.1",
- "@storybook/core-events": "7.4.1",
+ "@storybook/channels": "7.5.0",
+ "@storybook/client-logger": "7.5.0",
+ "@storybook/components": "7.5.0",
+ "@storybook/core-events": "7.5.0",
"@storybook/csf": "^0.1.0",
- "@storybook/docs-tools": "7.4.1",
+ "@storybook/docs-tools": "7.5.0",
"@storybook/global": "^5.0.0",
- "@storybook/manager-api": "7.4.1",
- "@storybook/preview-api": "7.4.1",
- "@storybook/theming": "7.4.1",
- "@storybook/types": "7.4.1",
+ "@storybook/manager-api": "7.5.0",
+ "@storybook/preview-api": "7.5.0",
+ "@storybook/theming": "7.5.0",
+ "@storybook/types": "7.5.0",
"@types/lodash": "^4.14.167",
"color-convert": "^2.0.1",
"dequal": "^2.0.2",
@@ -7243,15 +7516,15 @@
}
},
"node_modules/@storybook/builder-manager": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/builder-manager/-/builder-manager-7.4.1.tgz",
- "integrity": "sha512-5zD10jO+vxpbkz9yPdPy0ysRRd+81GmZ1yf12xARREy2hp+KeIIC228QDVA1OAsYcfnqREgCAnQslzhR57739A==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/builder-manager/-/builder-manager-7.5.0.tgz",
+ "integrity": "sha512-nj+n36i7Mds4RIyGJqvOB+Z47zfgbMes+6Gd6reT1vC22Yda5nAITnd2vxbYfv/sUPhIBBfuFZ/eogomgYCjKg==",
"dev": true,
"dependencies": {
"@fal-works/esbuild-plugin-global-externals": "^2.1.2",
- "@storybook/core-common": "7.4.1",
- "@storybook/manager": "7.4.1",
- "@storybook/node-logger": "7.4.1",
+ "@storybook/core-common": "7.5.0",
+ "@storybook/manager": "7.5.0",
+ "@storybook/node-logger": "7.5.0",
"@types/ejs": "^3.1.1",
"@types/find-cache-dir": "^3.2.1",
"@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.10",
@@ -7271,30 +7544,22 @@
}
},
"node_modules/@storybook/builder-webpack5": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-7.4.1.tgz",
- "integrity": "sha512-1Z4eod4a6Q2LbiTvI+sipM/ehQb9dtTD5W/3y8js2tQ8L8PE9q7CP3J64mJvEJ3Zh2Uc5S+CKqHoH6/Px3ZNcw==",
- "dev": true,
- "dependencies": {
- "@babel/core": "^7.22.9",
- "@storybook/addons": "7.4.1",
- "@storybook/channels": "7.4.1",
- "@storybook/client-api": "7.4.1",
- "@storybook/client-logger": "7.4.1",
- "@storybook/components": "7.4.1",
- "@storybook/core-common": "7.4.1",
- "@storybook/core-events": "7.4.1",
- "@storybook/core-webpack": "7.4.1",
- "@storybook/global": "^5.0.0",
- "@storybook/manager-api": "7.4.1",
- "@storybook/node-logger": "7.4.1",
- "@storybook/preview": "7.4.1",
- "@storybook/preview-api": "7.4.1",
- "@storybook/router": "7.4.1",
- "@storybook/store": "7.4.1",
- "@storybook/theming": "7.4.1",
- "@swc/core": "^1.3.49",
- "@types/node": "^16.0.0",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-7.5.0.tgz",
+ "integrity": "sha512-bZRIkJCLdwiPZIUIE5NxEHF+gTO/+4AB/t5/w7UnBhuydDgFStY3cBJHC7wp3crgRuNd4eZJYb2YCqcD/hAgVQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.22.0",
+ "@storybook/channels": "7.5.0",
+ "@storybook/client-logger": "7.5.0",
+ "@storybook/core-common": "7.5.0",
+ "@storybook/core-events": "7.5.0",
+ "@storybook/core-webpack": "7.5.0",
+ "@storybook/node-logger": "7.5.0",
+ "@storybook/preview": "7.5.0",
+ "@storybook/preview-api": "7.5.0",
+ "@swc/core": "^1.3.82",
+ "@types/node": "^18.0.0",
"@types/semver": "^7.3.4",
"babel-loader": "^9.0.0",
"babel-plugin-named-exports-order": "^0.0.2",
@@ -7325,10 +7590,6 @@
"type": "opencollective",
"url": "https://opencollective.com/storybook"
},
- "peerDependencies": {
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
- "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
- },
"peerDependenciesMeta": {
"typescript": {
"optional": true
@@ -7336,19 +7597,19 @@
}
},
"node_modules/@storybook/builder-webpack5/node_modules/@types/node": {
- "version": "16.18.50",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.50.tgz",
- "integrity": "sha512-OiDU5xRgYTJ203v4cprTs0RwOCd5c5Zjv+K5P8KSqfiCsB1W3LcamTUMcnQarpq5kOYbhHfSOgIEJvdPyb5xyw==",
+ "version": "18.18.6",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.6.tgz",
+ "integrity": "sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==",
"dev": true
},
"node_modules/@storybook/channels": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.4.1.tgz",
- "integrity": "sha512-gnE1mNrRF+9oCVRMq6MS/tLXJbYmf9P02PCC3KpMLcSsABdH5jcrACejzJVo/kE223knFH7NJc4BBj7+5h0uXA==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.5.0.tgz",
+ "integrity": "sha512-/7QJS1UA7TX3uhZqCpjv4Ib8nfMnDOJrBWvjiXiUONaRcSk/he5X+W1Zz/c7dgt+wkYuAh+evjc7glIaBhVNVQ==",
"dev": true,
"dependencies": {
- "@storybook/client-logger": "7.4.1",
- "@storybook/core-events": "7.4.1",
+ "@storybook/client-logger": "7.5.0",
+ "@storybook/core-events": "7.5.0",
"@storybook/global": "^5.0.0",
"qs": "^6.10.0",
"telejson": "^7.2.0",
@@ -7360,23 +7621,23 @@
}
},
"node_modules/@storybook/cli": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/cli/-/cli-7.4.1.tgz",
- "integrity": "sha512-G1oM1Egs5Z/5FOBcqfACJy2u5cDPl8FMFr3CETkn15a5MXzX3qxH8FD8GmZnXIsEDsGH5WvhnXYbCw+43R6GKg==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/cli/-/cli-7.5.0.tgz",
+ "integrity": "sha512-f14q6sqHhDf7bFS0o/ZTgN2tM00Q0cMGMmGFXTQSCh0HXJUS4ujy/FADL+x62wUylIdr1HkIw+ONWMMqHuenEA==",
"dev": true,
"dependencies": {
"@babel/core": "^7.22.9",
"@babel/preset-env": "^7.22.9",
"@babel/types": "^7.22.5",
"@ndelangen/get-tarball": "^3.0.7",
- "@storybook/codemod": "7.4.1",
- "@storybook/core-common": "7.4.1",
- "@storybook/core-events": "7.4.1",
- "@storybook/core-server": "7.4.1",
- "@storybook/csf-tools": "7.4.1",
- "@storybook/node-logger": "7.4.1",
- "@storybook/telemetry": "7.4.1",
- "@storybook/types": "7.4.1",
+ "@storybook/codemod": "7.5.0",
+ "@storybook/core-common": "7.5.0",
+ "@storybook/core-events": "7.5.0",
+ "@storybook/core-server": "7.5.0",
+ "@storybook/csf-tools": "7.5.0",
+ "@storybook/node-logger": "7.5.0",
+ "@storybook/telemetry": "7.5.0",
+ "@storybook/types": "7.5.0",
"@types/semver": "^7.3.4",
"@yarnpkg/fslib": "2.10.3",
"@yarnpkg/libzip": "2.3.0",
@@ -7492,24 +7753,10 @@
"node": ">=8"
}
},
- "node_modules/@storybook/client-api": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-7.4.1.tgz",
- "integrity": "sha512-B1sQhVv1vq7L1xcvzBT3n4gjG63GTD2KcexJVxcdkVaWNHxE6/QrX+gtsHFevkYI5sjs+sR9fdljALxMf2I0mQ==",
- "dev": true,
- "dependencies": {
- "@storybook/client-logger": "7.4.1",
- "@storybook/preview-api": "7.4.1"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/storybook"
- }
- },
"node_modules/@storybook/client-logger": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.4.1.tgz",
- "integrity": "sha512-2j0DQlKlPNY8XAaEZv+mUYEUm4dOWg6/Q92UNbvYPRK5qbXUvbMiQco5nmvg4LvMT6y99LhRSW2xrwEx5xKAKw==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.5.0.tgz",
+ "integrity": "sha512-JV7J9vc69f9Il4uW62NIeweUU7O38VwFWxtCkhd0bcBA/9RG0go4M2avzxYYEAe9kIOX9IBBk8WGzMacwW4gKQ==",
"dev": true,
"dependencies": {
"@storybook/global": "^5.0.0"
@@ -7520,18 +7767,18 @@
}
},
"node_modules/@storybook/codemod": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-7.4.1.tgz",
- "integrity": "sha512-KlN2oImqc45RLNRJDWJObvYcLzdtkk4fH40nBIP1/nem8AEbyjEbC5c1OtZilEV47Vn8IdAxqGRPQFXW8GVFEQ==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-7.5.0.tgz",
+ "integrity": "sha512-QdjFdD1OK+LqhYwNMh60/kgSt9VZIgH2TBUeXrPlCK6gfcZBrCB0ktgtuM8Zk/ROktq09pZoVDxqFi0AbEUPew==",
"dev": true,
"dependencies": {
"@babel/core": "^7.22.9",
"@babel/preset-env": "^7.22.9",
"@babel/types": "^7.22.5",
"@storybook/csf": "^0.1.0",
- "@storybook/csf-tools": "7.4.1",
- "@storybook/node-logger": "7.4.1",
- "@storybook/types": "7.4.1",
+ "@storybook/csf-tools": "7.5.0",
+ "@storybook/node-logger": "7.5.0",
+ "@storybook/types": "7.5.0",
"@types/cross-spawn": "^6.0.2",
"cross-spawn": "^7.0.3",
"globby": "^11.0.2",
@@ -7561,18 +7808,18 @@
}
},
"node_modules/@storybook/components": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/components/-/components-7.4.1.tgz",
- "integrity": "sha512-hCuKmMB0+d3/apHjC8G0vMks1cE1aeoKu09gQ40YT+cBxKWj2+lNVKxDd6wJpaR6bU/wrAL1S6eaIQ/T9QpqRA==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/components/-/components-7.5.0.tgz",
+ "integrity": "sha512-6lmZ6PbS27xN32vTJ/NvgaiKkFIQRzZuBeBIg2u+FoAEgCiCwRXjZKe/O8NZC2Xr0uf97+7U2P0kD4Hwr9SNhw==",
"dev": true,
"dependencies": {
"@radix-ui/react-select": "^1.2.2",
"@radix-ui/react-toolbar": "^1.0.4",
- "@storybook/client-logger": "7.4.1",
+ "@storybook/client-logger": "7.5.0",
"@storybook/csf": "^0.1.0",
"@storybook/global": "^5.0.0",
- "@storybook/theming": "7.4.1",
- "@storybook/types": "7.4.1",
+ "@storybook/theming": "7.5.0",
+ "@storybook/types": "7.5.0",
"memoizerific": "^1.11.3",
"use-resize-observer": "^9.1.0",
"util-deprecate": "^1.0.2"
@@ -7587,21 +7834,21 @@
}
},
"node_modules/@storybook/core-common": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-7.4.1.tgz",
- "integrity": "sha512-dvHY515l9yyH3Yki9CuGF/LG85yWDmhjtlbHJ7mrMSreaAgvDs7O5Q2iVh6DXg3oMspQvKlLii/ZLzu+3uxMbg==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-7.5.0.tgz",
+ "integrity": "sha512-Gw3/rzRb5+XbwqBcr2ZNaIYGEp+WNTwaBOnMs4yp2SCrNIb0P+i3BxlVQdgABaq43EI3/bksowT6hei0jyhGhw==",
"dev": true,
"dependencies": {
- "@storybook/core-events": "7.4.1",
- "@storybook/node-logger": "7.4.1",
- "@storybook/types": "7.4.1",
+ "@storybook/core-events": "7.5.0",
+ "@storybook/node-logger": "7.5.0",
+ "@storybook/types": "7.5.0",
"@types/find-cache-dir": "^3.2.1",
- "@types/node": "^16.0.0",
+ "@types/node": "^18.0.0",
"@types/node-fetch": "^2.6.4",
"@types/pretty-hrtime": "^1.0.0",
"chalk": "^4.1.0",
"esbuild": "^0.18.0",
- "esbuild-register": "^3.4.0",
+ "esbuild-register": "^3.5.0",
"file-system-cache": "2.3.0",
"find-cache-dir": "^3.0.0",
"find-up": "^5.0.0",
@@ -7622,9 +7869,9 @@
}
},
"node_modules/@storybook/core-common/node_modules/@types/node": {
- "version": "16.18.50",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.50.tgz",
- "integrity": "sha512-OiDU5xRgYTJ203v4cprTs0RwOCd5c5Zjv+K5P8KSqfiCsB1W3LcamTUMcnQarpq5kOYbhHfSOgIEJvdPyb5xyw==",
+ "version": "18.18.6",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.6.tgz",
+ "integrity": "sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==",
"dev": true
},
"node_modules/@storybook/core-common/node_modules/ansi-styles": {
@@ -7680,9 +7927,9 @@
}
},
"node_modules/@storybook/core-events": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.4.1.tgz",
- "integrity": "sha512-F1tGb32XZ4FRfbtXdi4b+zdzWUjFz5rn3TF18mSuBGGXvxKU+4tywgjGQ3dKGdvuP754czn3poSdz2ZW08bLsQ==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.5.0.tgz",
+ "integrity": "sha512-FsD+clTzayqprbVllnL8LLch+uCslJFDgsv7Zh99/zoi7OHtHyauoCZkdLBSiDzgc84qS41dY19HqX1/y7cnOw==",
"dev": true,
"dependencies": {
"ts-dedent": "^2.0.0"
@@ -7693,28 +7940,28 @@
}
},
"node_modules/@storybook/core-server": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-7.4.1.tgz",
- "integrity": "sha512-8JJGci8eyNSfiHJ+Xr46Jv95fqQbjrd+ecQJvpyRqwN1LFdCM6QtHYmjt6LzuK16/by5jYXJ7+f8SA+gvW8SbQ==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-7.5.0.tgz",
+ "integrity": "sha512-7QT8uzwSJOsv9PASQ6ywepYkcEYFB7+S7Cj/0nFMh3Vl9vW96LXvEHLAo9CUhSxdEKWeTnD8DS5+j90dLhQFCA==",
"dev": true,
"dependencies": {
"@aw-web-design/x-default-browser": "1.4.126",
"@discoveryjs/json-ext": "^0.5.3",
- "@storybook/builder-manager": "7.4.1",
- "@storybook/channels": "7.4.1",
- "@storybook/core-common": "7.4.1",
- "@storybook/core-events": "7.4.1",
+ "@storybook/builder-manager": "7.5.0",
+ "@storybook/channels": "7.5.0",
+ "@storybook/core-common": "7.5.0",
+ "@storybook/core-events": "7.5.0",
"@storybook/csf": "^0.1.0",
- "@storybook/csf-tools": "7.4.1",
+ "@storybook/csf-tools": "7.5.0",
"@storybook/docs-mdx": "^0.1.0",
"@storybook/global": "^5.0.0",
- "@storybook/manager": "7.4.1",
- "@storybook/node-logger": "7.4.1",
- "@storybook/preview-api": "7.4.1",
- "@storybook/telemetry": "7.4.1",
- "@storybook/types": "7.4.1",
+ "@storybook/manager": "7.5.0",
+ "@storybook/node-logger": "7.5.0",
+ "@storybook/preview-api": "7.5.0",
+ "@storybook/telemetry": "7.5.0",
+ "@storybook/types": "7.5.0",
"@types/detect-port": "^1.3.0",
- "@types/node": "^16.0.0",
+ "@types/node": "^18.0.0",
"@types/pretty-hrtime": "^1.0.0",
"@types/semver": "^7.3.4",
"better-opn": "^3.0.2",
@@ -7732,7 +7979,6 @@
"prompts": "^2.4.0",
"read-pkg-up": "^7.0.1",
"semver": "^7.3.7",
- "serve-favicon": "^2.5.0",
"telejson": "^7.2.0",
"tiny-invariant": "^1.3.1",
"ts-dedent": "^2.0.0",
@@ -7747,9 +7993,9 @@
}
},
"node_modules/@storybook/core-server/node_modules/@types/node": {
- "version": "16.18.50",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.50.tgz",
- "integrity": "sha512-OiDU5xRgYTJ203v4cprTs0RwOCd5c5Zjv+K5P8KSqfiCsB1W3LcamTUMcnQarpq5kOYbhHfSOgIEJvdPyb5xyw==",
+ "version": "18.18.6",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.6.tgz",
+ "integrity": "sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==",
"dev": true
},
"node_modules/@storybook/core-server/node_modules/ansi-styles": {
@@ -7805,15 +8051,15 @@
}
},
"node_modules/@storybook/core-webpack": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-7.4.1.tgz",
- "integrity": "sha512-fXkOU3IRbXNWmd4o6lNqoNq5s/iE07Bp86P8scE6a3aU309L4lHaIqbxVQy7afvTYqz3X/xtcf0DsuXQi25wXA==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-7.5.0.tgz",
+ "integrity": "sha512-TI83kG5k2PIjOc+QAOHy0GxOjeLE/TQKFji/+40QJzS7h2+eJTRrO7q32Vo+IyXrkHYlwHk4KrF2LqgYQL8HaQ==",
"dev": true,
"dependencies": {
- "@storybook/core-common": "7.4.1",
- "@storybook/node-logger": "7.4.1",
- "@storybook/types": "7.4.1",
- "@types/node": "^16.0.0",
+ "@storybook/core-common": "7.5.0",
+ "@storybook/node-logger": "7.5.0",
+ "@storybook/types": "7.5.0",
+ "@types/node": "^18.0.0",
"ts-dedent": "^2.0.0"
},
"funding": {
@@ -7822,9 +8068,9 @@
}
},
"node_modules/@storybook/core-webpack/node_modules/@types/node": {
- "version": "16.18.50",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.50.tgz",
- "integrity": "sha512-OiDU5xRgYTJ203v4cprTs0RwOCd5c5Zjv+K5P8KSqfiCsB1W3LcamTUMcnQarpq5kOYbhHfSOgIEJvdPyb5xyw==",
+ "version": "18.18.6",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.6.tgz",
+ "integrity": "sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==",
"dev": true
},
"node_modules/@storybook/csf": {
@@ -7837,12 +8083,12 @@
}
},
"node_modules/@storybook/csf-plugin": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-7.4.1.tgz",
- "integrity": "sha512-TnvDS2szwwzoqn3WbnB57w1Q+rZ+EFFwpLdjvocsiosLQglMQdPNhDvl1U5uDgwTzVhs4MEiEHJ1LxTkeizxhA==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-7.5.0.tgz",
+ "integrity": "sha512-kghaEFYvQISdAjQddeicSuvBFMeuuLNtpmMkuoLQzULF7e/Tws6zLCYsjGevqlnqXD0iW2XM/j9q4M5L/mWc5A==",
"dev": true,
"dependencies": {
- "@storybook/csf-tools": "7.4.1",
+ "@storybook/csf-tools": "7.5.0",
"unplugin": "^1.3.1"
},
"funding": {
@@ -7851,9 +8097,9 @@
}
},
"node_modules/@storybook/csf-tools": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-7.4.1.tgz",
- "integrity": "sha512-mzzsAtB9CYSgxCvZJ4xQrC7QIhMR5MXGBohADiNhnuRXLdZ6wXBhWkRi/sY7Wh5Uh8DdgHkGPJHJxcyYG+FYQw==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-7.5.0.tgz",
+ "integrity": "sha512-KOHbFNSwwc7KTdNz/6yO7S2pxbr7sH6nqfolS6/l+pod45WvRH3VhyqlDIIeX7ESIhfCw87ExC96hNDL3TojCw==",
"dev": true,
"dependencies": {
"@babel/generator": "^7.22.9",
@@ -7861,7 +8107,7 @@
"@babel/traverse": "^7.22.8",
"@babel/types": "^7.22.5",
"@storybook/csf": "^0.1.0",
- "@storybook/types": "7.4.1",
+ "@storybook/types": "7.5.0",
"fs-extra": "^11.1.0",
"recast": "^0.23.1",
"ts-dedent": "^2.0.0"
@@ -7878,14 +8124,14 @@
"dev": true
},
"node_modules/@storybook/docs-tools": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/docs-tools/-/docs-tools-7.4.1.tgz",
- "integrity": "sha512-4PRsib2hDQjGhT2CnnPgzNZ5pVrpQ6wtb5l0TG4lDDc0F9Tal0EbrooXWwMsc7SxYslHKIEgxd+Nll66FWILFw==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/docs-tools/-/docs-tools-7.5.0.tgz",
+ "integrity": "sha512-NFhqbXj6Wv5YypMwDkt0z9xcfWD7M3wZhr8Z9XcXDlUUPjBrdv0cHt3rfHwEXpTfFyunbK41KQZZ3JkjiAjgTg==",
"dev": true,
"dependencies": {
- "@storybook/core-common": "7.4.1",
- "@storybook/preview-api": "7.4.1",
- "@storybook/types": "7.4.1",
+ "@storybook/core-common": "7.5.0",
+ "@storybook/preview-api": "7.5.0",
+ "@storybook/types": "7.5.0",
"@types/doctrine": "^0.0.3",
"doctrine": "^3.0.0",
"lodash": "^4.17.21"
@@ -7902,9 +8148,9 @@
"dev": true
},
"node_modules/@storybook/manager": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/manager/-/manager-7.4.1.tgz",
- "integrity": "sha512-LaORUHqfinhKk6Ysz7LyBYqblr/Oj+H5jXeMidSWYor+cJ6AZp1BtCUwWAqtjBliZ8vfASxME1CCImENG11eSA==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/manager/-/manager-7.5.0.tgz",
+ "integrity": "sha512-M4h4b0Y4aZ1sRGaZuJXgvPZHqu7vN/wgWB5yPcSwJqH1+DlPxYXYnPKGERgaEUUVKJV3oWQD2qZ+UpDeTgI5UQ==",
"dev": true,
"funding": {
"type": "opencollective",
@@ -7912,19 +8158,19 @@
}
},
"node_modules/@storybook/manager-api": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-7.4.1.tgz",
- "integrity": "sha512-nzYasETW20uDWpfST6JFf6c/GSFB/dj7xVtg5EpvAYF8GkErCk9TvNKdLNroRrIYm5VJxHWC2V+CJ07RuX3Glw==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-7.5.0.tgz",
+ "integrity": "sha512-n9EaJTThsuFiBDs+GcmNBHnvLhH0znJQprhIQqHNVnosCs/7sloYUzWZzZvPwfnfPvRR7ostEEMXvriaYXYdJQ==",
"dev": true,
"dependencies": {
- "@storybook/channels": "7.4.1",
- "@storybook/client-logger": "7.4.1",
- "@storybook/core-events": "7.4.1",
+ "@storybook/channels": "7.5.0",
+ "@storybook/client-logger": "7.5.0",
+ "@storybook/core-events": "7.5.0",
"@storybook/csf": "^0.1.0",
"@storybook/global": "^5.0.0",
- "@storybook/router": "7.4.1",
- "@storybook/theming": "7.4.1",
- "@storybook/types": "7.4.1",
+ "@storybook/router": "7.5.0",
+ "@storybook/theming": "7.5.0",
+ "@storybook/types": "7.5.0",
"dequal": "^2.0.2",
"lodash": "^4.17.21",
"memoizerific": "^1.11.3",
@@ -7949,9 +8195,9 @@
"dev": true
},
"node_modules/@storybook/node-logger": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.4.1.tgz",
- "integrity": "sha512-P7rR/WoHCR2zdDo8bDowIBlB3wRrVNHHIfyWxubbzj/AA2uPv7cpdjDA+NDHAIq8MkuxZqfqhatjrHLFwMHDBg==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.5.0.tgz",
+ "integrity": "sha512-Og3hdB1bjpVCXhmlhvpgVxUfCQGd0DCguXf5qhn2kX4a+D++dxJ8YqzVJ5JQCacI9bCKITV6W9JSGseWcBaXBg==",
"dev": true,
"funding": {
"type": "opencollective",
@@ -7959,9 +8205,9 @@
}
},
"node_modules/@storybook/postinstall": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-7.4.1.tgz",
- "integrity": "sha512-nzSAS2kKhYFdeQHOb+mwk6LCiSBx8vigiRActRWMpoUSntlrLFdYKXoYfPQtUQcE7cHDLv5hutD31Kcl7pIazw==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-7.5.0.tgz",
+ "integrity": "sha512-SHpBItwar7qDZO7BBSqTNQK0yNy+RUROZUhW6wlVvsgVhIGF1bgA4pgpW1iMyfPmmGyNekE1BJjN+v8rjq9s6A==",
"dev": true,
"funding": {
"type": "opencollective",
@@ -7969,9 +8215,9 @@
}
},
"node_modules/@storybook/preview": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/preview/-/preview-7.4.1.tgz",
- "integrity": "sha512-KqHbS5jVKSvFESrwU3iLJE5ciIJicdV3ZducL9t+hNJOdchzV3ezEwMn6gApEin3dm3Ts7InN+W7nBc+MzaXmA==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/preview/-/preview-7.5.0.tgz",
+ "integrity": "sha512-KPhx43pRgIb6UhqjsF0sUG5c3GG2dwzTzjN1/sj0QbPMghZ3b7xKGrCu6VSlsXoWQtcwisMHETFnowk0Ba/AMg==",
"dev": true,
"funding": {
"type": "opencollective",
@@ -7979,17 +8225,17 @@
}
},
"node_modules/@storybook/preview-api": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.4.1.tgz",
- "integrity": "sha512-swmosWK73lP0CXDKMOwYIaaId28+muPDYX2V/0JmIOA+45HFXimeXZs3XsgVgQMutVF51QqnDA0pfrNgRofHgQ==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.5.0.tgz",
+ "integrity": "sha512-+DubgKwYFk532FKDB6sEGaG47wr0t137aIQSjbNwVmXXxj0QY0zIAThtERx7w6eHS7ZjOs6xlLEZhzC4FI525g==",
"dev": true,
"dependencies": {
- "@storybook/channels": "7.4.1",
- "@storybook/client-logger": "7.4.1",
- "@storybook/core-events": "7.4.1",
+ "@storybook/channels": "7.5.0",
+ "@storybook/client-logger": "7.5.0",
+ "@storybook/core-events": "7.5.0",
"@storybook/csf": "^0.1.0",
"@storybook/global": "^5.0.0",
- "@storybook/types": "7.4.1",
+ "@storybook/types": "7.5.0",
"@types/qs": "^6.9.5",
"dequal": "^2.0.2",
"lodash": "^4.17.21",
@@ -8005,9 +8251,9 @@
}
},
"node_modules/@storybook/react-dom-shim": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-7.4.1.tgz",
- "integrity": "sha512-LUxmXyAFZB61kFWtZZA5WCHgFfUI5Jtn0d2HVOfpIYK1OcGwW8K4ya0lbMVrYvMgL37e5ShPurjj32U2YBeiJA==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-7.5.0.tgz",
+ "integrity": "sha512-OzJhXg1En/9D9vKvD2t0EcYcuHFzrLTA9kEUWt/eP3Ww41kndfJoZca33JZr17iuKksVAZ8ucETMnkL3yO+ybA==",
"dev": true,
"funding": {
"type": "opencollective",
@@ -8019,12 +8265,12 @@
}
},
"node_modules/@storybook/router": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/router/-/router-7.4.1.tgz",
- "integrity": "sha512-7tE1B18jb+5+ujXd3BHcub85QnytIVBNA0iAo+o8MNwArISyodqp12y2D3w+QpXkg0GtPhAp/CMhzpyxotPhRQ==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/router/-/router-7.5.0.tgz",
+ "integrity": "sha512-NzPwjndmOEOUL8jK5kUrSvRUIcN5Z+h+l0Z8g4I56RoEhNTcKeOW4jbcT4WKnR9H455dti8HAcTV/4x59GpgxQ==",
"dev": true,
"dependencies": {
- "@storybook/client-logger": "7.4.1",
+ "@storybook/client-logger": "7.5.0",
"memoizerific": "^1.11.3",
"qs": "^6.10.0"
},
@@ -8037,29 +8283,15 @@
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
- "node_modules/@storybook/store": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/store/-/store-7.4.1.tgz",
- "integrity": "sha512-Z132AFO+mgc4W09zBmYBSY1w3q/bjYsf93dD29gyRP3i5+LrXmS3cFMkg0+buDTXarM+AoyEJ6vnia4MAYL+6A==",
- "dev": true,
- "dependencies": {
- "@storybook/client-logger": "7.4.1",
- "@storybook/preview-api": "7.4.1"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/storybook"
- }
- },
"node_modules/@storybook/telemetry": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/telemetry/-/telemetry-7.4.1.tgz",
- "integrity": "sha512-53eQPm22Fa7qzjXFSE++bJv5qNG/89rRLU5xywuSYmjQgtaS6HKLPjIRtNPPbU50gRvklVedDDxD8UqN73mD3w==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/telemetry/-/telemetry-7.5.0.tgz",
+ "integrity": "sha512-dvc1cjxHYGNfLEvh8eQI/R2KtMft0kUs6TJ2uXZdIX4+WqWG6mfn75sP8eyC1tcjkdslS6AmFWTfgt9EVcIPQA==",
"dev": true,
"dependencies": {
- "@storybook/client-logger": "7.4.1",
- "@storybook/core-common": "7.4.1",
- "@storybook/csf-tools": "7.4.1",
+ "@storybook/client-logger": "7.5.0",
+ "@storybook/core-common": "7.5.0",
+ "@storybook/csf-tools": "7.5.0",
"chalk": "^4.1.0",
"detect-package-manager": "^2.0.1",
"fetch-retry": "^5.0.2",
@@ -8124,24 +8356,24 @@
}
},
"node_modules/@storybook/testing-library": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/@storybook/testing-library/-/testing-library-0.2.0.tgz",
- "integrity": "sha512-Ff6jNnrsosmDshgCf0Eb5Cz7IA34p/1Ps5N3Kp3598kfXpBSccSkQQvVFUXC3kIHw/isIXWPqntZuKqnWUz7Gw==",
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@storybook/testing-library/-/testing-library-0.2.2.tgz",
+ "integrity": "sha512-L8sXFJUHmrlyU2BsWWZGuAjv39Jl1uAqUHdxmN42JY15M4+XCMjGlArdCCjDe1wpTSW6USYISA9axjZojgtvnw==",
"dev": true,
"dependencies": {
"@testing-library/dom": "^9.0.0",
- "@testing-library/user-event": "^14.0.0",
+ "@testing-library/user-event": "^14.4.0",
"ts-dedent": "^2.2.0"
}
},
"node_modules/@storybook/theming": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-7.4.1.tgz",
- "integrity": "sha512-a4QajZbnYumq8ovtn7nW7BeNrk/TaWyKmUrIz4w08I6ghzESJA4aCWZ6394awbrruiIOzCCKOUq4mfWEsc8W6A==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-7.5.0.tgz",
+ "integrity": "sha512-uTo97oh+pvmlfsZocFq5qae0zGo0VGk7oiBqNSSw6CiTqE1rIuSxoPrMAY+oCTWCUZV7DjONIGvpnGl2QALsAw==",
"dev": true,
"dependencies": {
"@emotion/use-insertion-effect-with-fallbacks": "^1.0.0",
- "@storybook/client-logger": "7.4.1",
+ "@storybook/client-logger": "7.5.0",
"@storybook/global": "^5.0.0",
"memoizerific": "^1.11.3"
},
@@ -8155,12 +8387,12 @@
}
},
"node_modules/@storybook/types": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.4.1.tgz",
- "integrity": "sha512-bjt1YDG9AocFBhIFRvGGbYZPlD223p+qAFcFgYdezU16fFE4ZGFUzUuq2ERkOofL7a2+OzLTCQ/SKe1jFkXCxQ==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.5.0.tgz",
+ "integrity": "sha512-fiOUnHKFi/UZSfvc53F0WEQCiquqcSqslL3f5EffwQRiXfeXlGavJb0kU03BO+CvOXcliRn6qKSF2dL0Rgb7Xw==",
"dev": true,
"dependencies": {
- "@storybook/channels": "7.4.1",
+ "@storybook/channels": "7.5.0",
"@types/babel__core": "^7.0.0",
"@types/express": "^4.7.0",
"file-system-cache": "2.3.0"
@@ -8171,13 +8403,14 @@
}
},
"node_modules/@swc/core": {
- "version": "1.3.84",
- "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.84.tgz",
- "integrity": "sha512-UPKUiDwG7HOdPfOb1VFeEJ76JDgU2w80JLewzx6tb0fk9TIjhr9yxKBzPbzc/QpjGHDu5iaEuNeZcu27u4j63g==",
+ "version": "1.3.93",
+ "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.93.tgz",
+ "integrity": "sha512-690GRr1wUGmGYZHk7fUduX/JUwViMF2o74mnZYIWEcJaCcd9MQfkhsxPBtjeg6tF+h266/Cf3RPYhsFBzzxXcA==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
- "@swc/types": "^0.1.4"
+ "@swc/counter": "^0.1.1",
+ "@swc/types": "^0.1.5"
},
"engines": {
"node": ">=10"
@@ -8187,16 +8420,16 @@
"url": "https://opencollective.com/swc"
},
"optionalDependencies": {
- "@swc/core-darwin-arm64": "1.3.84",
- "@swc/core-darwin-x64": "1.3.84",
- "@swc/core-linux-arm-gnueabihf": "1.3.84",
- "@swc/core-linux-arm64-gnu": "1.3.84",
- "@swc/core-linux-arm64-musl": "1.3.84",
- "@swc/core-linux-x64-gnu": "1.3.84",
- "@swc/core-linux-x64-musl": "1.3.84",
- "@swc/core-win32-arm64-msvc": "1.3.84",
- "@swc/core-win32-ia32-msvc": "1.3.84",
- "@swc/core-win32-x64-msvc": "1.3.84"
+ "@swc/core-darwin-arm64": "1.3.93",
+ "@swc/core-darwin-x64": "1.3.93",
+ "@swc/core-linux-arm-gnueabihf": "1.3.93",
+ "@swc/core-linux-arm64-gnu": "1.3.93",
+ "@swc/core-linux-arm64-musl": "1.3.93",
+ "@swc/core-linux-x64-gnu": "1.3.93",
+ "@swc/core-linux-x64-musl": "1.3.93",
+ "@swc/core-win32-arm64-msvc": "1.3.93",
+ "@swc/core-win32-ia32-msvc": "1.3.93",
+ "@swc/core-win32-x64-msvc": "1.3.93"
},
"peerDependencies": {
"@swc/helpers": "^0.5.0"
@@ -8208,9 +8441,9 @@
}
},
"node_modules/@swc/core-darwin-arm64": {
- "version": "1.3.84",
- "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.84.tgz",
- "integrity": "sha512-mqK0buOo+toF2HoJ/gWj2ApZbvbIiNq3mMwSTHCYJHlQFQfoTWnl9aaD5GSO4wfNFVYfEZ1R259o5uv5NlVtoA==",
+ "version": "1.3.93",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.93.tgz",
+ "integrity": "sha512-gEKgk7FVIgltnIfDO6GntyuQBBlAYg5imHpRgLxB1zSI27ijVVkksc6QwISzFZAhKYaBWIsFSVeL9AYSziAF7A==",
"cpu": [
"arm64"
],
@@ -8224,9 +8457,9 @@
}
},
"node_modules/@swc/core-darwin-x64": {
- "version": "1.3.84",
- "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.84.tgz",
- "integrity": "sha512-cyuQZz62C43EDZqtnptUTlfDvAjgG3qu139m5zsfIK6ltXA5inKFbDWV3a/M5c18dFzA2Xh21Q46XZezmtQ9Tg==",
+ "version": "1.3.93",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.93.tgz",
+ "integrity": "sha512-ZQPxm/fXdDQtn3yrYSL/gFfA8OfZ5jTi33yFQq6vcg/Y8talpZ+MgdSlYM0FkLrZdMTYYTNFiuBQuuvkA+av+Q==",
"cpu": [
"x64"
],
@@ -8240,9 +8473,9 @@
}
},
"node_modules/@swc/core-linux-arm-gnueabihf": {
- "version": "1.3.84",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.84.tgz",
- "integrity": "sha512-dmt/ECQrp3ZPWnK27p4E4xRIRHOoJhgGvxC5t5YaWzN20KcxE9ykEY2oLGSoeceM/A+4D11aRYGwF/EM7yOkvA==",
+ "version": "1.3.93",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.93.tgz",
+ "integrity": "sha512-OYFMMI2yV+aNe3wMgYhODxHdqUB/jrK0SEMHHS44GZpk8MuBXEF+Mcz4qjkY5Q1EH7KVQqXb/gVWwdgTHpjM2A==",
"cpu": [
"arm"
],
@@ -8256,9 +8489,9 @@
}
},
"node_modules/@swc/core-linux-arm64-gnu": {
- "version": "1.3.84",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.84.tgz",
- "integrity": "sha512-PgVfrI3NVg2z/oeg3GWLb9rFLMqidbdPwVH5nRyHVP2RX/BWP6qfnYfG+gJv4qrKzIldb9TyCGH7y8VWctKLxw==",
+ "version": "1.3.93",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.93.tgz",
+ "integrity": "sha512-BT4dT78odKnJMNiq5HdjBsv29CiIdcCcImAPxeFqAeFw1LL6gh9nzI8E96oWc+0lVT5lfhoesCk4Qm7J6bty8w==",
"cpu": [
"arm64"
],
@@ -8272,9 +8505,9 @@
}
},
"node_modules/@swc/core-linux-arm64-musl": {
- "version": "1.3.84",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.84.tgz",
- "integrity": "sha512-hcuEa8/vin4Ns0P+FpcDHQ4f3jmhgGKQhqw0w+TovPSVTIXr+nrFQ2AGhs9nAxS6tSQ77C53Eb5YRpK8ToFo1A==",
+ "version": "1.3.93",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.93.tgz",
+ "integrity": "sha512-yH5fWEl1bktouC0mhh0Chuxp7HEO4uCtS/ly1Vmf18gs6wZ8DOOkgAEVv2dNKIryy+Na++ljx4Ym7C8tSJTrLw==",
"cpu": [
"arm64"
],
@@ -8288,9 +8521,9 @@
}
},
"node_modules/@swc/core-linux-x64-gnu": {
- "version": "1.3.84",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.84.tgz",
- "integrity": "sha512-IvyimSbwGdu21jBBEqR1Up8Jhvl8kIAf1k3e5Oy8oRfgojdUfmW1EIwgGdoUeyQ1VHlfquiWaRGfsnHQUKl35g==",
+ "version": "1.3.93",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.93.tgz",
+ "integrity": "sha512-OFUdx64qvrGJhXKEyxosHxgoUVgba2ztYh7BnMiU5hP8lbI8G13W40J0SN3CmFQwPP30+3oEbW7LWzhKEaYjlg==",
"cpu": [
"x64"
],
@@ -8304,9 +8537,9 @@
}
},
"node_modules/@swc/core-linux-x64-musl": {
- "version": "1.3.84",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.84.tgz",
- "integrity": "sha512-hdgVU/O5ufDCe+p5RtCjU7PRNwd0WM+eWJS+GNY4QWL6O8y2VLM+i4+6YzwSUjeBk0xd+1YElMxbqz7r5tSZhw==",
+ "version": "1.3.93",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.93.tgz",
+ "integrity": "sha512-4B8lSRwEq1XYm6xhxHhvHmKAS7pUp1Q7E33NQ2TlmFhfKvCOh86qvThcjAOo57x8DRwmpvEVrqvpXtYagMN6Ig==",
"cpu": [
"x64"
],
@@ -8320,9 +8553,9 @@
}
},
"node_modules/@swc/core-win32-arm64-msvc": {
- "version": "1.3.84",
- "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.84.tgz",
- "integrity": "sha512-rzH6k2BF0BFOFhUTD+bh0oCiUCZjFfDfoZoYNN/CM0qbtjAcFH21hzMh/EH8ZaXq8k/iQmUNNa5MPNPZ4SOMNw==",
+ "version": "1.3.93",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.93.tgz",
+ "integrity": "sha512-BHShlxtkven8ZjjvZ5QR6sC5fZCJ9bMujEkiha6W4cBUTY7ce7qGFyHmQd+iPC85d9kD/0cCiX/Xez8u0BhO7w==",
"cpu": [
"arm64"
],
@@ -8336,9 +8569,9 @@
}
},
"node_modules/@swc/core-win32-ia32-msvc": {
- "version": "1.3.84",
- "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.84.tgz",
- "integrity": "sha512-Y+Dk7VLLVwwsAzoDmjkNW/sTmSPl9PGr4Mj1nhc5A2NNxZ+hz4SxFMclacDI03SC5ikK8Qh6WOoE/+nwUDa3uA==",
+ "version": "1.3.93",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.93.tgz",
+ "integrity": "sha512-nEwNWnz4JzYAK6asVvb92yeylfxMYih7eMQOnT7ZVlZN5ba9WF29xJ6kcQKs9HRH6MvWhz9+wRgv3FcjlU6HYA==",
"cpu": [
"ia32"
],
@@ -8352,9 +8585,9 @@
}
},
"node_modules/@swc/core-win32-x64-msvc": {
- "version": "1.3.84",
- "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.84.tgz",
- "integrity": "sha512-WmpaosqCWMX7DArLdU8AJcj96hy0PKlYh1DaMVikSrrDHbJm2dZ8rd27IK3qUB8DgPkrDYHmLAKNZ+z3gWXgRQ==",
+ "version": "1.3.93",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.93.tgz",
+ "integrity": "sha512-jibQ0zUr4kwJaQVwgmH+svS04bYTPnPw/ZkNInzxS+wFAtzINBYcU8s2PMWbDb2NGYiRSEeoSGyAvS9H+24JFA==",
"cpu": [
"x64"
],
@@ -8367,16 +8600,22 @@
"node": ">=10"
}
},
+ "node_modules/@swc/counter": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.2.tgz",
+ "integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==",
+ "dev": true
+ },
"node_modules/@swc/types": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.4.tgz",
- "integrity": "sha512-z/G02d+59gyyUb7KYhKi9jOhicek6QD2oMaotUyG+lUkybpXoV49dY9bj7Ah5Q+y7knK2jU67UTX9FyfGzaxQg==",
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz",
+ "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==",
"dev": true
},
"node_modules/@testing-library/dom": {
- "version": "9.3.1",
- "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.1.tgz",
- "integrity": "sha512-0DGPd9AR3+iDTjGoMpxIkAsUihHZ3Ai6CneU6bRRrffXMgzCdlNk43jTrD2/5LT6CBb3MWTP8v510JzYtahD2w==",
+ "version": "9.3.3",
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.3.tgz",
+ "integrity": "sha512-fB0R+fa3AUqbLHWyxXa2kGVtf1Fe1ZZFr0Zp6AIbIAzXb2mKbEXl+PCQNUOaq5lbTab5tfctfXRNsWXxa2f7Aw==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.10.4",
@@ -8432,6 +8671,35 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
+ "node_modules/@testing-library/dom/node_modules/deep-equal": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz",
+ "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==",
+ "dev": true,
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.0",
+ "call-bind": "^1.0.2",
+ "es-get-iterator": "^1.1.3",
+ "get-intrinsic": "^1.2.1",
+ "is-arguments": "^1.1.1",
+ "is-array-buffer": "^3.0.2",
+ "is-date-object": "^1.0.5",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "isarray": "^2.0.5",
+ "object-is": "^1.1.5",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.5.0",
+ "side-channel": "^1.0.4",
+ "which-boxed-primitive": "^1.0.2",
+ "which-collection": "^1.0.1",
+ "which-typed-array": "^1.1.9"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/@testing-library/dom/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -8454,9 +8722,9 @@
}
},
"node_modules/@testing-library/user-event": {
- "version": "14.4.3",
- "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.4.3.tgz",
- "integrity": "sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q==",
+ "version": "14.5.1",
+ "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.1.tgz",
+ "integrity": "sha512-UCcUKrUYGj7ClomOo2SpNVvx4/fkd/2BbIHDCle8A0ax+P3bU7yJwDBDrS6ZwdTMARWTGODX1hEsCcO+7beJjg==",
"dev": true,
"engines": {
"node": ">=12",
@@ -8476,9 +8744,9 @@
}
},
"node_modules/@ts-morph/common": {
- "version": "0.19.0",
- "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.19.0.tgz",
- "integrity": "sha512-Unz/WHmd4pGax91rdIKWi51wnVUW11QttMEPpBiBgIewnc9UQIX7UDLxr5vRlqeByXCwhkF6VabSsI0raWcyAQ==",
+ "version": "0.21.0",
+ "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.21.0.tgz",
+ "integrity": "sha512-ES110Mmne5Vi4ypUKrtVQfXFDtCsDXiUiGxF6ILVlE90dDD4fdpC1LSjydl/ml7xJWKSDZwUYD2zkOePMSrPBA==",
"dev": true,
"dependencies": {
"fast-glob": "^3.2.12",
@@ -8597,15 +8865,15 @@
}
},
"node_modules/@types/aria-query": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz",
- "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==",
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.3.tgz",
+ "integrity": "sha512-0Z6Tr7wjKJIk4OUEjVUQMtyunLDy339vcMaj38Kpj6jM2OE1p3S4kXExKZ7a3uXQAPCoy3sbrP1wibDKaf39oA==",
"dev": true
},
"node_modules/@types/babel__core": {
- "version": "7.20.1",
- "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz",
- "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==",
+ "version": "7.20.3",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.3.tgz",
+ "integrity": "sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==",
"dev": true,
"dependencies": {
"@babel/parser": "^7.20.7",
@@ -8616,18 +8884,18 @@
}
},
"node_modules/@types/babel__generator": {
- "version": "7.6.4",
- "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz",
- "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==",
+ "version": "7.6.6",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.6.tgz",
+ "integrity": "sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==",
"dev": true,
"dependencies": {
"@babel/types": "^7.0.0"
}
},
"node_modules/@types/babel__template": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz",
- "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==",
+ "version": "7.4.3",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.3.tgz",
+ "integrity": "sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==",
"dev": true,
"dependencies": {
"@babel/parser": "^7.1.0",
@@ -8635,18 +8903,18 @@
}
},
"node_modules/@types/babel__traverse": {
- "version": "7.20.1",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz",
- "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==",
+ "version": "7.20.3",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.3.tgz",
+ "integrity": "sha512-Lsh766rGEFbaxMIDH7Qa+Yha8cMVI3qAK6CHt3OR0YfxOIn5Z54iHiyDRycHrBqeIiqGa20Kpsv1cavfBKkRSw==",
"dev": true,
"dependencies": {
"@babel/types": "^7.20.7"
}
},
"node_modules/@types/body-parser": {
- "version": "1.19.2",
- "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
- "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==",
+ "version": "1.19.4",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.4.tgz",
+ "integrity": "sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==",
"dev": true,
"dependencies": {
"@types/connect": "*",
@@ -8654,27 +8922,27 @@
}
},
"node_modules/@types/bonjour": {
- "version": "3.5.10",
- "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz",
- "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==",
+ "version": "3.5.12",
+ "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.12.tgz",
+ "integrity": "sha512-ky0kWSqXVxSqgqJvPIkgFkcn4C8MnRog308Ou8xBBIVo39OmUFy+jqNe0nPwLCDFxUpmT9EvT91YzOJgkDRcFg==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/connect": {
- "version": "3.4.36",
- "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz",
- "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==",
+ "version": "3.4.37",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz",
+ "integrity": "sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/connect-history-api-fallback": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.1.tgz",
- "integrity": "sha512-iaQslNbARe8fctL5Lk+DsmgWOM83lM+7FzP0eQUJs1jd3kBE8NWqBTIT2S8SqQOJjxvt2eyIjpOuYeRXq2AdMw==",
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.2.tgz",
+ "integrity": "sha512-gX2j9x+NzSh4zOhnRPSdPPmTepS4DfxES0AvIFv3jGv5QyeAJf6u6dY5/BAoAJU9Qq1uTvwOku8SSC2GnCRl6Q==",
"dev": true,
"dependencies": {
"@types/express-serve-static-core": "*",
@@ -8688,36 +8956,36 @@
"dev": true
},
"node_modules/@types/cors": {
- "version": "2.8.14",
- "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.14.tgz",
- "integrity": "sha512-RXHUvNWYICtbP6s18PnOCaqToK8y14DnLd75c6HfyKf228dxy7pHNOQkxPtvXKp/hINFMDjbYzsj63nnpPMSRQ==",
+ "version": "2.8.15",
+ "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.15.tgz",
+ "integrity": "sha512-n91JxbNLD8eQIuXDIChAN1tCKNWCEgpceU9b7ZMbFA+P+Q4yIeh80jizFLEvolRPc1ES0VdwFlGv+kJTSirogw==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/cross-spawn": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.3.tgz",
- "integrity": "sha512-BDAkU7WHHRHnvBf5z89lcvACsvkz/n7Tv+HyD/uW76O29HoH1Tk/W6iQrepaZVbisvlEek4ygwT8IW7ow9XLAA==",
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.4.tgz",
+ "integrity": "sha512-GGLpeThc2Bu8FBGmVn76ZU3lix17qZensEI4/MPty0aZpm2CHfgEMis31pf5X5EiudYKcPAsWciAsCALoPo5dw==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/debug": {
- "version": "4.1.8",
- "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz",
- "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==",
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.10.tgz",
+ "integrity": "sha512-tOSCru6s732pofZ+sMv9o4o3Zc+Sa8l3bxd/tweTQudFn06vAzb13ZX46Zi6m6EJ+RUbRTHvgQJ1gBtSgkaUYA==",
"dev": true,
"dependencies": {
"@types/ms": "*"
}
},
"node_modules/@types/detect-port": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/@types/detect-port/-/detect-port-1.3.3.tgz",
- "integrity": "sha512-bV/jQlAJ/nPY3XqSatkGpu+nGzou+uSwrH1cROhn+jBFg47yaNH+blW4C7p9KhopC7QxCv/6M86s37k8dMk0Yg==",
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@types/detect-port/-/detect-port-1.3.4.tgz",
+ "integrity": "sha512-HveFGabu3IwATqwLelcp6UZ1MIzSFwk+qswC9luzzHufqAwhs22l7KkINDLWRfXxIPTYnSZ1DuQBEgeVPgUOSA==",
"dev": true
},
"node_modules/@types/doctrine": {
@@ -8727,44 +8995,44 @@
"dev": true
},
"node_modules/@types/ejs": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.2.tgz",
- "integrity": "sha512-ZmiaE3wglXVWBM9fyVC17aGPkLo/UgaOjEiI2FXQfyczrCefORPxIe+2dVmnmk3zkVIbizjrlQzmPGhSYGXG5g==",
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.4.tgz",
+ "integrity": "sha512-fnM/NjByiWdSRJRrmGxgqOSAnmOnsvX1QcNYk5TVyIIj+7ZqOKMb9gQa4OIl/lil2w/8TiTWV+nz3q8yqxez/w==",
"dev": true
},
"node_modules/@types/emscripten": {
- "version": "1.39.7",
- "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.7.tgz",
- "integrity": "sha512-tLqYV94vuqDrXh515F/FOGtBcRMTPGvVV1LzLbtYDcQmmhtpf/gLYf+hikBbQk8MzOHNz37wpFfJbYAuSn8HqA==",
+ "version": "1.39.9",
+ "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.9.tgz",
+ "integrity": "sha512-ILdWj4XYtNOqxJaW22NEQx2gJsLfV5ncxYhhGX1a1H1lXl2Ta0gUz7QOnOoF1xQbJwWDjImi8gXN9mKdIf6n9g==",
"dev": true
},
"node_modules/@types/eslint": {
- "version": "8.44.2",
- "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.2.tgz",
- "integrity": "sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg==",
+ "version": "8.44.5",
+ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.5.tgz",
+ "integrity": "sha512-Ol2eio8LtD/tGM4Ga7Jb83NuFwEv3NqvssSlifXL9xuFpSyQZw0ecmm2Kux6iU0KxQmp95hlPmGCzGJ0TCFeRA==",
"dependencies": {
"@types/estree": "*",
"@types/json-schema": "*"
}
},
"node_modules/@types/eslint-scope": {
- "version": "3.7.4",
- "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz",
- "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==",
+ "version": "3.7.6",
+ "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.6.tgz",
+ "integrity": "sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==",
"dependencies": {
"@types/eslint": "*",
"@types/estree": "*"
}
},
"node_modules/@types/estree": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz",
- "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA=="
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz",
+ "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ=="
},
"node_modules/@types/express": {
- "version": "4.17.17",
- "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz",
- "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==",
+ "version": "4.17.20",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.20.tgz",
+ "integrity": "sha512-rOaqlkgEvOW495xErXMsmyX3WKBInbhG5eqojXYi3cGUaLoRDlXa5d52fkfWZT963AZ3v2eZ4MbKE6WpDAGVsw==",
"dev": true,
"dependencies": {
"@types/body-parser": "*",
@@ -8774,9 +9042,9 @@
}
},
"node_modules/@types/express-serve-static-core": {
- "version": "4.17.36",
- "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.36.tgz",
- "integrity": "sha512-zbivROJ0ZqLAtMzgzIUC4oNqDG9iF0lSsAqpOD9kbs5xcIM3dTiyuHvBc7R8MtWBp3AAWGaovJa+wzWPjLYW7Q==",
+ "version": "4.17.38",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.38.tgz",
+ "integrity": "sha512-hXOtc0tuDHZPFwwhuBJXPbjemWtXnJjbvuuyNH2Y5Z6in+iXc63c4eXYDc7GGGqHy+iwYqAJMdaItqdnbcBKmg==",
"dev": true,
"dependencies": {
"@types/node": "*",
@@ -8792,24 +9060,24 @@
"dev": true
},
"node_modules/@types/geojson": {
- "version": "7946.0.10",
- "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz",
- "integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==",
+ "version": "7946.0.12",
+ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.12.tgz",
+ "integrity": "sha512-uK2z1ZHJyC0nQRbuovXFt4mzXDwf27vQeUWNhfKGwRcWW429GOhP8HxUHlM6TLH4bzmlv/HlEjpvJh3JfmGsAA==",
"dev": true
},
"node_modules/@types/graceful-fs": {
- "version": "4.1.6",
- "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz",
- "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==",
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.8.tgz",
+ "integrity": "sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/hammerjs": {
- "version": "2.0.41",
- "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.41.tgz",
- "integrity": "sha512-ewXv/ceBaJprikMcxCmWU1FKyMAQ2X7a9Gtmzw8fcg2kIePI1crERDM818W+XYrxqdBBOdlf2rm137bU+BltCA==",
+ "version": "2.0.43",
+ "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.43.tgz",
+ "integrity": "sha512-wqxfwHk83RS7+6OpytGdo5wqkqtvx+bGaIs1Rwm5NrtQHUfL4OgWs/5p0OipmjmT+fexePh37Ek+mqIpdNjQKA==",
"dev": true
},
"node_modules/@types/html-minifier-terser": {
@@ -8819,130 +9087,133 @@
"dev": true
},
"node_modules/@types/http-errors": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz",
- "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.3.tgz",
+ "integrity": "sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA==",
"dev": true
},
"node_modules/@types/http-proxy": {
- "version": "1.17.11",
- "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.11.tgz",
- "integrity": "sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==",
+ "version": "1.17.13",
+ "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.13.tgz",
+ "integrity": "sha512-GkhdWcMNiR5QSQRYnJ+/oXzu0+7JJEPC8vkWXK351BkhjraZF+1W13CUYARUvX9+NqIU2n6YHA4iwywsc/M6Sw==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/istanbul-lib-coverage": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
- "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==",
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+ "integrity": "sha512-zONci81DZYCZjiLe0r6equvZut0b+dBRPBN5kBDjsONnutYNtJMoWQ9uR2RkL1gLG9NMTzvf+29e5RFfPbeKhQ==",
"dev": true
},
"node_modules/@types/istanbul-lib-report": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
- "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.2.tgz",
+ "integrity": "sha512-8toY6FgdltSdONav1XtUHl4LN1yTmLza+EuDazb/fEmRNCwjyqNVIQWs2IfC74IqjHkREs/nQ2FWq5kZU9IC0w==",
"dev": true,
"dependencies": {
"@types/istanbul-lib-coverage": "*"
}
},
"node_modules/@types/istanbul-reports": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz",
- "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.3.tgz",
+ "integrity": "sha512-1nESsePMBlf0RPRffLZi5ujYh7IH1BWL4y9pr+Bn3cJBdxz+RTP8bUFljLz9HvzhhOSWKdyBZ4DIivdL6rvgZg==",
"dev": true,
"dependencies": {
"@types/istanbul-lib-report": "*"
}
},
"node_modules/@types/jasmine": {
- "version": "4.3.5",
- "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-4.3.5.tgz",
- "integrity": "sha512-9YHUdvuNDDRJYXZwHqSsO72Ok0vmqoJbNn73ttyITQp/VA60SarnZ+MPLD37rJAhVoKp+9BWOvJP5tHIRfZylQ==",
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-4.3.6.tgz",
+ "integrity": "sha512-3N0FpQTeiWjm+Oo1WUYWguUS7E6JLceiGTriFrG8k5PU7zRLJCzLcWURU3wjMbZGS//a2/LgjsnO3QxIlwxt9g==",
"dev": true
},
"node_modules/@types/json-query": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/@types/json-query/-/json-query-2.2.3.tgz",
- "integrity": "sha512-ygE4p8lyKzTBo9LF2K/u6MHnxPxbHY6wGvwM7TdAKhbP3SvEf+Y9aeVWedDiP8SMIPowTl9R/6awQYjiUTHz2g==",
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/@types/json-query/-/json-query-2.2.5.tgz",
+ "integrity": "sha512-DuoPfJ2lDdVWa1KSsJKOx1m1EXl2yIGwxymr2Hgpzilzzatmq6Ws3+7E9lo0Vk3EYBoXW95oAlQumYCsLKAa4g==",
"dev": true
},
"node_modules/@types/json-schema": {
- "version": "7.0.12",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz",
- "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA=="
+ "version": "7.0.14",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz",
+ "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw=="
},
"node_modules/@types/leaflet": {
- "version": "1.9.4",
- "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.4.tgz",
- "integrity": "sha512-kfwgQf4eOxoe/tD9CaKQrBKHbc7VpyfJOG5sxsQtkH+ML9xYa8hUC3UMa0wU1pKfciJtO0pU9g9XbWhPo7iBCA==",
+ "version": "1.9.7",
+ "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.7.tgz",
+ "integrity": "sha512-FOfKB1ALYUDnXkH7LfTFreWiZr9R7GErqGP+8lYQGWr2GFq5+jy3Ih0M7e9j41cvRN65kLALJ4dc43yZwyl/6g==",
"dev": true,
"dependencies": {
"@types/geojson": "*"
}
},
"node_modules/@types/lodash": {
- "version": "4.14.198",
- "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.198.tgz",
- "integrity": "sha512-trNJ/vtMZYMLhfN45uLq4ShQSw0/S7xCTLLVM+WM1rmFpba/VS42jVUgaO3w/NOLiWR/09lnYk0yMaA/atdIsg==",
+ "version": "4.14.200",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.200.tgz",
+ "integrity": "sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==",
"dev": true
},
"node_modules/@types/lodash-es": {
- "version": "4.17.9",
- "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.9.tgz",
- "integrity": "sha512-ZTcmhiI3NNU7dEvWLZJkzG6ao49zOIjEgIE0RgV7wbPxU0f2xT3VSAHw2gmst8swH6V0YkLRGp4qPlX/6I90MQ==",
+ "version": "4.17.10",
+ "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.10.tgz",
+ "integrity": "sha512-YJP+w/2khSBwbUSFdGsSqmDvmnN3cCKoPOL7Zjle6s30ZtemkkqhjVfFqGwPN7ASil5VyjE2GtyU/yqYY6mC0A==",
"dev": true,
"dependencies": {
"@types/lodash": "*"
}
},
"node_modules/@types/marked": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.3.1.tgz",
- "integrity": "sha512-vSSbKZFbNktrQ15v7o1EaH78EbWV+sPQbPjHG+Cp8CaNcPFUEfjZ0Iml/V0bFDwsTlYe8o6XC5Hfdp91cqPV2g==",
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.3.2.tgz",
+ "integrity": "sha512-a79Yc3TOk6dGdituy8hmTTJXjOkZ7zsFYV10L337ttq/rec8lRMDBpV7fL3uLx6TgbFCa5DU/h8FmIBQPSbU0w==",
"peer": true
},
"node_modules/@types/md5": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/@types/md5/-/md5-2.3.2.tgz",
- "integrity": "sha512-v+JFDu96+UYJ3/UWzB0mEglIS//MZXgRaJ4ubUPwOM0gvLc/kcQ3TWNYwENEK7/EcXGQVrW8h/XqednSjBd/Og==",
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/@types/md5/-/md5-2.3.4.tgz",
+ "integrity": "sha512-e/L4hvpCK8GavKXmP02QlNilZOj8lpmZGGA9QGMMPZjCUoKgi1B4BvhXcbruIi6r+PqzpcjLfda/tocpHFKqDA==",
"dev": true
},
"node_modules/@types/mdx": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.7.tgz",
- "integrity": "sha512-BG4tyr+4amr3WsSEmHn/fXPqaCba/AYZ7dsaQTiavihQunHSIxk+uAtqsjvicNpyHN6cm+B9RVrUOtW9VzIKHw==",
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.8.tgz",
+ "integrity": "sha512-r7/zWe+f9x+zjXqGxf821qz++ld8tp6Z4jUS6qmPZUXH6tfh4riXOhAqb12tWGWAevCFtMt1goLWkQMqIJKpsA==",
"dev": true
},
"node_modules/@types/mime": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
- "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==",
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.3.tgz",
+ "integrity": "sha512-Ys+/St+2VF4+xuY6+kDIXGxbNRO0mesVg0bbxEfB97Od1Vjpjx9KD1qxs64Gcb3CWPirk9Xe+PT4YiiHQ9T+eg==",
"dev": true
},
"node_modules/@types/mime-types": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.1.tgz",
- "integrity": "sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.3.tgz",
+ "integrity": "sha512-bvxCbHeeS7quxS7uOJShyoOQj/BfLabhF6mk9Rmr+2MRfW8W1yxyyL/0GTxLFTHen41GrIw4K3D4DrLouhb8vg==",
"dev": true
},
"node_modules/@types/ms": {
- "version": "0.7.31",
- "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz",
- "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==",
+ "version": "0.7.33",
+ "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.33.tgz",
+ "integrity": "sha512-AuHIyzR5Hea7ij0P9q7vx7xu4z0C28ucwjAZC0ja7JhINyCnOw8/DnvAPQQ9TfOlCtZAmCERKQX9+o1mgQhuOQ==",
"dev": true
},
"node_modules/@types/node": {
- "version": "20.6.0",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.0.tgz",
- "integrity": "sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg=="
+ "version": "20.8.7",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz",
+ "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==",
+ "dependencies": {
+ "undici-types": "~5.25.1"
+ }
},
"node_modules/@types/node-fetch": {
- "version": "2.6.5",
- "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.5.tgz",
- "integrity": "sha512-OZsUlr2nxvkqUFLSaY2ZbA+P1q22q+KrlxWOn/38RX+u5kTkYL2mTujEpzUhGkS+K/QCYp9oagfXG39XOzyySg==",
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-lX17GZVpJ/fuCjguZ5b3TjEbSENxmEk1B2z02yoXSK9WMEWRivhdSY73wWMn6bpcCDAOh6qAdktpKHIlkDk2lg==",
"dev": true,
"dependencies": {
"@types/node": "*",
@@ -8950,21 +9221,21 @@
}
},
"node_modules/@types/normalize-package-data": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz",
- "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==",
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.3.tgz",
+ "integrity": "sha512-ehPtgRgaULsFG8x0NeYJvmyH1hmlfsNLujHe9dQEia/7MAJYdzMSi19JtchUHjmBA6XC/75dK55mzZH+RyieSg==",
"dev": true
},
"node_modules/@types/parse-json": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
- "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.1.tgz",
+ "integrity": "sha512-3YmXzzPAdOTVljVMkTMBdBEvlOLg2cDQaDhnnhT3nT9uDbnJzjWhKlzb+desT12Y7tGqaN6d+AbozcKzyL36Ng==",
"dev": true
},
"node_modules/@types/pouchdb": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/@types/pouchdb/-/pouchdb-6.4.0.tgz",
- "integrity": "sha512-eGCpX+NXhd5VLJuJMzwe3L79fa9+IDTrAG3CPaf4s/31PD56hOrhDJTSmRELSXuiqXr6+OHzzP0PldSaWsFt7w==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@types/pouchdb/-/pouchdb-6.4.1.tgz",
+ "integrity": "sha512-GvTXWOup2REK9WttO6nHM81S+ICTssBzpMZ/waD+HBWvbNLGPeg89rOhsKm7YuUjSPRZwYkfldqh8epvaR9JdQ==",
"dev": true,
"dependencies": {
"@types/pouchdb-adapter-cordova-sqlite": "*",
@@ -8985,72 +9256,72 @@
}
},
"node_modules/@types/pouchdb-adapter-cordova-sqlite": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-cordova-sqlite/-/pouchdb-adapter-cordova-sqlite-1.0.1.tgz",
- "integrity": "sha512-nqlXpW1ho3KBg1mUQvZgH2755y3z/rw4UA7ZJCPMRTHofxGMY8izRVw5rHBL4/7P615or0J2udpRYxgkT3D02g==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-cordova-sqlite/-/pouchdb-adapter-cordova-sqlite-1.0.3.tgz",
+ "integrity": "sha512-xQTzjPW5AgtUzobByDY2VgIXeQ5QRN0BZumufvj6Y2c0lw9UZFHGgHQPe6eCVbGmZneaWhTKw+HutS4gILFzqw==",
"dev": true,
"dependencies": {
"@types/pouchdb-core": "*"
}
},
"node_modules/@types/pouchdb-adapter-fruitdown": {
- "version": "6.1.3",
- "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-fruitdown/-/pouchdb-adapter-fruitdown-6.1.3.tgz",
- "integrity": "sha512-Wz1Z1JLOW1hgmFQjqnSkmyyfH7by/iWb4abKn684WMvQfmxx6BxKJpJ4+eulkVPQzzgMMSgU1MpnQOm9FgRkbw==",
+ "version": "6.1.5",
+ "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-fruitdown/-/pouchdb-adapter-fruitdown-6.1.5.tgz",
+ "integrity": "sha512-p3BsBmYLbv8gVH9Ca1B45+Ua/hhX1V9o/UCdeAkcjC0Cx8aMnBz5B1oEflVhvuInpTfrwA8v1biLb/CaWBOeMw==",
"dev": true,
"dependencies": {
"@types/pouchdb-core": "*"
}
},
"node_modules/@types/pouchdb-adapter-http": {
- "version": "6.1.3",
- "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-http/-/pouchdb-adapter-http-6.1.3.tgz",
- "integrity": "sha512-9Z4TLbF/KJWy/D2sWRPBA+RNU0odQimfdvlDX+EY7rGcd3aVoH8qjD/X0Xcd/0dfBH5pKrNIMFFQgW/TylRCmA==",
+ "version": "6.1.5",
+ "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-http/-/pouchdb-adapter-http-6.1.5.tgz",
+ "integrity": "sha512-FC84xpDBL4rcJ86CjHiEFYG99sHyca7MJOPFoyePe+JxQd48TFWJ6hWcO7QyyBpIvF2h7Divg8jnaxnyHDSQ4w==",
"dev": true,
"dependencies": {
"@types/pouchdb-core": "*"
}
},
"node_modules/@types/pouchdb-adapter-idb": {
- "version": "6.1.4",
- "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-idb/-/pouchdb-adapter-idb-6.1.4.tgz",
- "integrity": "sha512-KIAXbkF4uYUz0ZwfNEFLtEkK44mEWopAsD76UhucH92XnJloBysav+TjI4FFfYQyTjoW3S1s6V+Z14CUJZ0F6w==",
+ "version": "6.1.6",
+ "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-idb/-/pouchdb-adapter-idb-6.1.6.tgz",
+ "integrity": "sha512-hS/QtHDwMeZbOS7D2epua1Ks/dabYPIqbJPEr9UOAtHiGhTZbQss7Flb66zB+we2cBYYPPUOYOwHbXs61zRBnQ==",
"dev": true,
"dependencies": {
"@types/pouchdb-core": "*"
}
},
"node_modules/@types/pouchdb-adapter-leveldb": {
- "version": "6.1.3",
- "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-leveldb/-/pouchdb-adapter-leveldb-6.1.3.tgz",
- "integrity": "sha512-ex8NFqQGFwEpFi7AaZ5YofmuemfZNsL3nTFZBUCAKYMBkazQij1pe2ILLStSvJr0XS0qxgXjCEW19T5Wqiiskg==",
+ "version": "6.1.5",
+ "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-leveldb/-/pouchdb-adapter-leveldb-6.1.5.tgz",
+ "integrity": "sha512-a0lZTPSEfojLabv9sOoksKh9zDfW8Q0N5aDAxfNGRH8BtdQ8wSHr3+V8igTdg9kT+OMhdU+G9xC543M2CY5edg==",
"dev": true,
"dependencies": {
"@types/pouchdb-core": "*"
}
},
"node_modules/@types/pouchdb-adapter-localstorage": {
- "version": "6.1.3",
- "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-localstorage/-/pouchdb-adapter-localstorage-6.1.3.tgz",
- "integrity": "sha512-oor040tye1KKiGLWYtIy7rRT7C2yoyX3Tf6elEJRpjOA7Ja/H8lKc4LaSh9ATbptIcES6MRqZDxtp7ly9hsW3Q==",
+ "version": "6.1.5",
+ "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-localstorage/-/pouchdb-adapter-localstorage-6.1.5.tgz",
+ "integrity": "sha512-qeXAYHm1avjgjS9tu6RgB7I9pQdNJ207kfYX6Nj0VsUGRtH2JjWPR16oIPqwvjdO6gVnNArS2MI4K+G6qzobLQ==",
"dev": true,
"dependencies": {
"@types/pouchdb-core": "*"
}
},
"node_modules/@types/pouchdb-adapter-memory": {
- "version": "6.1.3",
- "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-memory/-/pouchdb-adapter-memory-6.1.3.tgz",
- "integrity": "sha512-gVbsIMzDzgZYThFVT4eVNsmuZwVm/4jDxP1sjlgc3qtDIxbtBhGgyNfcskwwz9Zu5Lv1avkDsIWvcxQhnvRlHg==",
+ "version": "6.1.5",
+ "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-memory/-/pouchdb-adapter-memory-6.1.5.tgz",
+ "integrity": "sha512-n0Ps/SoHgTJ584cwD3YZyOriQa9m0ed4Taleq8deFWp2cV9ZLvt1ehV+5Or82VMSvqYK315RGosuDgSkPsUDng==",
"dev": true,
"dependencies": {
"@types/pouchdb-core": "*"
}
},
"node_modules/@types/pouchdb-adapter-node-websql": {
- "version": "6.1.3",
- "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-node-websql/-/pouchdb-adapter-node-websql-6.1.3.tgz",
- "integrity": "sha512-F/P+os6Jsa7CgHtH64+Z0HfwIcj0hIRB5z8gNhF7L7dxPWoAfkopK5H2gydrP3sQrlGyN4WInF+UJW/Zu1+FKg==",
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-node-websql/-/pouchdb-adapter-node-websql-6.1.4.tgz",
+ "integrity": "sha512-Jpt9a0jv0RHPwPMaaAfZvSxUkuburTSmZL/ksWkm7Efx/Ui8VFPEA/bT8ulHkkWtKWjoCCI79pceeY/xEpeYqw==",
"dev": true,
"dependencies": {
"@types/pouchdb-adapter-websql": "*",
@@ -9058,18 +9329,18 @@
}
},
"node_modules/@types/pouchdb-adapter-websql": {
- "version": "6.1.4",
- "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-websql/-/pouchdb-adapter-websql-6.1.4.tgz",
- "integrity": "sha512-zMJQCtXC40hBsIDRn0GhmpeGMK0f9l/OGWfLguvczROzxxcOD7REI+e6SEmX7gJKw5JuMvlfuHzkQwjmvSJbtg==",
+ "version": "6.1.6",
+ "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-websql/-/pouchdb-adapter-websql-6.1.6.tgz",
+ "integrity": "sha512-Yx0Ek7LiAEc5maD5W4d9yD/tmKyr7yFK+NZNSvPsIM6PH9Lc4Xd7b+bQdiiwvyLBBfCkWyYFrhzkGcHD5m/1YA==",
"dev": true,
"dependencies": {
"@types/pouchdb-core": "*"
}
},
"node_modules/@types/pouchdb-browser": {
- "version": "6.1.3",
- "resolved": "https://registry.npmjs.org/@types/pouchdb-browser/-/pouchdb-browser-6.1.3.tgz",
- "integrity": "sha512-EdYowrWxW9SWBMX/rux2eq7dbHi5Zeyzz+FF/IAsgQKnUxgeCO5VO2j4zTzos0SDyJvAQU+EYRc11r7xGn5tvA==",
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/@types/pouchdb-browser/-/pouchdb-browser-6.1.4.tgz",
+ "integrity": "sha512-yo/igvZ5JBZTkqEZoIOYXkIwyP1+hZdFY3Ts3ot/zZWmpXyySKvbtfNnhmtLeyTDWkc6ZL/U3rP/ta2U33WWvA==",
"dev": true,
"dependencies": {
"@types/pouchdb-adapter-http": "*",
@@ -9081,9 +9352,9 @@
}
},
"node_modules/@types/pouchdb-core": {
- "version": "7.0.11",
- "resolved": "https://registry.npmjs.org/@types/pouchdb-core/-/pouchdb-core-7.0.11.tgz",
- "integrity": "sha512-KTKj0Taf8pLTj8eW3qBtCd1Fh+/yhEyVo6/1czTN46MnseobdmnqgXtzaKgHMbuLouh+SHK1vM++aMPaG1qTTA==",
+ "version": "7.0.13",
+ "resolved": "https://registry.npmjs.org/@types/pouchdb-core/-/pouchdb-core-7.0.13.tgz",
+ "integrity": "sha512-DAuu60a/Y+An30+thA6BoucTyb4IdeIzqvz4qBfJRoUkKRIsFo7qMB4SUm1/wIq7ppyd9mljnjGRUIgCxjnS4w==",
"dev": true,
"dependencies": {
"@types/debug": "*",
@@ -9091,18 +9362,18 @@
}
},
"node_modules/@types/pouchdb-find": {
- "version": "7.3.0",
- "resolved": "https://registry.npmjs.org/@types/pouchdb-find/-/pouchdb-find-7.3.0.tgz",
- "integrity": "sha512-sFPli5tBjGX9UfXioik1jUzPdcN84eV82n0lmEFuoPepWqkLjQcyri0eOa++HYOaNPyMDhKFBqEALEZivK2dRg==",
+ "version": "7.3.2",
+ "resolved": "https://registry.npmjs.org/@types/pouchdb-find/-/pouchdb-find-7.3.2.tgz",
+ "integrity": "sha512-H4D+2gpGfoJCXURDJR6dIg6bKpFN3X46CQZEmEOeYSy5xGguEXokU+oKQ3HrIlD9p2eA4aonuh5I8uSTMSLprw==",
"dev": true,
"dependencies": {
"@types/pouchdb-core": "*"
}
},
"node_modules/@types/pouchdb-http": {
- "version": "6.1.3",
- "resolved": "https://registry.npmjs.org/@types/pouchdb-http/-/pouchdb-http-6.1.3.tgz",
- "integrity": "sha512-0e9E5SqNOyPl/3FnEIbENssB4FlJsNYuOy131nxrZk36S+y1R/6qO7ZVRypWpGTqBWSuVd7gCsq2UDwO/285+w==",
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/@types/pouchdb-http/-/pouchdb-http-6.1.4.tgz",
+ "integrity": "sha512-Sx7qnc9HaTJr15UDZTnxsxiqxeG47LyWdCX+KUoVhjWMw3cBbY1Wv4UuEAAlsNTdVK1t/GrmgC2K1rH+nRvIxg==",
"dev": true,
"dependencies": {
"@types/pouchdb-adapter-http": "*",
@@ -9110,18 +9381,18 @@
}
},
"node_modules/@types/pouchdb-mapreduce": {
- "version": "6.1.7",
- "resolved": "https://registry.npmjs.org/@types/pouchdb-mapreduce/-/pouchdb-mapreduce-6.1.7.tgz",
- "integrity": "sha512-WzBwm7tmO9QhfRzVaWT4v6JQSS/fG2OoUDrWrhX87rPe2Pn6laPvdK5li6myNRxCoI/l5e8Jd+oYBAFnaiFucA==",
+ "version": "6.1.9",
+ "resolved": "https://registry.npmjs.org/@types/pouchdb-mapreduce/-/pouchdb-mapreduce-6.1.9.tgz",
+ "integrity": "sha512-dsgLocavfxj4exjUETKU5ffKYhjzdBfkTDSctVSWLUqjKsUuAqHCcot6ECxkUVuD6Tejv0Y8rGi3If5xzGb5Vw==",
"dev": true,
"dependencies": {
"@types/pouchdb-core": "*"
}
},
"node_modules/@types/pouchdb-node": {
- "version": "6.1.4",
- "resolved": "https://registry.npmjs.org/@types/pouchdb-node/-/pouchdb-node-6.1.4.tgz",
- "integrity": "sha512-wnTCH8X1JOPpNOfVhz8HW0AvmdHh6pt40MuRj0jQnK7QEHsHS79WujsKTKSOF8QXtPwpvCNSsI7ut7H7tfxxJQ==",
+ "version": "6.1.6",
+ "resolved": "https://registry.npmjs.org/@types/pouchdb-node/-/pouchdb-node-6.1.6.tgz",
+ "integrity": "sha512-5t3p4YsbAp3sxx4OVhBdsfwfuM3o9XNnjXOEj10up/Z6ykIqDLfFyy2kPWW5c9txj7Qxl07EQlwm9CbIWNEhBg==",
"dev": true,
"dependencies": {
"@types/pouchdb-adapter-http": "*",
@@ -9132,9 +9403,9 @@
}
},
"node_modules/@types/pouchdb-replication": {
- "version": "6.4.4",
- "resolved": "https://registry.npmjs.org/@types/pouchdb-replication/-/pouchdb-replication-6.4.4.tgz",
- "integrity": "sha512-BsE5LKpjJK4iAf6Fx5kyrMw+33V+Ip7uWldUnU2BYrrvtR+MLD22dcImm7DZN1st2wPPb91i0XEnQzvP0w1C/Q==",
+ "version": "6.4.6",
+ "resolved": "https://registry.npmjs.org/@types/pouchdb-replication/-/pouchdb-replication-6.4.6.tgz",
+ "integrity": "sha512-DYsh3X5fnbmMOZ1u0CAZBD8iPkDmHQIJwxjez8S60SHQyFqLUzd4A/OV7C4nNszdcdtGNwhSwoNdfjZe4JX16Q==",
"dev": true,
"dependencies": {
"@types/pouchdb-core": "*",
@@ -9142,33 +9413,33 @@
}
},
"node_modules/@types/pretty-hrtime": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@types/pretty-hrtime/-/pretty-hrtime-1.0.1.tgz",
- "integrity": "sha512-VjID5MJb1eGKthz2qUerWT8+R4b9N+CHvGCzg9fn4kWZgaF9AhdYikQio3R7wV8YY1NsQKPaCwKz1Yff+aHNUQ==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@types/pretty-hrtime/-/pretty-hrtime-1.0.2.tgz",
+ "integrity": "sha512-vyv9knII8XeW8TnXDcGH7HqG6FeR56ESN6ExM34d/U8Zvs3xuG34euV6CVyB7KEYI7Ts4lQM8b4NL72e7UadnA==",
"dev": true
},
"node_modules/@types/prop-types": {
- "version": "15.7.5",
- "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
- "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
+ "version": "15.7.9",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz",
+ "integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==",
"dev": true
},
"node_modules/@types/qs": {
- "version": "6.9.8",
- "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz",
- "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==",
+ "version": "6.9.9",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz",
+ "integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==",
"dev": true
},
"node_modules/@types/range-parser": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
- "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==",
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz",
+ "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==",
"dev": true
},
"node_modules/@types/react": {
- "version": "18.2.21",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.21.tgz",
- "integrity": "sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA==",
+ "version": "18.2.29",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.29.tgz",
+ "integrity": "sha512-Z+ZrIRocWtdD70j45izShRwDuiB4JZqDegqMFW/I8aG5DxxLKOzVNoq62UIO82v9bdgi+DO1jvsb9sTEZUSm+Q==",
"dev": true,
"dependencies": {
"@types/prop-types": "*",
@@ -9177,18 +9448,18 @@
}
},
"node_modules/@types/react-dom": {
- "version": "16.9.19",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.19.tgz",
- "integrity": "sha512-xC8D280Bf6p0zguJ8g62jcEOKZiUbx9sIe6O3tT/lKfR87A7A6g65q13z6D5QUMIa/6yFPkNhqjF5z/VVZEYqQ==",
+ "version": "16.9.20",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.20.tgz",
+ "integrity": "sha512-sYJBek61QO1qeZOnGy79jOaQnQK/sT5CHK0gmwEhMzbhrgpRWoxdEXRaaR96vGfRttWliKG82SVrWbc6WRNwng==",
"dev": true,
"dependencies": {
"@types/react": "^16"
}
},
"node_modules/@types/react-dom/node_modules/@types/react": {
- "version": "16.14.46",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.46.tgz",
- "integrity": "sha512-Am4pyXMrr6cWWw/TN3oqHtEZl0j+G6Up/O8m65+xF/3ZaUgkv1GAtTPWw4yNRmH0HJXmur6xKCKoMo3rBGynuw==",
+ "version": "16.14.50",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.50.tgz",
+ "integrity": "sha512-7TWZ/HjhXsRK3BbhSFxTinbSft3sUXJAU3ONngT0rpcKJaIOlxkRke4bidqQTopUbEv1ApC5nlSEkIpX43MkTg==",
"dev": true,
"dependencies": {
"@types/prop-types": "*",
@@ -9203,21 +9474,21 @@
"dev": true
},
"node_modules/@types/scheduler": {
- "version": "0.16.3",
- "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
- "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==",
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.4.tgz",
+ "integrity": "sha512-2L9ifAGl7wmXwP4v3pN4p2FLhD0O1qsJpvKmNin5VA8+UvNVb447UDaAEV6UdrkA+m/Xs58U1RFps44x6TFsVQ==",
"dev": true
},
"node_modules/@types/semver": {
- "version": "7.5.2",
- "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.2.tgz",
- "integrity": "sha512-7aqorHYgdNO4DM36stTiGO3DvKoex9TQRwsJU6vMaFGyqpBA1MNZkz+PG3gaNUPpTAOYhT1WR7M1JyA3fbS9Cw==",
+ "version": "7.5.3",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz",
+ "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==",
"dev": true
},
"node_modules/@types/send": {
- "version": "0.17.1",
- "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz",
- "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==",
+ "version": "0.17.2",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.2.tgz",
+ "integrity": "sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==",
"dev": true,
"dependencies": {
"@types/mime": "^1",
@@ -9225,18 +9496,18 @@
}
},
"node_modules/@types/serve-index": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz",
- "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==",
+ "version": "1.9.2",
+ "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.2.tgz",
+ "integrity": "sha512-asaEIoc6J+DbBKXtO7p2shWUpKacZOoMBEGBgPG91P8xhO53ohzHWGCs4ScZo5pQMf5ukQzVT9fhX1WzpHihig==",
"dev": true,
"dependencies": {
"@types/express": "*"
}
},
"node_modules/@types/serve-static": {
- "version": "1.15.2",
- "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz",
- "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==",
+ "version": "1.15.3",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.3.tgz",
+ "integrity": "sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg==",
"dev": true,
"dependencies": {
"@types/http-errors": "*",
@@ -9251,15 +9522,15 @@
"dev": true
},
"node_modules/@types/sizzle": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
- "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.4.tgz",
+ "integrity": "sha512-jA2llq2zNkg8HrALI7DtWzhALcVH0l7i89yhY3iBdOz6cBPeACoFq+fkQrjHA39t1hnSFOboZ7A/AY5MMZSlag==",
"dev": true
},
"node_modules/@types/sockjs": {
- "version": "0.3.33",
- "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz",
- "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==",
+ "version": "0.3.34",
+ "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.34.tgz",
+ "integrity": "sha512-R+n7qBFnm/6jinlteC9DBL5dGiDGjWAvjo4viUanpnc/dG1y7uDoacXPIQ/PQEg1fI912SMHIa014ZjRpvDw4g==",
"dev": true,
"dependencies": {
"@types/node": "*"
@@ -9272,21 +9543,21 @@
"dev": true
},
"node_modules/@types/uuid": {
- "version": "9.0.3",
- "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.3.tgz",
- "integrity": "sha512-taHQQH/3ZyI3zP8M/puluDEIEvtQHVYcC6y3N8ijFtAd28+Ey/G4sg1u2gB01S8MwybLOKAp9/yCMu/uR5l3Ug==",
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.5.tgz",
+ "integrity": "sha512-xfHdwa1FMJ082prjSJpoEI57GZITiQz10r3vEJCHa2khEFQjKy91aWKz6+zybzssCvXUwE1LQWgWVwZ4nYUvHQ==",
"dev": true
},
"node_modules/@types/webpack-env": {
- "version": "1.18.1",
- "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.1.tgz",
- "integrity": "sha512-D0HJET2/UY6k9L6y3f5BL+IDxZmPkYmPT4+qBrRdmRLYRuV0qNKizMgTvYxXZYn+36zjPeoDZAEYBCM6XB+gww==",
+ "version": "1.18.2",
+ "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.2.tgz",
+ "integrity": "sha512-BFqcTHHTrrI8EBmIzNAmLPP3IqtEG9J1IPFWbPeS/F0/TGNmo0pI5svOa7JbMF9vSCXQCvJWT2gxLJNVuf9blw==",
"dev": true
},
"node_modules/@types/ws": {
- "version": "8.5.5",
- "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz",
- "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==",
+ "version": "8.5.7",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.7.tgz",
+ "integrity": "sha512-6UrLjiDUvn40CMrAubXuIVtj2PEfKDffJS7ychvnPU44j+KVeXmdHHTgqcM/dxLUTHxlXHiFM8Skmb8ozGdTnQ==",
"dev": true,
"dependencies": {
"@types/node": "*"
@@ -9299,24 +9570,24 @@
"dev": true
},
"node_modules/@types/yargs": {
- "version": "17.0.24",
- "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz",
- "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==",
+ "version": "17.0.28",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.28.tgz",
+ "integrity": "sha512-N3e3fkS86hNhtk6BEnc0rj3zcehaxx8QWhCROJkqpl5Zaoi7nAic3jH8q94jVD3zu5LGk+PUB6KAiDmimYOEQw==",
"dev": true,
"dependencies": {
"@types/yargs-parser": "*"
}
},
"node_modules/@types/yargs-parser": {
- "version": "21.0.0",
- "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz",
- "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==",
+ "version": "21.0.1",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.1.tgz",
+ "integrity": "sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==",
"dev": true
},
"node_modules/@types/yauzl": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz",
- "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==",
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.1.tgz",
+ "integrity": "sha512-CHzgNU3qYBnp/O4S3yv2tXPlvMTq0YWSTVg2/JYLqWZGHwwgJGAwd00poay/11asPq8wLFwHzubyInqHIFmmiw==",
"dev": true,
"optional": true,
"dependencies": {
@@ -9324,16 +9595,16 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "6.7.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.0.tgz",
- "integrity": "sha512-gUqtknHm0TDs1LhY12K2NA3Rmlmp88jK9Tx8vGZMfHeNMLE3GH2e9TRub+y+SOjuYgtOmok+wt1AyDPZqxbNag==",
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.8.0.tgz",
+ "integrity": "sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw==",
"dev": true,
"dependencies": {
"@eslint-community/regexpp": "^4.5.1",
- "@typescript-eslint/scope-manager": "6.7.0",
- "@typescript-eslint/type-utils": "6.7.0",
- "@typescript-eslint/utils": "6.7.0",
- "@typescript-eslint/visitor-keys": "6.7.0",
+ "@typescript-eslint/scope-manager": "6.8.0",
+ "@typescript-eslint/type-utils": "6.8.0",
+ "@typescript-eslint/utils": "6.8.0",
+ "@typescript-eslint/visitor-keys": "6.8.0",
"debug": "^4.3.4",
"graphemer": "^1.4.0",
"ignore": "^5.2.4",
@@ -9359,13 +9630,13 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": {
- "version": "6.7.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.0.tgz",
- "integrity": "sha512-f/QabJgDAlpSz3qduCyQT0Fw7hHpmhOzY/Rv6zO3yO+HVIdPfIWhrQoAyG+uZVtWAIS85zAyzgAFfyEr+MgBpg==",
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.8.0.tgz",
+ "integrity": "sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g==",
"dev": true,
"dependencies": {
- "@typescript-eslint/typescript-estree": "6.7.0",
- "@typescript-eslint/utils": "6.7.0",
+ "@typescript-eslint/typescript-estree": "6.8.0",
+ "@typescript-eslint/utils": "6.8.0",
"debug": "^4.3.4",
"ts-api-utils": "^1.0.1"
},
@@ -9386,17 +9657,17 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": {
- "version": "6.7.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.0.tgz",
- "integrity": "sha512-MfCq3cM0vh2slSikQYqK2Gq52gvOhe57vD2RM3V4gQRZYX4rDPnKLu5p6cm89+LJiGlwEXU8hkYxhqqEC/V3qA==",
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.8.0.tgz",
+ "integrity": "sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@types/json-schema": "^7.0.12",
"@types/semver": "^7.5.0",
- "@typescript-eslint/scope-manager": "6.7.0",
- "@typescript-eslint/types": "6.7.0",
- "@typescript-eslint/typescript-estree": "6.7.0",
+ "@typescript-eslint/scope-manager": "6.8.0",
+ "@typescript-eslint/types": "6.8.0",
+ "@typescript-eslint/typescript-estree": "6.8.0",
"semver": "^7.5.4"
},
"engines": {
@@ -9411,15 +9682,15 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "6.7.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.0.tgz",
- "integrity": "sha512-jZKYwqNpNm5kzPVP5z1JXAuxjtl2uG+5NpaMocFPTNC2EdYIgbXIPImObOkhbONxtFTTdoZstLZefbaK+wXZng==",
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.8.0.tgz",
+ "integrity": "sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg==",
"dev": true,
"dependencies": {
- "@typescript-eslint/scope-manager": "6.7.0",
- "@typescript-eslint/types": "6.7.0",
- "@typescript-eslint/typescript-estree": "6.7.0",
- "@typescript-eslint/visitor-keys": "6.7.0",
+ "@typescript-eslint/scope-manager": "6.8.0",
+ "@typescript-eslint/types": "6.8.0",
+ "@typescript-eslint/typescript-estree": "6.8.0",
+ "@typescript-eslint/visitor-keys": "6.8.0",
"debug": "^4.3.4"
},
"engines": {
@@ -9439,13 +9710,13 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "6.7.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.0.tgz",
- "integrity": "sha512-lAT1Uau20lQyjoLUQ5FUMSX/dS07qux9rYd5FGzKz/Kf8W8ccuvMyldb8hadHdK/qOI7aikvQWqulnEq2nCEYA==",
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz",
+ "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "6.7.0",
- "@typescript-eslint/visitor-keys": "6.7.0"
+ "@typescript-eslint/types": "6.8.0",
+ "@typescript-eslint/visitor-keys": "6.8.0"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
@@ -9540,9 +9811,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "6.7.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.0.tgz",
- "integrity": "sha512-ihPfvOp7pOcN/ysoj0RpBPOx3HQTJTrIN8UZK+WFd3/iDeFHHqeyYxa4hQk4rMhsz9H9mXpR61IzwlBVGXtl9Q==",
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz",
+ "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==",
"dev": true,
"engines": {
"node": "^16.0.0 || >=18.0.0"
@@ -9553,13 +9824,13 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "6.7.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.0.tgz",
- "integrity": "sha512-dPvkXj3n6e9yd/0LfojNU8VMUGHWiLuBZvbM6V6QYD+2qxqInE7J+J/ieY2iGwR9ivf/R/haWGkIj04WVUeiSQ==",
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz",
+ "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "6.7.0",
- "@typescript-eslint/visitor-keys": "6.7.0",
+ "@typescript-eslint/types": "6.8.0",
+ "@typescript-eslint/visitor-keys": "6.8.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@@ -9702,12 +9973,12 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "6.7.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.0.tgz",
- "integrity": "sha512-/C1RVgKFDmGMcVGeD8HjKv2bd72oI1KxQDeY8uc66gw9R0OK0eMq48cA+jv9/2Ag6cdrsUGySm1yzYmfz0hxwQ==",
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz",
+ "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "6.7.0",
+ "@typescript-eslint/types": "6.8.0",
"eslint-visitor-keys": "^3.4.1"
},
"engines": {
@@ -10773,9 +11044,9 @@
"dev": true
},
"node_modules/axios": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz",
- "integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==",
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz",
+ "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==",
"dev": true,
"dependencies": {
"follow-redirects": "^1.15.0",
@@ -10790,12 +11061,12 @@
"dev": true
},
"node_modules/axobject-query": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz",
- "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==",
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
+ "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==",
"dev": true,
"dependencies": {
- "deep-equal": "^2.0.5"
+ "dequal": "^2.0.3"
}
},
"node_modules/babel-core": {
@@ -10960,13 +11231,13 @@
"dev": true
},
"node_modules/babel-plugin-polyfill-corejs2": {
- "version": "0.4.5",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz",
- "integrity": "sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg==",
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.6.tgz",
+ "integrity": "sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==",
"dev": true,
"dependencies": {
"@babel/compat-data": "^7.22.6",
- "@babel/helper-define-polyfill-provider": "^0.4.2",
+ "@babel/helper-define-polyfill-provider": "^0.4.3",
"semver": "^6.3.1"
},
"peerDependencies": {
@@ -10983,25 +11254,25 @@
}
},
"node_modules/babel-plugin-polyfill-corejs3": {
- "version": "0.8.3",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz",
- "integrity": "sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA==",
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.5.tgz",
+ "integrity": "sha512-Q6CdATeAvbScWPNLB8lzSO7fgUVBkQt6zLgNlfyeCr/EQaEQR+bWiBYYPYAFyE528BMjRhL+1QBMOI4jc/c5TA==",
"dev": true,
"dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.4.2",
- "core-js-compat": "^3.31.0"
+ "@babel/helper-define-polyfill-provider": "^0.4.3",
+ "core-js-compat": "^3.32.2"
},
"peerDependencies": {
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
}
},
"node_modules/babel-plugin-polyfill-regenerator": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz",
- "integrity": "sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA==",
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.3.tgz",
+ "integrity": "sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==",
"dev": true,
"dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.4.2"
+ "@babel/helper-define-polyfill-provider": "^0.4.3"
},
"peerDependencies": {
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
@@ -11327,9 +11598,9 @@
}
},
"node_modules/browserslist": {
- "version": "4.21.10",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
- "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
+ "version": "4.22.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz",
+ "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==",
"funding": [
{
"type": "opencollective",
@@ -11345,10 +11616,10 @@
}
],
"dependencies": {
- "caniuse-lite": "^1.0.30001517",
- "electron-to-chromium": "^1.4.477",
+ "caniuse-lite": "^1.0.30001541",
+ "electron-to-chromium": "^1.4.535",
"node-releases": "^2.0.13",
- "update-browserslist-db": "^1.0.11"
+ "update-browserslist-db": "^1.0.13"
},
"bin": {
"browserslist": "cli.js"
@@ -11421,6 +11692,21 @@
"semver": "^7.0.0"
}
},
+ "node_modules/bundle-name": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz",
+ "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==",
+ "dev": true,
+ "dependencies": {
+ "run-applescript": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/bytes": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
@@ -11521,9 +11807,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001534",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001534.tgz",
- "integrity": "sha512-vlPVrhsCS7XaSh2VvWluIQEzVhefrUQcEsQWSS5A5V+dM07uv1qHeQzAOTGIMy9i3e9bH15+muvI/UHojVgS/Q==",
+ "version": "1.0.30001550",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001550.tgz",
+ "integrity": "sha512-p82WjBYIypO0ukTsd/FG3Xxs+4tFeaY9pfT4amQL8KWtYH7H9nYwReGAbMTJ0hsmRO8IfDtsS6p3ZWj8+1c2RQ==",
"funding": [
{
"type": "opencollective",
@@ -11672,9 +11958,9 @@
}
},
"node_modules/ci-info": {
- "version": "3.8.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz",
- "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==",
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
"dev": true,
"funding": [
{
@@ -11892,12 +12178,12 @@
}
},
"node_modules/commander": {
- "version": "10.0.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
- "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
+ "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
"dev": true,
"engines": {
- "node": ">=14"
+ "node": ">=16"
}
},
"node_modules/common-path-prefix": {
@@ -12209,12 +12495,12 @@
}
},
"node_modules/core-js-compat": {
- "version": "3.32.2",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.2.tgz",
- "integrity": "sha512-+GjlguTDINOijtVRUxrQOv3kfu9rl+qPNdX2LTbJ/ZyVTuxK+ksVSAGX1nHstu4hrv1En/uPTtWgq2gI5wt4AQ==",
+ "version": "3.33.0",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.0.tgz",
+ "integrity": "sha512-0w4LcLXsVEuNkIqwjjf9rjCoPhK8uqA4tMRh4Ge26vfLtUutshn+aRJU21I9LCJlh2QQHfisNToLjw1XEJLTWw==",
"dev": true,
"dependencies": {
- "browserslist": "^4.21.10"
+ "browserslist": "^4.22.1"
},
"funding": {
"type": "opencollective",
@@ -12388,14 +12674,14 @@
}
},
"node_modules/crypto-es": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/crypto-es/-/crypto-es-2.0.4.tgz",
- "integrity": "sha512-GJxgJJ7HjGzwT7iQF0K9RertKkzgSKUXd8X2aQ7RGDS8yMVDzIBFMNHID9hnj48Ep8NAICHWV1CFIETlVNZ/Lg=="
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/crypto-es/-/crypto-es-2.1.0.tgz",
+ "integrity": "sha512-C5Dbuv4QTPGuloy5c5Vv/FZHtmK+lobLAypFfuRaBbwCsk3qbCWWESCH3MUcBsrgXloRNMrzwUAiPg4U6+IaKA=="
},
"node_modules/crypto-js": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz",
- "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
+ "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
"dev": true
},
"node_modules/crypto-random-string": {
@@ -12568,9 +12854,9 @@
}
},
"node_modules/cypress/node_modules/@types/node": {
- "version": "16.18.50",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.50.tgz",
- "integrity": "sha512-OiDU5xRgYTJ203v4cprTs0RwOCd5c5Zjv+K5P8KSqfiCsB1W3LcamTUMcnQarpq5kOYbhHfSOgIEJvdPyb5xyw==",
+ "version": "16.18.59",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.59.tgz",
+ "integrity": "sha512-PJ1w2cNeKUEdey4LiPra0ZuxZFOGvetswE8qHRriV/sUkL5Al4tTmPV9D2+Y/TPIxTHHgxTfRjZVKWhPw/ORhQ==",
"dev": true
},
"node_modules/cypress/node_modules/ansi-styles": {
@@ -13247,9 +13533,9 @@
}
},
"node_modules/dayjs": {
- "version": "1.11.9",
- "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz",
- "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==",
+ "version": "1.11.10",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz",
+ "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==",
"devOptional": true
},
"node_modules/debug": {
@@ -13284,29 +13570,17 @@
"dev": true
},
"node_modules/deep-equal": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz",
- "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
+ "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
"dev": true,
"dependencies": {
- "array-buffer-byte-length": "^1.0.0",
- "call-bind": "^1.0.2",
- "es-get-iterator": "^1.1.3",
- "get-intrinsic": "^1.2.1",
- "is-arguments": "^1.1.1",
- "is-array-buffer": "^3.0.2",
- "is-date-object": "^1.0.5",
- "is-regex": "^1.1.4",
- "is-shared-array-buffer": "^1.0.2",
- "isarray": "^2.0.5",
- "object-is": "^1.1.5",
+ "is-arguments": "^1.0.4",
+ "is-date-object": "^1.0.1",
+ "is-regex": "^1.0.4",
+ "object-is": "^1.0.1",
"object-keys": "^1.1.1",
- "object.assign": "^4.1.4",
- "regexp.prototype.flags": "^1.5.0",
- "side-channel": "^1.0.4",
- "which-boxed-primitive": "^1.0.2",
- "which-collection": "^1.0.1",
- "which-typed-array": "^1.1.9"
+ "regexp.prototype.flags": "^1.2.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -13332,6 +13606,24 @@
"node": ">=0.10.0"
}
},
+ "node_modules/default-browser": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz",
+ "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==",
+ "dev": true,
+ "dependencies": {
+ "bundle-name": "^3.0.0",
+ "default-browser-id": "^3.0.0",
+ "execa": "^7.1.1",
+ "titleize": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/default-browser-id": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz",
@@ -13348,6 +13640,116 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/default-browser/node_modules/execa": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz",
+ "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.1",
+ "human-signals": "^4.3.0",
+ "is-stream": "^3.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^5.1.0",
+ "onetime": "^6.0.0",
+ "signal-exit": "^3.0.7",
+ "strip-final-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || ^16.14.0 || >=18.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/default-browser/node_modules/human-signals": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz",
+ "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.18.0"
+ }
+ },
+ "node_modules/default-browser/node_modules/is-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
+ "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser/node_modules/mimic-fn": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
+ "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser/node_modules/npm-run-path": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
+ "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser/node_modules/onetime": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
+ "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
+ "dev": true,
+ "dependencies": {
+ "mimic-fn": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser/node_modules/path-key": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
+ "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser/node_modules/strip-final-newline": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
+ "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/default-gateway": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz",
@@ -13400,9 +13802,9 @@
}
},
"node_modules/define-data-property": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz",
- "integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
+ "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
"dependencies": {
"get-intrinsic": "^1.2.1",
"gopd": "^1.0.1",
@@ -13909,9 +14311,9 @@
}
},
"node_modules/electron-to-chromium": {
- "version": "1.4.520",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.520.tgz",
- "integrity": "sha512-Frfus2VpYADsrh1lB3v/ft/WVFlVzOIm+Q0p7U7VqHI6qr7NWHYKe+Wif3W50n7JAFoBsWVsoU0+qDks6WQ60g=="
+ "version": "1.4.557",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.557.tgz",
+ "integrity": "sha512-6x0zsxyMXpnMJnHrondrD3SuAeKcwij9S+83j2qHAQPXbGTDDfgImzzwgGlzrIcXbHQ42tkG4qA6U860cImNhw=="
},
"node_modules/elkjs": {
"version": "0.8.2",
@@ -13979,9 +14381,9 @@
}
},
"node_modules/engine.io": {
- "version": "6.5.2",
- "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.2.tgz",
- "integrity": "sha512-IXsMcGpw/xRfjra46sVZVHiSWo/nJ/3g1337q9KNXtS6YRzbW5yIzTCb9DjhrBe7r3GZQR0I4+nq+4ODk5g/cA==",
+ "version": "6.5.3",
+ "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.3.tgz",
+ "integrity": "sha512-IML/R4eG/pUS5w7OfcDE0jKrljWS9nwnEfsxWCIJF5eO6AHo6+Hlv+lQbdlAYsiJPHzUthLm1RUjnBzWOs45cw==",
"dev": true,
"dependencies": {
"@types/cookie": "^0.4.1",
@@ -14347,15 +14749,15 @@
}
},
"node_modules/eslint": {
- "version": "8.49.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.49.0.tgz",
- "integrity": "sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==",
+ "version": "8.51.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz",
+ "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
"@eslint/eslintrc": "^2.1.2",
- "@eslint/js": "8.49.0",
+ "@eslint/js": "8.51.0",
"@humanwhocodes/config-array": "^0.11.11",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
@@ -14400,10 +14802,51 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/eslint-config-prettier": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz",
+ "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==",
+ "dev": true,
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-prettier": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz",
+ "integrity": "sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==",
+ "dev": true,
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0",
+ "synckit": "^0.8.5"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/prettier"
+ },
+ "peerDependencies": {
+ "@types/eslint": ">=8.0.0",
+ "eslint": ">=8.0.0",
+ "prettier": ">=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/eslint": {
+ "optional": true
+ },
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
"node_modules/eslint-plugin-storybook": {
- "version": "0.6.13",
- "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.6.13.tgz",
- "integrity": "sha512-smd+CS0WH1jBqUEJ3znGS7DU4ayBE9z6lkQAK2yrSUv1+rq8BT/tiI5C/rKE7rmiqiAfojtNYZRhzo5HrulccQ==",
+ "version": "0.6.15",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.6.15.tgz",
+ "integrity": "sha512-lAGqVAJGob47Griu29KXYowI4G7KwMoJDOkEip8ujikuDLxU+oWJ1l0WL6F2oDO4QiyUFXvtDkEkISMOPzo+7w==",
"dev": true,
"dependencies": {
"@storybook/csf": "^0.0.1",
@@ -14533,9 +14976,9 @@
}
},
"node_modules/eslint/node_modules/globals": {
- "version": "13.21.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz",
- "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==",
+ "version": "13.23.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
+ "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
"dev": true,
"dependencies": {
"type-fest": "^0.20.2"
@@ -15007,6 +15450,12 @@
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
+ "node_modules/fast-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
+ "dev": true
+ },
"node_modules/fast-glob": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
@@ -15319,9 +15768,9 @@
}
},
"node_modules/flag-icons": {
- "version": "6.11.0",
- "resolved": "https://registry.npmjs.org/flag-icons/-/flag-icons-6.11.0.tgz",
- "integrity": "sha512-oK+QhV5UMWq+lmyOnfXUfVhSgHy29gQ0gQpmORdNP6ucAsKzIGm39ncvyThJyvt76Au2qsepDTE9waHRuaYPUw=="
+ "version": "6.11.2",
+ "resolved": "https://registry.npmjs.org/flag-icons/-/flag-icons-6.11.2.tgz",
+ "integrity": "sha512-xEVPdyDkL28GG0H+x7OP89uFXDgCduNX5DEJ9ZJuxpg3dnDCioBoHfhl4kjC4ixnOnVh7ajL/PNFg7my8qBxtQ=="
},
"node_modules/flat": {
"version": "5.0.2",
@@ -15333,12 +15782,12 @@
}
},
"node_modules/flat-cache": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz",
- "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz",
+ "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==",
"dev": true,
"dependencies": {
- "flatted": "^3.2.7",
+ "flatted": "^3.2.9",
"keyv": "^4.5.3",
"rimraf": "^3.0.2"
},
@@ -15347,24 +15796,24 @@
}
},
"node_modules/flatted": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
- "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
+ "version": "3.2.9",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
+ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
"dev": true
},
"node_modules/flow-parser": {
- "version": "0.216.1",
- "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.216.1.tgz",
- "integrity": "sha512-wstw46/C/8bRv/8RySCl15lK376j8DHxm41xFjD9eVL+jSS1UmVpbdLdA0LzGuS2v5uGgQiBLEj6mgSJQwW+MA==",
+ "version": "0.219.0",
+ "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.219.0.tgz",
+ "integrity": "sha512-f1RKw+2QW4HCwCQ7qw8fTrlWmQnPIHmWDYbrMhXSSAuDbQbncY63I3Y/vwgimChGF2PT4qtXusu04R3wtCh4hw==",
"dev": true,
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/follow-redirects": {
- "version": "1.15.2",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
- "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
+ "version": "1.15.3",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
+ "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==",
"dev": true,
"funding": [
{
@@ -15618,9 +16067,9 @@
}
},
"node_modules/fraction.js": {
- "version": "4.3.6",
- "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.6.tgz",
- "integrity": "sha512-n2aZ9tNfYDwaHhvFTkhFErqOMIb8uyzSQ+vGJBjZyanAKZVbGUQ1sngfk9FdkBw7G26O7AgNjLcecLffD1c7eg==",
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
+ "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
"dev": true,
"engines": {
"node": "*"
@@ -15678,9 +16127,9 @@
}
},
"node_modules/fs-monkey": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz",
- "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz",
+ "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==",
"dev": true
},
"node_modules/fs.realpath": {
@@ -15703,9 +16152,12 @@
}
},
"node_modules/function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
},
"node_modules/functional-red-black-tree": {
"version": "1.0.1",
@@ -15846,23 +16298,48 @@
}
},
"node_modules/giget": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/giget/-/giget-1.1.2.tgz",
- "integrity": "sha512-HsLoS07HiQ5oqvObOI+Qb2tyZH4Gj5nYGfF9qQcZNrPw+uEFhdXtgJr01aO2pWadGHucajYDLxxbtQkm97ON2A==",
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/giget/-/giget-1.1.3.tgz",
+ "integrity": "sha512-zHuCeqtfgqgDwvXlR84UNgnJDuUHQcNI5OqWqFxxuk2BshuKbYhJWdxBsEo4PvKqoGh23lUAIvBNpChMLv7/9Q==",
"dev": true,
"dependencies": {
- "colorette": "^2.0.19",
+ "colorette": "^2.0.20",
"defu": "^6.1.2",
- "https-proxy-agent": "^5.0.1",
+ "https-proxy-agent": "^7.0.2",
"mri": "^1.2.0",
- "node-fetch-native": "^1.0.2",
- "pathe": "^1.1.0",
- "tar": "^6.1.13"
+ "node-fetch-native": "^1.4.0",
+ "pathe": "^1.1.1",
+ "tar": "^6.2.0"
},
"bin": {
"giget": "dist/cli.mjs"
}
},
+ "node_modules/giget/node_modules/agent-base": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz",
+ "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/giget/node_modules/https-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==",
+ "dev": true,
+ "dependencies": {
+ "agent-base": "^7.0.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
"node_modules/github-slugger": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz",
@@ -15870,19 +16347,19 @@
"dev": true
},
"node_modules/glob": {
- "version": "10.3.4",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.4.tgz",
- "integrity": "sha512-6LFElP3A+i/Q8XQKEvZjkEWEOTgAIALR9AO2rwT8bgPhDd1anmqDJDZ6lLddI4ehxxxR1S5RIqKe1uapMQfYaQ==",
+ "version": "10.3.10",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
+ "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
"dev": true,
"dependencies": {
"foreground-child": "^3.1.0",
- "jackspeak": "^2.0.3",
+ "jackspeak": "^2.3.5",
"minimatch": "^9.0.1",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
"path-scurry": "^1.10.1"
},
"bin": {
- "glob": "dist/cjs/src/bin.js"
+ "glob": "dist/esm/bin.mjs"
},
"engines": {
"node": ">=16 || 14 >=14.17"
@@ -16133,12 +16610,9 @@
"dev": true
},
"node_modules/has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dependencies": {
- "function-bind": "^1.1.1"
- },
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz",
+ "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==",
"engines": {
"node": ">= 0.4.0"
}
@@ -16585,9 +17059,9 @@
}
},
"node_modules/i18next": {
- "version": "22.5.1",
- "resolved": "https://registry.npmjs.org/i18next/-/i18next-22.5.1.tgz",
- "integrity": "sha512-8TGPgM3pAD+VRsMtUMNknRz3kzqwp/gPALrWMsDnmC1mKqJwpWyooQRLMcbTwq8z8YwSmuj+ZYvc+xCuEpkssA==",
+ "version": "23.5.1",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.5.1.tgz",
+ "integrity": "sha512-JelYzcaCoFDaa+Ysbfz2JsGAKkrHiMG6S61+HLBUEIPaF40WMwW9hCPymlQGrP+wWawKxKPuSuD71WZscCsWHg==",
"dev": true,
"funding": [
{
@@ -16604,7 +17078,7 @@
}
],
"dependencies": {
- "@babel/runtime": "^7.20.6"
+ "@babel/runtime": "^7.22.5"
}
},
"node_modules/iconv-lite": {
@@ -16866,13 +17340,6 @@
"node": ">=8"
}
},
- "node_modules/inside": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/inside/-/inside-1.0.0.tgz",
- "integrity": "sha512-tvFwvS4g7q6iDot/4FjtWFHwwpv6TVvEumbTdLQilk1F07ojakbXPQcvf3kMAlyNDpzKRzn+d33O3RuXODuxZQ==",
- "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
- "dev": true
- },
"node_modules/internal-slot": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
@@ -17129,6 +17596,39 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-inside-container": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
+ "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
+ "dev": true,
+ "dependencies": {
+ "is-docker": "^3.0.0"
+ },
+ "bin": {
+ "is-inside-container": "cli.js"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-inside-container/node_modules/is-docker": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
+ "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
+ "dev": true,
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/is-installed-globally": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz",
@@ -17566,9 +18066,9 @@
}
},
"node_modules/jackspeak": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.3.tgz",
- "integrity": "sha512-R2bUw+kVZFS/h1AZqBKrSgDmdmjApzgY0AlCPumopFiAlbUxE2gf+SCuBzQ0cP5hHmUmFYF5yw55T97Th5Kstg==",
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
+ "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
"dev": true,
"dependencies": {
"@isaacs/cliui": "^8.0.2"
@@ -18363,9 +18863,9 @@
}
},
"node_modules/katex": {
- "version": "0.16.8",
- "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.8.tgz",
- "integrity": "sha512-ftuDnJbcbOckGY11OO+zg3OofESlbR5DRl2cmN8HeWeeFIV7wTXvAOx8kEjZjobhA+9wh2fbKeO6cdcA9Mnovg==",
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.9.tgz",
+ "integrity": "sha512-fsSYjWS0EEOwvy81j3vRA8TEAhQhKiqO+FQaKWp0m39qwOzHVBgAUBIXWj1pB+O2W3fIpNa6Y9KSKCVbfPhyAQ==",
"funding": [
"https://opencollective.com/katex",
"https://github.com/sponsors/katex"
@@ -18388,27 +18888,27 @@
}
},
"node_modules/keycloak-js": {
- "version": "22.0.3",
- "resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-22.0.3.tgz",
- "integrity": "sha512-QV96sDngWMlJ8Mq5l+A0BNuzZqJT+d8UM9vvGsPXFT+TDfPjXuFjtrpHH26X6YMY3JaCvH2mH9PXb3DGvEkuOw==",
+ "version": "22.0.5",
+ "resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-22.0.5.tgz",
+ "integrity": "sha512-a7ZwCZeHl8tpeJBy102tZtAnHslDUOA1Nf/sHNF3HYLchKpwoDuaitwIUiS2GnNUe+tlNKLlCqZS+Mi5K79m1w==",
"dependencies": {
"base64-js": "^1.5.1",
"js-sha256": "^0.9.0"
}
},
"node_modules/keyv": {
- "version": "4.5.3",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz",
- "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==",
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
"dev": true,
"dependencies": {
"json-buffer": "3.0.1"
}
},
"node_modules/khroma": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.0.0.tgz",
- "integrity": "sha512-2J8rDNlQWbtiNYThZRvmMv5yt44ZakX+Tz5ZIp/mN1pt4snn+m030Va5Z4v8xA0cQFDXBwO/8i42xL4QPsVk3g==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz",
+ "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==",
"optional": true
},
"node_modules/kind-of": {
@@ -18439,13 +18939,13 @@
}
},
"node_modules/launch-editor": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz",
- "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==",
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz",
+ "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==",
"dev": true,
"dependencies": {
"picocolors": "^1.0.0",
- "shell-quote": "^1.7.3"
+ "shell-quote": "^1.8.1"
}
},
"node_modules/layout-base": {
@@ -19177,6 +19677,7 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz",
"integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==",
+ "peer": true,
"bin": {
"marked": "bin/marked.js"
},
@@ -19429,9 +19930,9 @@
}
},
"node_modules/minipass": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz",
- "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==",
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
+ "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
"dev": true,
"engines": {
"node": ">=16 || 14 >=14.17"
@@ -20165,9 +20666,9 @@
}
},
"node_modules/npm-install-checks": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.2.0.tgz",
- "integrity": "sha512-744wat5wAAHsxa4590mWO0tJ8PKxR8ORZsH9wGpQc3nWTzozMAgBN/XyqYw7mg3yqLM8dLwEnwSfKMmXAjF69g==",
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz",
+ "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==",
"dev": true,
"dependencies": {
"semver": "^7.1.1"
@@ -20557,9 +21058,9 @@
}
},
"node_modules/object-inspect": {
- "version": "1.12.3",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
- "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.0.tgz",
+ "integrity": "sha512-HQ4J+ic8hKrgIt3mqk6cVOVrW2ozL4KdvHlqpBv9vDYWx9ysAgENAdvy4FoGF+KFdhR7nQTNm5J0ctAeOwn+3g==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -21304,9 +21805,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.27",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz",
- "integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==",
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"dev": true,
"funding": [
{
@@ -21685,6 +22186,18 @@
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/pretty-bytes": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
@@ -22513,9 +23026,9 @@
"dev": true
},
"node_modules/regenerate-unicode-properties": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz",
- "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==",
+ "version": "10.1.1",
+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz",
+ "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==",
"dev": true,
"dependencies": {
"regenerate": "^1.4.2"
@@ -23033,9 +23546,9 @@
"optional": true
},
"node_modules/rollup": {
- "version": "3.29.1",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.1.tgz",
- "integrity": "sha512-c+ebvQz0VIH4KhhCpDsI+Bik0eT8ZFEVZEYw0cGMVqIP8zc+gnwl7iXCamTw7vzv2MeuZFZfdx5JJIq+ehzDlg==",
+ "version": "3.29.4",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz",
+ "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==",
"dev": true,
"bin": {
"rollup": "dist/bin/rollup"
@@ -23048,6 +23561,21 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/run-applescript": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz",
+ "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==",
+ "dev": true,
+ "dependencies": {
+ "execa": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/run-async": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
@@ -23164,9 +23692,9 @@
}
},
"node_modules/sax": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
- "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz",
+ "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==",
"dev": true
},
"node_modules/saxes": {
@@ -23343,34 +23871,6 @@
"randombytes": "^2.1.0"
}
},
- "node_modules/serve-favicon": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz",
- "integrity": "sha512-FMW2RvqNr03x+C0WxTyu6sOv21oOjkq5j8tjquWccwa6ScNyGFOGJVpuS1NmTVGBAHS07xnSKotgf2ehQmf9iA==",
- "dev": true,
- "dependencies": {
- "etag": "~1.8.1",
- "fresh": "0.5.2",
- "ms": "2.1.1",
- "parseurl": "~1.3.2",
- "safe-buffer": "5.1.1"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/serve-favicon/node_modules/ms": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
- "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
- "dev": true
- },
- "node_modules/serve-favicon/node_modules/safe-buffer": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
- "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
- "dev": true
- },
"node_modules/serve-index": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
@@ -23869,9 +24369,9 @@
}
},
"node_modules/spdx-license-ids": {
- "version": "3.0.13",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz",
- "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==",
+ "version": "3.0.16",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz",
+ "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==",
"dev": true
},
"node_modules/spdy": {
@@ -24241,12 +24741,12 @@
"dev": true
},
"node_modules/storybook": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/storybook/-/storybook-7.4.1.tgz",
- "integrity": "sha512-b90jq0CYqBMl2JAbC1lInGAoadkPkeGg4Vh8C9Bv7dGhl6M9uei3yEMQTDrj3HvCsktdeZqztGfrkGs2scK+LA==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/storybook/-/storybook-7.5.0.tgz",
+ "integrity": "sha512-dmvQNSuoHq1KrPcK8siApBi5n5reSf6RFAlLHYD+nhM+EP6SL2fXdVjP6ZynTUMRu1NQ5YR/oJhz/SsBzJNkcA==",
"dev": true,
"dependencies": {
- "@storybook/cli": "7.4.1"
+ "@storybook/cli": "7.5.0"
},
"bin": {
"sb": "index.js",
@@ -24561,6 +25061,22 @@
"integrity": "sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g==",
"dev": true
},
+ "node_modules/synckit": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz",
+ "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==",
+ "dev": true,
+ "dependencies": {
+ "@pkgr/utils": "^2.3.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
"node_modules/tapable": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
@@ -25015,6 +25531,18 @@
"integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==",
"dev": true
},
+ "node_modules/titleize": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz",
+ "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/tmp": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
@@ -25053,9 +25581,9 @@
}
},
"node_modules/tocbot": {
- "version": "4.21.1",
- "resolved": "https://registry.npmjs.org/tocbot/-/tocbot-4.21.1.tgz",
- "integrity": "sha512-IfajhBTeg0HlMXu1f+VMbPef05QpDTsZ9X2Yn1+8npdaXsXg/+wrm9Ze1WG5OS1UDC3qJ5EQN/XOZ3gfXjPFCw==",
+ "version": "4.21.2",
+ "resolved": "https://registry.npmjs.org/tocbot/-/tocbot-4.21.2.tgz",
+ "integrity": "sha512-R5Muhi/TUu4i4snWVrMgNoXyJm2f8sJfdgIkQvqb+cuIXQEIMAiWGWgCgYXHqX4+XiS/Bnm7IYZ9Zy6NVe6lhw==",
"dev": true
},
"node_modules/toidentifier": {
@@ -25147,12 +25675,12 @@
}
},
"node_modules/ts-morph": {
- "version": "18.0.0",
- "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-18.0.0.tgz",
- "integrity": "sha512-Kg5u0mk19PIIe4islUI/HWRvm9bC1lHejK4S0oh1zaZ77TMZAEmQC0sHQYiu2RgCQFZKXz1fMVi/7nOOeirznA==",
+ "version": "20.0.0",
+ "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-20.0.0.tgz",
+ "integrity": "sha512-JVmEJy2Wow5n/84I3igthL9sudQ8qzjh/6i4tmYCm6IqYyKFlNbJZi7oBdjyqcWSWYRu3CtL0xbT6fS03ESZIg==",
"dev": true,
"dependencies": {
- "@ts-morph/common": "~0.19.0",
+ "@ts-morph/common": "~0.21.0",
"code-block-writer": "^12.0.0"
}
},
@@ -25449,6 +25977,11 @@
"node": ">=0.8.0"
}
},
+ "node_modules/undici-types": {
+ "version": "5.25.3",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz",
+ "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA=="
+ },
"node_modules/unicode-canonical-property-names-ecmascript": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
@@ -25609,12 +26142,12 @@
}
},
"node_modules/unplugin": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.4.0.tgz",
- "integrity": "sha512-5x4eIEL6WgbzqGtF9UV8VEC/ehKptPXDS6L2b0mv4FRMkJxRtjaJfOWDd6a8+kYbqsjklix7yWP0N3SUepjXcg==",
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.5.0.tgz",
+ "integrity": "sha512-9ZdRwbh/4gcm1JTOkp9lAkIDrtOyOxgHmY7cjuwI8L/2RTikMcVG25GsZwNAgRuap3iDw2jeq7eoqtAsz5rW3A==",
"dev": true,
"dependencies": {
- "acorn": "^8.9.0",
+ "acorn": "^8.10.0",
"chokidar": "^3.5.3",
"webpack-sources": "^3.2.3",
"webpack-virtual-modules": "^0.5.0"
@@ -25630,9 +26163,9 @@
}
},
"node_modules/update-browserslist-db": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",
- "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==",
+ "version": "1.0.13",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
+ "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
"funding": [
{
"type": "opencollective",
@@ -25667,9 +26200,9 @@
}
},
"node_modules/url": {
- "version": "0.11.2",
- "resolved": "https://registry.npmjs.org/url/-/url-0.11.2.tgz",
- "integrity": "sha512-7yIgNnrST44S7PJ5+jXbdIupfU1nWUdQJBFBeJRclPXiWgCvrSq5Frw8lr/i//n5sqDfzoKmBymMS81l4U/7cg==",
+ "version": "0.11.3",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz",
+ "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==",
"dev": true,
"dependencies": {
"punycode": "^1.4.1",
@@ -26573,9 +27106,9 @@
}
},
"node_modules/ws": {
- "version": "8.14.1",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.1.tgz",
- "integrity": "sha512-4OOseMUq8AzRBI/7SLMUwO+FEDnguetSk7KMb1sHwvF2w2Wv5Hoj0nlifx8vtGsftE/jWHojPy8sMMzYLJ2G/A==",
+ "version": "8.14.2",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz",
+ "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==",
"dev": true,
"engines": {
"node": ">=10.0.0"
@@ -26667,9 +27200,9 @@
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
},
"node_modules/yaml": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz",
- "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==",
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz",
+ "integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==",
"dev": true,
"engines": {
"node": ">= 14"
diff --git a/package.json b/package.json
index af9ad8b5b3..9aaaf0368d 100644
--- a/package.json
+++ b/package.json
@@ -21,14 +21,14 @@
"private": true,
"dependencies": {
"@angular/animations": "^16.2.1",
- "@angular/cdk": "^16.2.1",
+ "@angular/cdk": "^16.2.10",
"@angular/common": "^16.2.1",
"@angular/compiler": "^16.2.1",
"@angular/core": "^16.2.1",
"@angular/forms": "^16.2.1",
"@angular/localize": "^16.2.1",
- "@angular/material": "^16.2.1",
- "@angular/material-moment-adapter": "^16.2.1",
+ "@angular/material": "^16.2.10",
+ "@angular/material-moment-adapter": "^16.2.10",
"@angular/platform-browser": "^16.2.1",
"@angular/platform-browser-dynamic": "^16.2.1",
"@angular/router": "^16.2.1",
@@ -42,15 +42,15 @@
"@fortawesome/free-regular-svg-icons": "^6.4.2",
"@fortawesome/free-solid-svg-icons": "^6.4.2",
"@ngneat/until-destroy": "^10.0.0",
- "@sentry/browser": "^7.64.0",
+ "@sentry/browser": "^7.76.0",
"angulartics2": "^12.2.1",
"assert": "^2.0.0",
- "crypto-es": "^2.0.4",
+ "crypto-es": "^2.1.0",
"deep-object-diff": "^1.1.9",
- "flag-icons": "^6.10.0",
+ "flag-icons": "^6.11.2",
"hammerjs": "^2.0.8",
"json-query": "^2.2.2",
- "keycloak-js": "^22.0.1",
+ "keycloak-js": "^22.0.5",
"leaflet": "^1.9.4",
"lodash-es": "^4.17.21",
"md5": "^2.3.0",
@@ -102,6 +102,8 @@
"babel-loader": "^9.1.3",
"cypress": "13.1.0",
"eslint": "^8.47.0",
+ "eslint-config-prettier": "^9.0.0",
+ "eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-storybook": "^0.6.13",
"jasmine-core": "^5.1.0",
"jasmine-spec-reporter": "^7.0.0",
diff --git a/src/app/child-dev-project/attendance/activities-overview/activities-overview.component.html b/src/app/child-dev-project/attendance/activities-overview/activities-overview.component.html
deleted file mode 100644
index 0cb187e2f0..0000000000
--- a/src/app/child-dev-project/attendance/activities-overview/activities-overview.component.html
+++ /dev/null
@@ -1,6 +0,0 @@
-
diff --git a/src/app/child-dev-project/attendance/activities-overview/activities-overview.component.spec.ts b/src/app/child-dev-project/attendance/activities-overview/activities-overview.component.spec.ts
deleted file mode 100644
index c5881318bb..0000000000
--- a/src/app/child-dev-project/attendance/activities-overview/activities-overview.component.spec.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-import {
- ComponentFixture,
- fakeAsync,
- TestBed,
- tick,
- waitForAsync,
-} from "@angular/core/testing";
-import { RecurringActivity } from "../model/recurring-activity";
-import { EntityMapperService } from "../../../core/entity/entity-mapper/entity-mapper.service";
-import {
- mockEntityMapper,
- MockEntityMapperService,
-} from "../../../core/entity/entity-mapper/mock-entity-mapper-service";
-import { UpdatedEntity } from "../../../core/entity/model/entity-update";
-import { Subject } from "rxjs";
-import { School } from "../../schools/model/school";
-
-import { ActivitiesOverviewComponent } from "./activities-overview.component";
-import { MockedTestingModule } from "../../../utils/mocked-testing.module";
-import { FormDialogService } from "../../../core/form-dialog/form-dialog.service";
-
-describe("ActivitiesOverviewComponent", () => {
- let component: ActivitiesOverviewComponent;
- let fixture: ComponentFixture;
-
- let entityMapper: MockEntityMapperService;
-
- beforeEach(waitForAsync(() => {
- entityMapper = mockEntityMapper();
- TestBed.configureTestingModule({
- imports: [ActivitiesOverviewComponent, MockedTestingModule.withState()],
- providers: [
- { provide: EntityMapperService, useValue: entityMapper },
- { provide: FormDialogService, useValue: null },
- ],
- }).compileComponents();
- }));
-
- beforeEach(() => {
- fixture = TestBed.createComponent(ActivitiesOverviewComponent);
- component = fixture.componentInstance;
- component.entity = new School();
- fixture.detectChanges();
- });
-
- it("should create", () => {
- expect(component).toBeTruthy();
- });
-
- it("should fetch all and only recurring activities having the selected school as a linkedGroup", async () => {
- const school1 = new School("school1");
- const activity1 = new RecurringActivity();
- activity1.linkedGroups = ["school1"];
- const activity2 = new RecurringActivity();
- activity2.linkedGroups = ["school1", "school2"];
- const activity3 = new RecurringActivity();
- activity3.linkedGroups = ["school3"];
- entityMapper.addAll([activity1, activity2, activity3]);
-
- component.entity = school1;
- await component.ngOnInit();
- expect(component.records).toEqual([activity1, activity2]);
- });
-
- it("should create a new recurring activity having the current school as a linkedGroup", () => {
- component.entity = new School("school1");
- const newRecurringActivity = component.generateNewRecordFactory();
- expect(newRecurringActivity().linkedGroups).toEqual(["school1"]);
- });
-
- it("should remove the recurring activity from the table view if the current school is removed as a group of this recurring activity", fakeAsync(() => {
- const school1 = new School("school1");
- const activity1 = new RecurringActivity();
- activity1.linkedGroups = ["school1"];
- const activity2 = new RecurringActivity();
- activity2.linkedGroups = ["school1", "school2", "school3"];
- entityMapper.addAll([activity1, activity2]);
- const subject = new Subject>();
- spyOn(entityMapper, "receiveUpdates").and.returnValue(subject);
- component.entity = school1;
- component.ngOnInit();
- tick();
-
- expect(component.records).toEqual([activity1, activity2]);
-
- activity2.linkedGroups = ["school2", "school3"];
- subject.next({ entity: activity2, type: "update" });
- tick();
-
- expect(component.records).toEqual([activity1]);
- }));
-});
diff --git a/src/app/child-dev-project/attendance/activities-overview/activities-overview.component.ts b/src/app/child-dev-project/attendance/activities-overview/activities-overview.component.ts
index e67e89f7e3..4d5e5e6e0d 100644
--- a/src/app/child-dev-project/attendance/activities-overview/activities-overview.component.ts
+++ b/src/app/child-dev-project/attendance/activities-overview/activities-overview.component.ts
@@ -1,23 +1,28 @@
-import { Component, Input, OnInit } from "@angular/core";
+import { Component, OnInit } from "@angular/core";
import { RecurringActivity } from "../model/recurring-activity";
-import { FormFieldConfig } from "../../../core/common-components/entity-form/entity-form/FormConfig";
-import { EntityMapperService } from "../../../core/entity/entity-mapper/entity-mapper.service";
-import { Entity } from "../../../core/entity/model/entity";
import { DynamicComponent } from "../../../core/config/dynamic-components/dynamic-component.decorator";
-import { delay } from "rxjs";
+import { RelatedEntitiesComponent } from "../../../core/entity-details/related-entities/related-entities.component";
import { EntitySubrecordComponent } from "../../../core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component";
-import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
+import { ColumnConfig } from "../../../core/common-components/entity-subrecord/entity-subrecord/entity-subrecord-config";
-@UntilDestroy()
+/**
+ * @deprecated configure a RelatedEntitiesComponent instead
+ */
@DynamicComponent("ActivitiesOverview")
@Component({
selector: "app-activities-overview",
- templateUrl: "./activities-overview.component.html",
- styleUrls: ["./activities-overview.component.scss"],
+ templateUrl:
+ "../../../core/entity-details/related-entities/related-entities.component.html",
imports: [EntitySubrecordComponent],
standalone: true,
})
-export class ActivitiesOverviewComponent implements OnInit {
+export class ActivitiesOverviewComponent
+ extends RelatedEntitiesComponent
+ implements OnInit
+{
+ entityType = RecurringActivity.ENTITY_TYPE;
+ property = "linkedGroups";
+
titleColumn = {
id: "title",
edit: "EditTextWithAutocomplete",
@@ -27,49 +32,16 @@ export class ActivitiesOverviewComponent implements OnInit {
relevantValue: "",
},
};
- @Input() columns: FormFieldConfig[] = [
+ _columns: ColumnConfig[] = [
this.titleColumn,
- { id: "type" },
- { id: "assignedTo" },
- { id: "linkedGroups" },
- { id: "excludedParticipants" },
+ "type",
+ "assignedTo",
+ "linkedGroups",
+ "excludedParticipants",
];
- @Input() entity: Entity;
- records: RecurringActivity[] = [];
-
- constructor(private entityMapper: EntityMapperService) {}
-
async ngOnInit() {
this.titleColumn.additional.relevantValue = this.entity.getId();
- await this.initLinkedActivities();
-
- this.entityMapper
- .receiveUpdates(RecurringActivity)
- // using short delay to make sure the EntitySubrecord's `receiveUpdates` code is executed before this
- .pipe(delay(0), untilDestroyed(this))
- .subscribe((updateEntity) => {
- if (updateEntity.type === "update") {
- this.initLinkedActivities();
- }
- });
- }
-
- private async initLinkedActivities() {
- this.records = await this.entityMapper
- .loadType(RecurringActivity)
- .then((activities) =>
- activities.filter((activity) =>
- activity.linkedGroups.includes(this.entity.getId()),
- ),
- );
- }
-
- generateNewRecordFactory(): () => RecurringActivity {
- return () => {
- const newRecurringActivity = new RecurringActivity();
- newRecurringActivity.linkedGroups.push(this.entity.getId());
- return newRecurringActivity;
- };
+ await super.ngOnInit();
}
}
diff --git a/src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.html b/src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.html
index de9808bda5..07fc624d8c 100644
--- a/src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.html
+++ b/src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.html
@@ -29,7 +29,7 @@ {{ event.subject }}
diff --git a/src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts b/src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
index ad53d635fc..f465cc1a85 100644
--- a/src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
+++ b/src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
@@ -1,11 +1,9 @@
-import { Component, ViewChild } from "@angular/core";
+import { Component, Input, ViewChild } from "@angular/core";
import { EntityMapperService } from "../../../core/entity/entity-mapper/entity-mapper.service";
import { Note } from "../../notes/model/note";
import { ConfirmationDialogService } from "../../../core/common-components/confirmation-dialog/confirmation-dialog.service";
import { ConfirmationDialogButton } from "../../../core/common-components/confirmation-dialog/confirmation-dialog/confirmation-dialog.component";
import { RollCallComponent } from "./roll-call/roll-call.component";
-import { ActivatedRoute } from "@angular/router";
-import { RouteData } from "../../../core/config/dynamic-routing/view-config.interface";
import { RouteTarget } from "../../../app.routing";
import { NgIf } from "@angular/common";
import { MatButtonModule } from "@angular/material/button";
@@ -14,14 +12,6 @@ import { MatTooltipModule } from "@angular/material/tooltip";
import { RollCallSetupComponent } from "./roll-call-setup/roll-call-setup.component";
import { ViewTitleComponent } from "../../../core/common-components/view-title/view-title.component";
-/**
- * additional config specifically for AddDayAttendanceComponent
- */
-export interface AddDayAttendanceConfig {
- /** (optional) property name of the participant entities by which they are sorted for the roll call */
- sortParticipantsBy?: string;
-}
-
@RouteTarget("AddDayAttendance")
@Component({
selector: "app-add-day-attendance",
@@ -39,7 +29,8 @@ export interface AddDayAttendanceConfig {
standalone: true,
})
export class AddDayAttendanceComponent {
- config?: AddDayAttendanceConfig;
+ /** (optional) property name of the participant entities by which they are sorted for the roll call */
+ @Input() sortParticipantsBy: string;
currentStage = 0;
@@ -75,13 +66,8 @@ export class AddDayAttendanceComponent {
constructor(
private entityMapper: EntityMapperService,
- private route: ActivatedRoute,
private confirmationDialog: ConfirmationDialogService,
- ) {
- this.route.data.subscribe((data: RouteData) => {
- this.config = data.config;
- });
- }
+ ) {}
finishBasicInformationStage(event: Note) {
this.event = event;
diff --git a/src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html b/src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
index 8a9617e58d..ecdd75d394 100644
--- a/src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
+++ b/src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
@@ -5,7 +5,7 @@
[value]="(currentIndex / children.length) * 100"
>
-
+
{{ currentIndex + 1 }} / {{ children.length }}
-
+
+
+
0" style="margin-right: -10px">
+
+
+
+
{
let component: AttendanceWeekDashboardComponent;
@@ -90,28 +91,38 @@ describe("AttendanceWeekDashboardComponent", () => {
]);
});
- it("should correctly use the offset", () => {
- // default case: last week monday till saturday
- const mondayLastWeek = moment().startOf("isoWeek").subtract(7, "days");
- const saturdayLastWeek = mondayLastWeek.clone().add("5", "days");
+ function expectTimePeriodCalled(from: moment.Moment, to: moment.Moment) {
mockAttendanceService.getAllActivityAttendancesForPeriod.calls.reset();
component.ngOnInit();
expect(
mockAttendanceService.getAllActivityAttendancesForPeriod,
- ).toHaveBeenCalledWith(mondayLastWeek.toDate(), saturdayLastWeek.toDate());
+ ).toHaveBeenCalledWith(from.toDate(), to.toDate());
+ }
- // with offset: this week monday till saturday
- const mondayThisWeek = moment().startOf("isoWeek");
- const saturdayThisWeek = mondayThisWeek.clone().add(5, "days");
- mockAttendanceService.getAllActivityAttendancesForPeriod.calls.reset();
+ it("should correctly use the offset", () => {
+ // default case: last week monday till saturday
+ // on Monday, that's the first day of the current period
+ MockDate.set(moment("2023-11-20").toDate());
+ const mondayLastWeek = moment("2023-11-13");
+ const saturdayLastWeek = moment("2023-11-18");
+ expectTimePeriodCalled(mondayLastWeek, saturdayLastWeek);
+
+ // on Sunday, that's the still the last day of the currently ending period
+ MockDate.set(moment("2023-11-26").toDate());
+ const mondayLastWeek2 = moment("2023-11-13");
+ const saturdayLastWeek2 = moment("2023-11-18");
+ expectTimePeriodCalled(mondayLastWeek2, saturdayLastWeek2);
+
+ // with offset: this week monday till saturday
+ MockDate.set(moment("2023-11-20").toDate());
+ const mondayThisWeek = moment("2023-11-20");
+ const saturdayThisWeek = moment("2023-11-25");
component.daysOffset = 7;
- component.ngOnInit();
+ expectTimePeriodCalled(mondayThisWeek, saturdayThisWeek);
- expect(
- mockAttendanceService.getAllActivityAttendancesForPeriod,
- ).toHaveBeenCalledWith(mondayThisWeek.toDate(), saturdayThisWeek.toDate());
+ MockDate.reset();
});
});
diff --git a/src/app/child-dev-project/attendance/dashboard-widgets/attendance-week-dashboard/attendance-week-dashboard.component.ts b/src/app/child-dev-project/attendance/dashboard-widgets/attendance-week-dashboard/attendance-week-dashboard.component.ts
index be585ee430..2b1db14b1f 100644
--- a/src/app/child-dev-project/attendance/dashboard-widgets/attendance-week-dashboard/attendance-week-dashboard.component.ts
+++ b/src/app/child-dev-project/attendance/dashboard-widgets/attendance-week-dashboard/attendance-week-dashboard.component.ts
@@ -99,22 +99,16 @@ export class AttendanceWeekDashboardComponent implements OnInit, AfterViewInit {
}
private async loadAttendanceOfAbsentees() {
- const today = new Date();
- const previousMonday = new Date(
- today.getFullYear(),
- today.getMonth(),
- today.getDate() - today.getDay() - 6 + this.daysOffset,
- );
- const previousSaturday = new Date(
- previousMonday.getFullYear(),
- previousMonday.getMonth(),
- previousMonday.getDate() + 5,
- );
+ const previousMonday = moment()
+ .startOf("isoWeek")
+ .subtract(1, "week")
+ .add(this.daysOffset, "days");
+ const previousSaturday = moment(previousMonday).add(5, "days");
const activityAttendances =
await this.attendanceService.getAllActivityAttendancesForPeriod(
- previousMonday,
- previousSaturday,
+ previousMonday.toDate(),
+ previousSaturday.toDate(),
);
const lowAttendanceCases = new Set();
const records: AttendanceWeekRow[] = [];
diff --git a/src/app/child-dev-project/attendance/edit-attendance/edit-attendance.component.spec.ts b/src/app/child-dev-project/attendance/edit-attendance/edit-attendance.component.spec.ts
index 069ca990ce..bee7d4c417 100644
--- a/src/app/child-dev-project/attendance/edit-attendance/edit-attendance.component.spec.ts
+++ b/src/app/child-dev-project/attendance/edit-attendance/edit-attendance.component.spec.ts
@@ -85,9 +85,10 @@ describe("EditAttendanceComponent", () => {
categoryForm.setValue(defaultInteractionTypes.find((c) => c.isMeeting));
fixture.detectChanges();
- const inputElements = await TestbedHarnessEnvironment.loader(
- fixture,
- ).getAllHarnesses(MatInputHarness);
+ const inputElements =
+ await TestbedHarnessEnvironment.loader(fixture).getAllHarnesses(
+ MatInputHarness,
+ );
const firstRemarkInput = inputElements[1];
await firstRemarkInput.setValue("new remarks");
diff --git a/src/app/child-dev-project/attendance/edit-attendance/edit-attendance.component.ts b/src/app/child-dev-project/attendance/edit-attendance/edit-attendance.component.ts
index 7fe25e7f1a..58ba70a4c3 100644
--- a/src/app/child-dev-project/attendance/edit-attendance/edit-attendance.component.ts
+++ b/src/app/child-dev-project/attendance/edit-attendance/edit-attendance.component.ts
@@ -90,12 +90,13 @@ export class EditAttendanceComponent
const index = children.indexOf(id);
children.splice(index, 1);
this.attendanceForm.value.delete(id);
- this.formControl.setValue([...children]);
this.formControl.markAsDirty();
+ this.formControl.setValue([...children]);
}
updateAttendanceValue(childId, property: "status" | "remarks", newValue) {
- this.getAttendance(childId)[property] = newValue;
this.formControl.markAsDirty();
+ this.getAttendance(childId)[property] = newValue;
+ this.attendanceForm.setValue(this.attendanceForm.value);
}
}
diff --git a/src/app/child-dev-project/children/aser/model/aser.ts b/src/app/child-dev-project/children/aser/model/aser.ts
index 045bf2b32d..19ecb55a87 100644
--- a/src/app/child-dev-project/children/aser/model/aser.ts
+++ b/src/app/child-dev-project/children/aser/model/aser.ts
@@ -22,15 +22,26 @@ import { SkillLevel } from "./skill-levels";
import { WarningLevel } from "../../../warning-level";
import { ConfigurableEnumDatatype } from "../../../../core/basic-datatypes/configurable-enum/configurable-enum-datatype/configurable-enum.datatype";
import { PLACEHOLDERS } from "../../../../core/entity/schema/entity-schema-field";
+import { Child } from "../../model/child";
@DatabaseEntity("Aser")
export class Aser extends Entity {
- @DatabaseField() child: string; // id of Child entity
+ static override hasPII = true;
+
+ @DatabaseField({
+ dataType: "entity",
+ additional: Child.ENTITY_TYPE,
+ entityReferenceRole: "composite",
+ })
+ child: string;
+
@DatabaseField({
label: $localize`:Label for date of the ASER results:Date`,
defaultValue: PLACEHOLDERS.NOW,
+ anonymize: "retain-anonymized",
})
date: Date;
+
@DatabaseField({
label: $localize`:Label of the Hindi ASER result:Hindi`,
dataType: "configurable-enum",
@@ -55,6 +66,7 @@ export class Aser extends Entity {
innerDataType: "math-levels",
})
math: SkillLevel;
+
@DatabaseField({
label: $localize`:Label for the remarks of a ASER result:Remarks`,
})
diff --git a/src/app/child-dev-project/children/child-block/child-block.component.html b/src/app/child-dev-project/children/child-block/child-block.component.html
index 8b3c1815f1..a5e2166e74 100644
--- a/src/app/child-dev-project/children/child-block/child-block.component.html
+++ b/src/app/child-dev-project/children/child-block/child-block.component.html
@@ -5,9 +5,16 @@
[class.inactive]="!entity.isActive"
class="truncate-text container"
>
-
+
{{ entity?.toString() }}
- ({{ entity?.projectNumber }})
+
+ ({{ entity?.projectNumber }})
diff --git a/src/app/child-dev-project/children/children-components.ts b/src/app/child-dev-project/children/children-components.ts
index 569caea244..c39c2287e0 100644
--- a/src/app/child-dev-project/children/children-components.ts
+++ b/src/app/child-dev-project/children/children-components.ts
@@ -44,13 +44,6 @@ export const childrenComponents: ComponentTuple[] = [
"./health-checkup/children-bmi-dashboard/children-bmi-dashboard.component"
).then((c) => c.ChildrenBmiDashboardComponent),
],
- [
- "RelatedEntitiesWithSummary",
- () =>
- import(
- "../../core/entity-details/related-entities-with-summary/related-entities-with-summary.component"
- ).then((c) => c.RelatedEntitiesWithSummaryComponent),
- ],
[
"BmiBlock",
() =>
diff --git a/src/app/child-dev-project/children/children-list/children-list.component.spec.ts b/src/app/child-dev-project/children/children-list/children-list.component.spec.ts
index 97b121db14..5153552570 100644
--- a/src/app/child-dev-project/children/children-list/children-list.component.spec.ts
+++ b/src/app/child-dev-project/children/children-list/children-list.component.spec.ts
@@ -17,7 +17,6 @@ describe("ChildrenListComponent", () => {
let fixture: ComponentFixture;
const routeData: EntityListConfig = {
title: "Children List",
- filterPlaceholder: "e.g. participant name",
columns: [
{ view: "DisplayText", label: "PN", id: "projectNumber" },
{ view: "ChildBlock", label: "Name", id: "name" },
diff --git a/src/app/child-dev-project/children/children-list/children-list.component.ts b/src/app/child-dev-project/children/children-list/children-list.component.ts
index f692d2d3f4..03fd7dc774 100644
--- a/src/app/child-dev-project/children/children-list/children-list.component.ts
+++ b/src/app/child-dev-project/children/children-list/children-list.component.ts
@@ -34,6 +34,8 @@ export class ChildrenListComponent implements OnInit {
async ngOnInit() {
this.route.data.subscribe(
+ // TODO replace this use of route and rely on the RoutedViewComponent instead
+ // see that flattens the config option, assigning individual properties as inputs however, so we can't easily pass on
(data: RouteData) => (this.listConfig = data.config),
);
this.childrenList = await this.childrenService.getChildren();
diff --git a/src/app/child-dev-project/children/children.service.spec.ts b/src/app/child-dev-project/children/children.service.spec.ts
index 371750d700..09e60059ce 100644
--- a/src/app/child-dev-project/children/children.service.spec.ts
+++ b/src/app/child-dev-project/children/children.service.spec.ts
@@ -11,7 +11,7 @@ import { genders } from "./model/genders";
import { DatabaseTestingModule } from "../../utils/database-testing.module";
import { sortByAttribute } from "../../utils/utils";
import { expectEntitiesToMatch } from "../../utils/expect-entity-data.spec";
-import { DateWithAge } from "./model/dateWithAge";
+import { DateWithAge } from "../../core/basic-datatypes/date-with-age/dateWithAge";
describe("ChildrenService", () => {
let service: ChildrenService;
diff --git a/src/app/child-dev-project/children/demo-data-generators/demo-child-generator.service.ts b/src/app/child-dev-project/children/demo-data-generators/demo-child-generator.service.ts
index 522bd4e305..f10e8d1a66 100644
--- a/src/app/child-dev-project/children/demo-data-generators/demo-child-generator.service.ts
+++ b/src/app/child-dev-project/children/demo-data-generators/demo-child-generator.service.ts
@@ -8,7 +8,7 @@ import { faker } from "../../../core/demo-data/faker";
import { centersWithProbability } from "./fixtures/centers";
import { genders } from "../model/genders";
import { calculateAge } from "../../../utils/utils";
-import { DateWithAge } from "../model/dateWithAge";
+import { DateWithAge } from "../../../core/basic-datatypes/date-with-age/dateWithAge";
export class DemoChildConfig {
count: number;
diff --git a/src/app/child-dev-project/children/health-checkup/model/health-check.ts b/src/app/child-dev-project/children/health-checkup/model/health-check.ts
index 56e639a030..b8ad26bcca 100644
--- a/src/app/child-dev-project/children/health-checkup/model/health-check.ts
+++ b/src/app/child-dev-project/children/health-checkup/model/health-check.ts
@@ -19,6 +19,7 @@ import { Entity } from "../../../../core/entity/model/entity";
import { DatabaseEntity } from "../../../../core/entity/database-entity.decorator";
import { DatabaseField } from "../../../../core/entity/database-field.decorator";
import { WarningLevel } from "../../../warning-level";
+import { Child } from "../../model/child";
/**
* Model Class for the Health Checks that are taken for a Child.
@@ -26,12 +27,24 @@ import { WarningLevel } from "../../../warning-level";
*/
@DatabaseEntity("HealthCheck")
export class HealthCheck extends Entity {
+ static override hasPII = true;
+
static create(contents: Partial) {
return Object.assign(new HealthCheck(), contents);
}
- @DatabaseField() child: string;
- @DatabaseField({ label: $localize`:Label for date of a health check:Date` })
+ @DatabaseField({
+ dataType: "entity",
+ additional: Child.ENTITY_TYPE,
+ entityReferenceRole: "composite",
+ anonymize: "retain",
+ })
+ child: string;
+
+ @DatabaseField({
+ label: $localize`:Label for date of a health check:Date`,
+ anonymize: "retain-anonymized",
+ })
date: Date;
/** height measurement in cm **/
diff --git a/src/app/child-dev-project/children/model/child.spec.ts b/src/app/child-dev-project/children/model/child.spec.ts
index ab4f350743..6f35d39f6f 100644
--- a/src/app/child-dev-project/children/model/child.spec.ts
+++ b/src/app/child-dev-project/children/model/child.spec.ts
@@ -57,5 +57,13 @@ describe("Child", () => {
const testEntity3 = new Child();
testEntity3["status"] = "Dropout";
expect(testEntity3.isActive).withContext("Dropout").toBeFalse();
+
+ // always give "inactive" precedence over other logic (as it is trigger in UI)
+ const testEntityPrec = new Child();
+ testEntityPrec["inactive"] = false;
+ testEntityPrec["status"] = "Dropout";
+ expect(testEntityPrec.isActive)
+ .withContext("inactive taking precedence")
+ .toBeTrue();
});
});
diff --git a/src/app/child-dev-project/children/model/child.ts b/src/app/child-dev-project/children/model/child.ts
index 79f8fe2fad..4cd743f56c 100644
--- a/src/app/child-dev-project/children/model/child.ts
+++ b/src/app/child-dev-project/children/model/child.ts
@@ -19,8 +19,8 @@ import { Entity } from "../../../core/entity/model/entity";
import { DatabaseEntity } from "../../../core/entity/database-entity.decorator";
import { DatabaseField } from "../../../core/entity/database-field.decorator";
import { ConfigurableEnumValue } from "../../../core/basic-datatypes/configurable-enum/configurable-enum.interface";
-import { DateWithAge } from "./dateWithAge";
import { IconName } from "@fortawesome/fontawesome-svg-core";
+import { DateWithAge } from "../../../core/basic-datatypes/date-with-age/dateWithAge";
export type Center = ConfigurableEnumValue;
@@ -31,6 +31,7 @@ export class Child extends Entity {
static label = $localize`:label for entity:Participant`;
static labelPlural = $localize`:label (plural) for entity:Participants`;
static color = "#1565C0";
+ static override hasPII = true;
static create(name: string): Child {
const instance = new Child();
@@ -54,12 +55,14 @@ export class Child extends Entity {
label: $localize`:Label for the project number of a child:Project Number`,
labelShort: $localize`:Short label for the project number:PN`,
searchable: true,
+ anonymize: "retain",
})
projectNumber: string;
@DatabaseField({
label: $localize`:Label for the date of birth of a child:Date of birth`,
labelShort: $localize`:Short label for the date of birth:DoB`,
+ anonymize: "retain-anonymized",
})
dateOfBirth: DateWithAge;
@@ -67,6 +70,7 @@ export class Child extends Entity {
dataType: "configurable-enum",
label: $localize`:Label for the gender of a child:Gender`,
innerDataType: "genders",
+ anonymize: "retain",
})
gender: ConfigurableEnumValue;
@@ -74,11 +78,13 @@ export class Child extends Entity {
dataType: "configurable-enum",
innerDataType: "center",
label: $localize`:Label for the center of a child:Center`,
+ anonymize: "retain",
})
center: Center;
@DatabaseField({
label: $localize`:Label for the admission date of a child:Admission`,
+ anonymize: "retain-anonymized",
})
admissionDate: Date;
@@ -89,11 +95,13 @@ export class Child extends Entity {
@DatabaseField({
label: $localize`:Label for the dropout date of a child:Dropout Date`,
+ anonymize: "retain-anonymized",
})
dropoutDate: Date;
@DatabaseField({
label: $localize`:Label for the type of dropout of a child:Dropout Type`,
+ anonymize: "retain",
})
dropoutType: string;
@@ -120,6 +128,11 @@ export class Child extends Entity {
phone: string;
get isActive(): boolean {
+ if (this.inactive !== undefined) {
+ // explicit property set through UI has to take precedence
+ return super.isActive;
+ }
+
return (
this.status !== "Dropout" &&
!this["dropoutDate"] &&
diff --git a/src/app/child-dev-project/children/model/childSchoolRelation.ts b/src/app/child-dev-project/children/model/childSchoolRelation.ts
index fdb8119efe..4362b98af5 100644
--- a/src/app/child-dev-project/children/model/childSchoolRelation.ts
+++ b/src/app/child-dev-project/children/model/childSchoolRelation.ts
@@ -9,13 +9,17 @@ import { TimePeriod } from "../../../core/entity-details/related-time-period-ent
*/
@DatabaseEntity("ChildSchoolRelation")
export class ChildSchoolRelation extends TimePeriod {
+ static override hasPII = true;
+
@DatabaseField({
label: $localize`:Label for the child of a relation:Child`,
dataType: "entity",
additional: Child.ENTITY_TYPE,
+ entityReferenceRole: "composite",
validators: {
required: true,
},
+ anonymize: "retain",
})
childId: string;
@@ -23,9 +27,11 @@ export class ChildSchoolRelation extends TimePeriod {
label: $localize`:Label for the school of a relation:School`,
dataType: "entity",
additional: School.ENTITY_TYPE,
+ entityReferenceRole: "aggregate",
validators: {
required: true,
},
+ anonymize: "retain",
})
schoolId: string;
@@ -36,6 +42,7 @@ export class ChildSchoolRelation extends TimePeriod {
dataType: "date-only",
label: $localize`:Label for the start date of a relation:Start date`,
description: $localize`:Description of the start date of a relation:The date a child joins a school`,
+ anonymize: "retain",
})
start: Date;
@@ -43,6 +50,7 @@ export class ChildSchoolRelation extends TimePeriod {
dataType: "date-only",
label: $localize`:Label for the end date of a relation:End date`,
description: $localize`:Description of the end date of a relation:The date of a child leaving the school`,
+ anonymize: "retain",
})
end: Date;
diff --git a/src/app/child-dev-project/notes/model/note.ts b/src/app/child-dev-project/notes/model/note.ts
index 11bf224ada..378815bb0d 100644
--- a/src/app/child-dev-project/notes/model/note.ts
+++ b/src/app/child-dev-project/notes/model/note.ts
@@ -39,6 +39,7 @@ export class Note extends Entity {
static toStringAttributes = ["subject"];
static label = $localize`:label for entity:Note`;
static labelPlural = $localize`:label (plural) for entity:Notes`;
+ static override hasPII = true;
static create(
date: Date,
@@ -76,7 +77,9 @@ export class Note extends Entity {
label: $localize`:Label for the children of a note:Children`,
dataType: "entity-array",
additional: Child.ENTITY_TYPE,
+ entityReferenceRole: "composite",
editComponent: "EditAttendance",
+ anonymize: "retain",
})
children: string[] = [];
@@ -85,28 +88,37 @@ export class Note extends Entity {
*
* No direct access to change this property. Use the `.getAttendance()` method to have safe access.
*/
- @DatabaseField({ innerDataType: "schema-embed", additional: EventAttendance })
+ @DatabaseField({
+ innerDataType: "schema-embed",
+ additional: EventAttendance,
+ anonymize: "retain",
+ })
private childrenAttendance: Map = new Map();
@DatabaseField({
label: $localize`:Label for the date of a note:Date`,
dataType: "date-only",
defaultValue: PLACEHOLDERS.NOW,
+ anonymize: "retain",
})
date: Date;
+
@DatabaseField({ label: $localize`:Label for the subject of a note:Subject` })
subject: string;
+
@DatabaseField({
label: $localize`:Label for the actual notes of a note:Notes`,
editComponent: "EditLongText",
})
text: string;
+
/** IDs of users that authored this note */
@DatabaseField({
label: $localize`:Label for the social worker(s) who created the note:SW`,
dataType: "entity-array",
additional: User.ENTITY_TYPE,
defaultValue: PLACEHOLDERS.CURRENT_USER,
+ anonymize: "retain",
})
authors: string[] = [];
@@ -114,13 +126,23 @@ export class Note extends Entity {
label: $localize`:Label for the category of a note:Category`,
dataType: "configurable-enum",
innerDataType: INTERACTION_TYPE_CONFIG_ID,
+ anonymize: "retain",
})
category: InteractionType;
+ @DatabaseField({
+ label: $localize`Attachment`,
+ dataType: "file",
+ })
+ attachment: string;
+
/**
* id referencing a different entity (e.g. a recurring activity) this note is related to
*/
- @DatabaseField() relatesTo: string;
+ @DatabaseField({
+ anonymize: "retain",
+ })
+ relatesTo: string;
/**
* other records (e.g. a recurring activity, group membership, ...) to which this note is related in some way,
@@ -134,6 +156,7 @@ export class Note extends Entity {
editComponent: "EditEntityArray",
// by default no additional relatedEntities can be linked apart from children and schools, overwrite this in config to display (e.g. additional: "ChildSchoolRelation")
additional: undefined,
+ anonymize: "retain",
})
relatedEntities: string[] = [];
@@ -144,6 +167,8 @@ export class Note extends Entity {
label: $localize`:label for the linked schools:Groups`,
dataType: "entity-array",
additional: School.ENTITY_TYPE,
+ entityReferenceRole: "composite",
+ anonymize: "retain",
})
schools: string[] = [];
@@ -151,6 +176,7 @@ export class Note extends Entity {
label: $localize`:Status of a note:Status`,
dataType: "configurable-enum",
innerDataType: "warning-levels",
+ anonymize: "retain",
})
warningLevel: Ordering.EnumValue;
diff --git a/src/app/child-dev-project/notes/note-details/note-details.component.html b/src/app/child-dev-project/notes/note-details/note-details.component.html
index 7832f0da99..2649422078 100644
--- a/src/app/child-dev-project/notes/note-details/note-details.component.html
+++ b/src/app/child-dev-project/notes/note-details/note-details.component.html
@@ -18,51 +18,55 @@
{{ tmpEntity.date | date }}: {{ tmpEntity.subject }}
-
-
-
+
+
+
-
-
diff --git a/src/app/child-dev-project/notes/note-details/note-details.component.ts b/src/app/child-dev-project/notes/note-details/note-details.component.ts
index 368ec94a47..060add770f 100644
--- a/src/app/child-dev-project/notes/note-details/note-details.component.ts
+++ b/src/app/child-dev-project/notes/note-details/note-details.component.ts
@@ -26,6 +26,7 @@ import { DynamicComponentDirective } from "../../../core/config/dynamic-componen
import { MAT_DIALOG_DATA, MatDialogModule } from "@angular/material/dialog";
import { DialogButtonsComponent } from "../../../core/form-dialog/dialog-buttons/dialog-buttons.component";
import { DialogCloseComponent } from "../../../core/common-components/dialog-close/dialog-close.component";
+import { EntityArchivedInfoComponent } from "../../../core/entity-details/entity-archived-info/entity-archived-info.component";
/**
* Component responsible for displaying the Note creation/view window
@@ -46,6 +47,7 @@ import { DialogCloseComponent } from "../../../core/common-components/dialog-clo
DialogButtonsComponent,
MatMenuModule,
DialogCloseComponent,
+ EntityArchivedInfoComponent,
],
standalone: true,
encapsulation: ViewEncapsulation.None,
@@ -56,9 +58,9 @@ export class NoteDetailsComponent implements OnInit {
/** export format for notes to be used for downloading the individual details */
exportConfig: ExportColumnConfig[];
- topForm = ["date", "warningLevel", "category", "authors"].map((field) => [
- toFormFieldConfig(field),
- ]);
+ topForm = ["date", "warningLevel", "category", "authors", "attachment"].map(
+ (field) => [toFormFieldConfig(field)],
+ );
middleForm = ["subject", "text"].map(toFormFieldConfig);
bottomForm = ["children", "schools"].map(toFormFieldConfig);
form: EntityForm;
diff --git a/src/app/child-dev-project/notes/notes-manager/notes-manager.component.spec.ts b/src/app/child-dev-project/notes/notes-manager/notes-manager.component.spec.ts
index 92422aa17a..0c1238b8fa 100644
--- a/src/app/child-dev-project/notes/notes-manager/notes-manager.component.spec.ts
+++ b/src/app/child-dev-project/notes/notes-manager/notes-manager.component.spec.ts
@@ -1,7 +1,4 @@
-import {
- NotesManagerComponent,
- NotesManagerConfig,
-} from "./notes-manager.component";
+import { NotesManagerComponent } from "./notes-manager.component";
import {
ComponentFixture,
fakeAsync,
@@ -191,11 +188,9 @@ describe("NotesManagerComponent", () => {
entityMapper.save(eventNote);
tick();
+ component.includeEventNotes = true;
routeMock.data.next({
- config: Object.assign(
- { includeEventNotes: true } as NotesManagerConfig,
- routeData,
- ),
+ config: routeData,
});
flush();
diff --git a/src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts b/src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
index e38943d871..a7ae7e67b7 100644
--- a/src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
+++ b/src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
@@ -4,7 +4,6 @@ import { NoteDetailsComponent } from "../note-details/note-details.component";
import { ActivatedRoute } from "@angular/router";
import { EntityMapperService } from "../../../core/entity/entity-mapper/entity-mapper.service";
import { FilterSelectionOption } from "../../../core/filter/filters/filters";
-import { SessionService } from "../../../core/session/session-service/session.service";
import { FormDialogService } from "../../../core/form-dialog/form-dialog.service";
import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
import { LoggingService } from "../../../core/logging/logging.service";
@@ -92,7 +91,6 @@ export class NotesManagerComponent implements OnInit {
constructor(
private formDialog: FormDialogService,
- private sessionService: SessionService,
private entityMapperService: EntityMapperService,
private route: ActivatedRoute,
private log: LoggingService,
@@ -101,11 +99,9 @@ export class NotesManagerComponent implements OnInit {
async ngOnInit() {
this.route.data.subscribe(
async (data: RouteData) => {
+ // TODO replace this use of route and rely on the RoutedViewComponent instead
this.config = data.config;
this.addPrebuiltFilters();
-
- this.includeEventNotes = data.config.includeEventNotes;
- this.showEventNotesToggle = data.config.showEventNotesToggle;
this.notes = await this.loadEntities();
},
);
diff --git a/src/app/child-dev-project/schools/child-school-overview/child-school-overview.component.ts b/src/app/child-dev-project/schools/child-school-overview/child-school-overview.component.ts
index d4bea18e49..2ac5ade5e0 100644
--- a/src/app/child-dev-project/schools/child-school-overview/child-school-overview.component.ts
+++ b/src/app/child-dev-project/schools/child-school-overview/child-school-overview.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit } from "@angular/core";
+import { Component, Input, OnInit } from "@angular/core";
import { DynamicComponent } from "../../../core/config/dynamic-components/dynamic-component.decorator";
import { Child } from "../../children/model/child";
import { School } from "../model/school";
@@ -41,6 +41,7 @@ export class ChildSchoolOverviewComponent
implements OnInit
{
mode: "child" | "school" = "child";
+ @Input() showInactive = false;
constructor(private childrenService: ChildrenService) {
super(null, null);
@@ -60,7 +61,7 @@ export class ChildSchoolOverviewComponent
this.switchRelatedEntityColumnForMode();
await this.loadData();
- super.filterActiveInactive();
+ super.onIsActiveFilterChange(this.showInactive);
}
private inferMode(entity: Entity): "child" | "school" {
diff --git a/src/app/core/basic-datatypes/array/array.datatype.ts b/src/app/core/basic-datatypes/array/array.datatype.ts
index 25d0aff32e..0d036455a7 100644
--- a/src/app/core/basic-datatypes/array/array.datatype.ts
+++ b/src/app/core/basic-datatypes/array/array.datatype.ts
@@ -97,6 +97,25 @@ export class ArrayDatatype<
),
);
}
+
+ async anonymize(
+ value: EntityType[],
+ schemaField: EntitySchemaField,
+ parent,
+ ): Promise {
+ const arrayElementDatatype: DefaultDatatype =
+ this.schemaService.getDatatypeOrDefault(schemaField.innerDataType);
+
+ const mappedPromises = value.map(async (el) =>
+ arrayElementDatatype.anonymize(
+ el,
+ generateSubSchemaField(schemaField),
+ parent,
+ ),
+ );
+
+ return Promise.all(mappedPromises);
+ }
}
/**
diff --git a/src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.html b/src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.html
index f0e54c54cc..599b384fc6 100644
--- a/src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.html
+++ b/src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.html
@@ -2,6 +2,7 @@
Edit dropdown options
+
matIconPrefix
class="grab-icon margin-right-small"
>
+
+
+
+
+
+ Add new option
+
+
+
+
+
diff --git a/src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.spec.ts b/src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.spec.ts
index f1d171a757..32bd4619d7 100644
--- a/src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.spec.ts
+++ b/src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.spec.ts
@@ -17,6 +17,7 @@ import {
entityRegistry,
EntityRegistry,
} from "../../../entity/database-entity.decorator";
+import { NoopAnimationsModule } from "@angular/platform-browser/animations";
describe("ConfigureEnumPopupComponent", () => {
let component: ConfigureEnumPopupComponent;
@@ -26,7 +27,11 @@ describe("ConfigureEnumPopupComponent", () => {
beforeEach(async () => {
entityMapper = mockEntityMapper();
await TestBed.configureTestingModule({
- imports: [ConfigureEnumPopupComponent, FontAwesomeTestingModule],
+ imports: [
+ ConfigureEnumPopupComponent,
+ FontAwesomeTestingModule,
+ NoopAnimationsModule,
+ ],
providers: [
{ provide: MAT_DIALOG_DATA, useValue: new ConfigurableEnum() },
{ provide: MatDialogRef, useValue: { afterClosed: () => EMPTY } },
diff --git a/src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.ts b/src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.ts
index 949bb3f46d..bffccff20a 100644
--- a/src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.ts
+++ b/src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.ts
@@ -43,6 +43,8 @@ import { Entity } from "../../../entity/model/entity";
standalone: true,
})
export class ConfigureEnumPopupComponent {
+ newOptionInput: string;
+
constructor(
@Inject(MAT_DIALOG_DATA) public enumEntity: ConfigurableEnum,
private dialog: MatDialogRef,
@@ -125,4 +127,13 @@ export class ConfigureEnumPopupComponent {
),
);
}
+
+ createNewOption() {
+ this.enumEntity.values.push({
+ id: this.newOptionInput,
+ label: this.newOptionInput,
+ });
+ this.newOptionInput = "";
+ }
+ mynewFun() {}
}
diff --git a/src/app/core/basic-datatypes/date-with-age/date-with-age.datatype.spec.ts b/src/app/core/basic-datatypes/date-with-age/date-with-age.datatype.spec.ts
index c198494af8..101e1b19d0 100644
--- a/src/app/core/basic-datatypes/date-with-age/date-with-age.datatype.spec.ts
+++ b/src/app/core/basic-datatypes/date-with-age/date-with-age.datatype.spec.ts
@@ -1,7 +1,7 @@
import { DateWithAgeDatatype } from "./date-with-age.datatype";
-import { DateWithAge } from "../../../child-dev-project/children/model/dateWithAge";
import { testDatatype } from "../../entity/schema/entity-schema.service.spec";
import moment from "moment";
+import { DateWithAge } from "./dateWithAge";
describe("Schema data type: date-with-age", () => {
testDatatype(
diff --git a/src/app/core/basic-datatypes/date-with-age/date-with-age.datatype.ts b/src/app/core/basic-datatypes/date-with-age/date-with-age.datatype.ts
index 49d6ab46fe..50ab219e90 100644
--- a/src/app/core/basic-datatypes/date-with-age/date-with-age.datatype.ts
+++ b/src/app/core/basic-datatypes/date-with-age/date-with-age.datatype.ts
@@ -1,6 +1,6 @@
import { DateOnlyDatatype } from "../date-only/date-only.datatype";
-import { DateWithAge } from "../../../child-dev-project/children/model/dateWithAge";
import { Injectable } from "@angular/core";
+import { DateWithAge } from "./dateWithAge";
/**
* Similar to the 'date-only' datatype but it uses the `DateWithAge` class which provides the `age` function.
diff --git a/src/app/child-dev-project/children/model/dateWithAge.ts b/src/app/core/basic-datatypes/date-with-age/dateWithAge.ts
similarity index 100%
rename from src/app/child-dev-project/children/model/dateWithAge.ts
rename to src/app/core/basic-datatypes/date-with-age/dateWithAge.ts
diff --git a/src/app/core/basic-datatypes/date-with-age/display-age/display-age.component.spec.ts b/src/app/core/basic-datatypes/date-with-age/display-age/display-age.component.spec.ts
index ad4ad52c92..f8cd943f29 100644
--- a/src/app/core/basic-datatypes/date-with-age/display-age/display-age.component.spec.ts
+++ b/src/app/core/basic-datatypes/date-with-age/display-age/display-age.component.spec.ts
@@ -2,8 +2,8 @@ import { ComponentFixture, TestBed } from "@angular/core/testing";
import { DisplayAgeComponent } from "./display-age.component";
import { Child } from "../../../../child-dev-project/children/model/child";
-import { DateWithAge } from "../../../../child-dev-project/children/model/dateWithAge";
import moment from "moment";
+import { DateWithAge } from "../dateWithAge";
describe("DisplayAgeComponent", () => {
let component: DisplayAgeComponent;
diff --git a/src/app/core/basic-datatypes/date-with-age/display-age/display-age.component.ts b/src/app/core/basic-datatypes/date-with-age/display-age/display-age.component.ts
index abe9f9a770..377224d8d0 100644
--- a/src/app/core/basic-datatypes/date-with-age/display-age/display-age.component.ts
+++ b/src/app/core/basic-datatypes/date-with-age/display-age/display-age.component.ts
@@ -1,7 +1,7 @@
import { Component, OnInit } from "@angular/core";
import { ViewDirective } from "../../../entity/default-datatype/view.directive";
-import { DateWithAge } from "../../../../child-dev-project/children/model/dateWithAge";
import { DynamicComponent } from "../../../config/dynamic-components/dynamic-component.decorator";
+import { DateWithAge } from "../dateWithAge";
/**
* A component which displays the age of an entity with a DateOfBirth property.
diff --git a/src/app/core/basic-datatypes/date-with-age/display-age/display-age.stories.ts b/src/app/core/basic-datatypes/date-with-age/display-age/display-age.stories.ts
index 247756345a..33e9af6d93 100644
--- a/src/app/core/basic-datatypes/date-with-age/display-age/display-age.stories.ts
+++ b/src/app/core/basic-datatypes/date-with-age/display-age/display-age.stories.ts
@@ -1,8 +1,8 @@
import { applicationConfig, Meta, StoryFn } from "@storybook/angular";
import { StorybookBaseModule } from "../../../../utils/storybook-base.module";
import { DisplayAgeComponent } from "./display-age.component";
-import { DateWithAge } from "../../../../child-dev-project/children/model/dateWithAge";
import { importProvidersFrom } from "@angular/core";
+import { DateWithAge } from "../dateWithAge";
export default {
title: "Core/Entities/Properties/date/DisplayAge",
diff --git a/src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.component.html b/src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.component.html
index f9cd7c35e8..9ef10c03a9 100644
--- a/src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.component.html
+++ b/src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.component.html
@@ -1,5 +1,10 @@
-
+
{{ label }}
+
Age {
let component: EditAgeComponent;
diff --git a/src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.component.ts b/src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.component.ts
index 4d692054e0..77241695bd 100644
--- a/src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.component.ts
+++ b/src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.component.ts
@@ -5,7 +5,6 @@ import {
MatDatepickerInputEvent,
MatDatepickerModule,
} from "@angular/material/datepicker";
-import { DateWithAge } from "../../../../child-dev-project/children/model/dateWithAge";
import { ReactiveFormsModule } from "@angular/forms";
import { MatFormFieldModule } from "@angular/material/form-field";
import { MatInputModule } from "@angular/material/input";
@@ -13,6 +12,7 @@ import { ErrorHintComponent } from "../../../common-components/error-hint/error-
import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
import { NgIf } from "@angular/common";
import { MatTooltipModule } from "@angular/material/tooltip";
+import { DateWithAge } from "../dateWithAge";
@DynamicComponent("EditAge")
@Component({
diff --git a/src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.stories.ts b/src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.stories.ts
index c70dd08798..0bbdce871f 100644
--- a/src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.stories.ts
+++ b/src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.stories.ts
@@ -1,6 +1,6 @@
import { generateFormFieldStory } from "../../../entity/default-datatype/edit-component-story-utils";
-import { DateWithAge } from "../../../../child-dev-project/children/model/dateWithAge";
import { StoryFn } from "@storybook/angular";
+import { DateWithAge } from "../dateWithAge";
const formFieldStory = generateFormFieldStory(
"EditAge",
diff --git a/src/app/core/basic-datatypes/date/date.datatype.spec.ts b/src/app/core/basic-datatypes/date/date.datatype.spec.ts
index c3f8214c62..a630ffc912 100644
--- a/src/app/core/basic-datatypes/date/date.datatype.spec.ts
+++ b/src/app/core/basic-datatypes/date/date.datatype.spec.ts
@@ -7,4 +7,12 @@ describe("Schema data type: date", () => {
new Date(2023, 10, 25),
new Date(2023, 10, 25),
);
+
+ it("should anonymize dates and only retain year", async () => {
+ const datatype = new DateDatatype();
+ const testDate = new Date(2023, 10, 25);
+
+ const actualAnonymized = await datatype.anonymize(testDate);
+ expect(actualAnonymized).toEqual(new Date(2023, 6, 1));
+ });
});
diff --git a/src/app/core/basic-datatypes/date/date.datatype.ts b/src/app/core/basic-datatypes/date/date.datatype.ts
index a176ffc55c..d18777f913 100644
--- a/src/app/core/basic-datatypes/date/date.datatype.ts
+++ b/src/app/core/basic-datatypes/date/date.datatype.ts
@@ -71,4 +71,10 @@ export class DateDatatype extends DefaultDatatype<
return undefined;
}
}
+
+ async anonymize(value: Date): Promise {
+ // normalize to 01.06. of the year, which has less statistical distortion than 01.01.
+ // (roughly half the dates before anonymization will be earlier and half will be later)
+ return new Date(value.getFullYear(), 6, 1);
+ }
}
diff --git a/src/app/core/basic-datatypes/date/display-date/display-date.component.html b/src/app/core/basic-datatypes/date/display-date/display-date.component.html
new file mode 100644
index 0000000000..78fd5b6411
--- /dev/null
+++ b/src/app/core/basic-datatypes/date/display-date/display-date.component.html
@@ -0,0 +1,14 @@
+
+ {{ value | date: config }}
+
+
+
+ {{ value | date: "YYYY" }}
+
+
diff --git a/src/app/core/basic-datatypes/date/display-date/display-date.component.ts b/src/app/core/basic-datatypes/date/display-date/display-date.component.ts
index 76001a89f0..7db5675d5e 100644
--- a/src/app/core/basic-datatypes/date/display-date/display-date.component.ts
+++ b/src/app/core/basic-datatypes/date/display-date/display-date.component.ts
@@ -1,7 +1,9 @@
-import { Component } from "@angular/core";
+import { Component, Input } from "@angular/core";
import { ViewDirective } from "../../../entity/default-datatype/view.directive";
import { DynamicComponent } from "../../../config/dynamic-components/dynamic-component.decorator";
-import { DatePipe } from "@angular/common";
+import { DatePipe, NgIf } from "@angular/common";
+import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
+import { MatTooltipModule } from "@angular/material/tooltip";
/**
* This component displays a date attribute using the shortDate format.
@@ -12,8 +14,13 @@ import { DatePipe } from "@angular/common";
@DynamicComponent("DisplayDate")
@Component({
selector: "app-display-date",
- template: `{{ value | date: config }}`,
+ templateUrl: "./display-date.component.html",
standalone: true,
- imports: [DatePipe],
+ imports: [DatePipe, NgIf, FontAwesomeModule, MatTooltipModule],
})
-export class DisplayDateComponent extends ViewDirective {}
+export class DisplayDateComponent extends ViewDirective {
+ @Input() displayAsAnonymized: boolean;
+
+ /** formatting string for date pipe */
+ @Input() config: string;
+}
diff --git a/src/app/core/basic-datatypes/date/edit-date/edit-date.component.html b/src/app/core/basic-datatypes/date/edit-date/edit-date.component.html
index caf141aebe..31f53b3378 100644
--- a/src/app/core/basic-datatypes/date/edit-date/edit-date.component.html
+++ b/src/app/core/basic-datatypes/date/edit-date/edit-date.component.html
@@ -5,6 +5,15 @@
[formControlName]="formControlName"
[matDatepicker]="datepickerComp"
/>
+
+
+
{
- const mockEntitySchemaService: EntitySchemaService = {
- getDatatypeOrDefault: () => new EntityDatatype(undefined),
+ const mockEntityDatatype = new EntityDatatype(null, null);
+ const mockEntitySchemaService = {
+ getDatatypeOrDefault: () => mockEntityDatatype,
} as any;
- testDatatype(
- new EntityArrayDatatype(mockEntitySchemaService),
- ["1", "User:5"],
- ["1", "User:5"],
- "User",
- );
+ const datatype = new EntityArrayDatatype(mockEntitySchemaService);
+
+ testDatatype(datatype, ["1", "User:5"], ["1", "User:5"], "User");
testDatatype(
- new EntityArrayDatatype(mockEntitySchemaService),
+ datatype,
["User:1", "Child:1"],
["User:1", "Child:1"],
["User", "Child", "School"],
);
+ it("should anonymize entities recursively", async () => {
+ const testValue = ["Entity:ref-1", "Entity:ref-2"];
+ spyOn(mockEntityDatatype, "anonymize").and.callFake(async (x) => x);
+
+ const anonymizedValue = await datatype.anonymize(testValue, null, null);
+
+ expect(anonymizedValue).toEqual(testValue);
+ expect(mockEntityDatatype.anonymize).toHaveBeenCalledTimes(2);
+ expect(mockEntityDatatype.anonymize).toHaveBeenCalledWith(
+ "Entity:ref-1",
+ jasmine.objectContaining({ dataType: "entity" }),
+ null,
+ );
+ });
+
xit("adds prefix to ids when a definite entity type is given in schema", () => {
// TODO discuss whether we want to switch to prefixed ids always (also see #1526)
const data = {
diff --git a/src/app/core/basic-datatypes/entity-array/entity-array.datatype.ts b/src/app/core/basic-datatypes/entity-array/entity-array.datatype.ts
index 0840a37baa..543873e13e 100644
--- a/src/app/core/basic-datatypes/entity-array/entity-array.datatype.ts
+++ b/src/app/core/basic-datatypes/entity-array/entity-array.datatype.ts
@@ -63,4 +63,12 @@ export class EntityArrayDatatype extends ArrayDatatype {
return value;
}*/
}
+
+ async anonymize(value, schema: EntitySchemaField, parent) {
+ return super.anonymize(
+ value,
+ { ...schema, innerDataType: EntityDatatype.dataType },
+ parent,
+ );
+ }
}
diff --git a/src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html b/src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
index 0f80445fcf..d7a6e0cc7b 100644
--- a/src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
+++ b/src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
@@ -1,19 +1,25 @@
- Select matching {{ entity.label }} property
-
-
- {{ property.label }}
-
-
-
+
+ Select matching {{ entity.label }} property
+
+
+
+ {{ property.label }}
+
+
+
-
- Save & Close
-
- Cancel
+
+ Save & Close
+
+ Cancel
diff --git a/src/app/core/basic-datatypes/entity/entity-reference-role.ts b/src/app/core/basic-datatypes/entity/entity-reference-role.ts
new file mode 100644
index 0000000000..e629dda389
--- /dev/null
+++ b/src/app/core/basic-datatypes/entity/entity-reference-role.ts
@@ -0,0 +1,10 @@
+/**
+ * Specifies the role of an entity reference where
+ * "aggregate" = "has a" relationship where both entities have meaning independent of each other;
+ * "composite" = "part of" relationship where the referenced entity should not exist without the referenced entity.
+ *
+ * Default is treated as "aggregate".
+ *
+ * (role names following the UML association types)
+ */
+export type EntityReferenceRole = "aggregate" | "composite";
diff --git a/src/app/core/basic-datatypes/entity/entity.datatype.spec.ts b/src/app/core/basic-datatypes/entity/entity.datatype.spec.ts
index 133f37454e..99b11747c0 100644
--- a/src/app/core/basic-datatypes/entity/entity.datatype.spec.ts
+++ b/src/app/core/basic-datatypes/entity/entity.datatype.spec.ts
@@ -20,16 +20,17 @@ import { EntityDatatype } from "./entity.datatype";
import { mockEntityMapper } from "../../entity/entity-mapper/mock-entity-mapper-service";
import { Child } from "../../../child-dev-project/children/model/child";
import { ChildSchoolRelation } from "../../../child-dev-project/children/model/childSchoolRelation";
+import { EntityActionsService } from "../../entity/entity-actions/entity-actions.service";
describe("Schema data type: entity", () => {
- testDatatype(new EntityDatatype(undefined), "1", "1", "User");
+ testDatatype(new EntityDatatype(null, null), "1", "1", "User");
it("should map to the referenced entity", async () => {
const c1 = Child.create("first");
const c2 = new Child();
c2.projectNumber = "123";
const entityMapper = mockEntityMapper([c1, c2]);
- const dataType = new EntityDatatype(entityMapper);
+ const dataType = new EntityDatatype(entityMapper, null);
const schema = ChildSchoolRelation.schema.get("childId");
await expectAsync(
@@ -42,4 +43,27 @@ describe("Schema data type: entity", () => {
dataType.importMapFunction("345", schema, "projectNumber"),
).toBeResolvedTo(undefined);
});
+
+ it("should anonymize entity recursively", async () => {
+ const referencedEntity = new Child("ref-1");
+ referencedEntity.name = "test";
+
+ const entityMapper = mockEntityMapper([referencedEntity]);
+ spyOn(entityMapper, "save");
+ const mockRemoveService: jasmine.SpyObj =
+ jasmine.createSpyObj("EntityRemoveService", ["anonymize"]);
+ const dataType = new EntityDatatype(entityMapper, mockRemoveService);
+
+ const testValue = referencedEntity.getId();
+ const testSchemaField = { additional: "Child", dataType: "entity" };
+
+ const anonymizedValue = await dataType.anonymize(
+ testValue,
+ testSchemaField,
+ null,
+ );
+
+ expect(anonymizedValue).toEqual(testValue);
+ expect(mockRemoveService.anonymize).toHaveBeenCalledWith(referencedEntity);
+ });
});
diff --git a/src/app/core/basic-datatypes/entity/entity.datatype.ts b/src/app/core/basic-datatypes/entity/entity.datatype.ts
index 1e9c81a7a2..eb1281c586 100644
--- a/src/app/core/basic-datatypes/entity/entity.datatype.ts
+++ b/src/app/core/basic-datatypes/entity/entity.datatype.ts
@@ -20,6 +20,7 @@ import { StringDatatype } from "../string/string.datatype";
import { EntitySchemaField } from "../../entity/schema/entity-schema-field";
import { EntityMapperService } from "../../entity/entity-mapper/entity-mapper.service";
import { ColumnMapping } from "../../import/column-mapping";
+import { EntityActionsService } from "../../entity/entity-actions/entity-actions.service";
/**
* Datatype for the EntitySchemaService to handle a single reference to another entity
@@ -37,7 +38,10 @@ export class EntityDatatype extends StringDatatype {
viewComponent = "DisplayEntity";
importConfigComponent = "EntityImportConfig";
- constructor(private entityMapper: EntityMapperService) {
+ constructor(
+ private entityMapper: EntityMapperService,
+ private removeService: EntityActionsService,
+ ) {
super();
}
@@ -57,4 +61,29 @@ export class EntityDatatype extends StringDatatype {
importIncompleteAdditionalConfigBadge(col: ColumnMapping): string {
return col.additional ? undefined : "?";
}
+
+ /**
+ * Recursively calls anonymize on the referenced entity and saves it.
+ * @param value
+ * @param schemaField
+ * @param parent
+ */
+ async anonymize(
+ value,
+ schemaField: EntitySchemaField,
+ parent,
+ ): Promise {
+ const referencedEntity = await this.entityMapper.load(
+ schemaField.additional,
+ value,
+ );
+
+ if (!referencedEntity) {
+ // TODO: remove broken references?
+ return value;
+ }
+
+ await this.removeService.anonymize(referencedEntity);
+ return value;
+ }
}
diff --git a/src/app/core/basic-datatypes/month/display-month/display-month.component.ts b/src/app/core/basic-datatypes/month/display-month/display-month.component.ts
index ecdf6591e5..8eddf4dd3a 100644
--- a/src/app/core/basic-datatypes/month/display-month/display-month.component.ts
+++ b/src/app/core/basic-datatypes/month/display-month/display-month.component.ts
@@ -1,11 +1,16 @@
import { Component } from "@angular/core";
-import { DatePipe } from "@angular/common";
+import { DatePipe, NgIf } from "@angular/common";
import { ViewDirective } from "../../../entity/default-datatype/view.directive";
+import { DisplayDateComponent } from "../../date/display-date/display-date.component";
@Component({
selector: "app-display-month",
standalone: true,
- template: `{{ value | date: "YYYY-MM" }}`,
- imports: [DatePipe],
+ template: ` `,
+ imports: [DatePipe, NgIf, DisplayDateComponent],
})
export class DisplayMonthComponent extends ViewDirective {}
diff --git a/src/app/core/basic-datatypes/month/edit-month/edit-month.component.html b/src/app/core/basic-datatypes/month/edit-month/edit-month.component.html
index 56239701c7..ab01510f80 100644
--- a/src/app/core/basic-datatypes/month/edit-month/edit-month.component.html
+++ b/src/app/core/basic-datatypes/month/edit-month/edit-month.component.html
@@ -5,6 +5,15 @@
[formControl]="formControl"
[matDatepicker]="datepickerComp"
/>
+
+
+
{
setMonthAndYear(date: Moment, datepicker: MatDatepicker) {
- this.formControl.setValue(date.toDate());
this.formControl.markAsDirty();
+ this.formControl.setValue(date.toDate());
datepicker.close();
}
}
diff --git a/src/app/core/common-components/basic-autocomplete/custom-form-control.directive.ts b/src/app/core/common-components/basic-autocomplete/custom-form-control.directive.ts
index 48263da39b..00fc6d0a23 100644
--- a/src/app/core/common-components/basic-autocomplete/custom-form-control.directive.ts
+++ b/src/app/core/common-components/basic-autocomplete/custom-form-control.directive.ts
@@ -4,6 +4,7 @@ import {
FormGroupDirective,
NgControl,
NgForm,
+ Validators,
} from "@angular/forms";
import { MatFormFieldControl } from "@angular/material/form-field";
import {
@@ -28,7 +29,16 @@ export abstract class CustomFormControlDirective
// eslint-disable-next-line @angular-eslint/no-input-rename
@Input("aria-describedby") userAriaDescribedBy: string;
@Input() placeholder: string;
- @Input() required = false;
+
+ @Input()
+ get required() {
+ return this._required;
+ }
+ set required(req: boolean) {
+ this._required = coerceBooleanProperty(req);
+ this.stateChanges.next();
+ }
+ private _required = false;
abstract inputElement: { _elementRef: ElementRef };
stateChanges = new Subject();
@@ -123,16 +133,22 @@ export abstract class CustomFormControlDirective
this.disabled = isDisabled;
}
+ ngDoCheck() {
+ const control = this.ngControl
+ ? (this.ngControl.control as AbstractControl)
+ : null;
+
+ this.checkUpdateErrorState(control);
+ this.checkUpdateRequired(control);
+ }
+
/**
* Updates the error state based on the form control
* Taken from {@link https://github.com/angular/components/blob/a1d5614f18066c0c2dc2580c7b5099e8f68a8e74/src/material/core/common-behaviors/error-state.ts#L59}
*/
- ngDoCheck() {
+ private checkUpdateErrorState(control: AbstractControl | null) {
const oldState = this.errorState;
const parent = this.parentFormGroup || this.parentForm;
- const control = this.ngControl
- ? (this.ngControl.control as AbstractControl)
- : null;
const newState = this.errorStateMatcher.isErrorState(control, parent);
if (newState !== oldState) {
@@ -140,4 +156,17 @@ export abstract class CustomFormControlDirective
this.stateChanges.next();
}
}
+
+ private checkUpdateRequired(control: AbstractControl | null) {
+ if (!control) {
+ return;
+ }
+
+ if (
+ this.required !==
+ coerceBooleanProperty(control.hasValidator(Validators.required))
+ ) {
+ this.required = control.hasValidator(Validators.required);
+ }
+ }
}
diff --git a/src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts b/src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
index f7fd6c9cb5..b4352403db 100644
--- a/src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
+++ b/src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
@@ -6,6 +6,7 @@ import {
YesNoButtons,
} from "./confirmation-dialog/confirmation-dialog.component";
import { firstValueFrom } from "rxjs";
+import { ProgressDialogComponent } from "./progress-dialog/progress-dialog.component";
/**
* Inject this service instead of MatDialog if you need a simple, configurable confirmation dialog box
@@ -63,4 +64,17 @@ export class ConfirmationDialogService {
$localize`:Discard changes message:You have unsaved changes. Do you really want to leave this page? All unsaved changes will be lost.`,
);
}
+
+ /**
+ * Show an (indeterminate) progress bar modal that cannot be closed by the user.
+ * Use the returned dialogRef to close the dialog once your processing is completed.
+ * @param message
+ */
+ showProgressDialog(message: string) {
+ return this.dialog.open(ProgressDialogComponent, {
+ data: { message },
+ minWidth: "50vh",
+ disableClose: true,
+ });
+ }
}
diff --git a/src/app/core/common-components/confirmation-dialog/confirmation-dialog/confirmation-dialog.component.html b/src/app/core/common-components/confirmation-dialog/confirmation-dialog/confirmation-dialog.component.html
index f1a2a1861e..4b31f2b57c 100644
--- a/src/app/core/common-components/confirmation-dialog/confirmation-dialog/confirmation-dialog.component.html
+++ b/src/app/core/common-components/confirmation-dialog/confirmation-dialog/confirmation-dialog.component.html
@@ -6,7 +6,7 @@
>
-
{{ data.text }}
+
{{ para }}
diff --git a/src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.html b/src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.html
new file mode 100644
index 0000000000..8481907b58
--- /dev/null
+++ b/src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.html
@@ -0,0 +1,7 @@
+
+ {{ data.message }}
+
+
+
+
+
diff --git a/src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts b/src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts
new file mode 100644
index 0000000000..8926eec000
--- /dev/null
+++ b/src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.spec.ts
@@ -0,0 +1,32 @@
+import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing";
+
+import { ProgressDialogComponent } from "./progress-dialog.component";
+import { MAT_DIALOG_DATA, MatDialogRef } from "@angular/material/dialog";
+
+describe("ProgressDialogComponent", () => {
+ let component: ProgressDialogComponent;
+ let fixture: ComponentFixture
;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ imports: [ProgressDialogComponent],
+ providers: [
+ { provide: MatDialogRef, useValue: {} },
+ {
+ provide: MAT_DIALOG_DATA,
+ useValue: { message: "test title" },
+ },
+ ],
+ }).compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ProgressDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it("should create", () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts b/src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
new file mode 100644
index 0000000000..3c213d838c
--- /dev/null
+++ b/src/app/core/common-components/confirmation-dialog/progress-dialog/progress-dialog.component.ts
@@ -0,0 +1,16 @@
+import { Component, Inject } from "@angular/core";
+import { MAT_DIALOG_DATA, MatDialogModule } from "@angular/material/dialog";
+import { MatProgressBarModule } from "@angular/material/progress-bar";
+
+/**
+ * A simple progress indicator dialog
+ * used via the {@link ConfirmationDialogService}.
+ */
+@Component({
+ templateUrl: "./progress-dialog.component.html",
+ imports: [MatProgressBarModule, MatDialogModule],
+ standalone: true,
+})
+export class ProgressDialogComponent {
+ constructor(@Inject(MAT_DIALOG_DATA) public data: { message: string }) {}
+}
diff --git a/src/app/core/common-components/entity-form/entity-form.service.spec.ts b/src/app/core/common-components/entity-form/entity-form.service.spec.ts
index c0ca1e9bda..d945c641d4 100644
--- a/src/app/core/common-components/entity-form/entity-form.service.spec.ts
+++ b/src/app/core/common-components/entity-form/entity-form.service.spec.ts
@@ -173,7 +173,7 @@ describe("EntityFormService", () => {
schema.defaultValue = PLACEHOLDERS.NOW;
form = service.createFormGroup([{ id: "test" }], new Entity());
- expect(form.get("test")).toHaveValue(new Date());
+ expect(form.get("test").value).toEqual(new Date());
schema.defaultValue = PLACEHOLDERS.CURRENT_USER;
form = service.createFormGroup([{ id: "test" }], new Entity());
diff --git a/src/app/core/common-components/entity-form/entity-form/entity-form.component.spec.ts b/src/app/core/common-components/entity-form/entity-form/entity-form.component.spec.ts
index e57589da85..5d81b59e78 100644
--- a/src/app/core/common-components/entity-form/entity-form/entity-form.component.spec.ts
+++ b/src/app/core/common-components/entity-form/entity-form/entity-form.component.spec.ts
@@ -6,7 +6,7 @@ import { MockedTestingModule } from "../../../../utils/mocked-testing.module";
import { EntityMapperService } from "../../../entity/entity-mapper/entity-mapper.service";
import { ConfirmationDialogService } from "../../confirmation-dialog/confirmation-dialog.service";
import { EntityFormService } from "../entity-form.service";
-import { DateWithAge } from "../../../../child-dev-project/children/model/dateWithAge";
+import { DateWithAge } from "../../../basic-datatypes/date-with-age/dateWithAge";
describe("EntityFormComponent", () => {
let component: EntityFormComponent;
diff --git a/src/app/core/common-components/entity-form/entity-form/entity-form.component.ts b/src/app/core/common-components/entity-form/entity-form/entity-form.component.ts
index fd806f216b..7cdc2713ae 100644
--- a/src/app/core/common-components/entity-form/entity-form/entity-form.component.ts
+++ b/src/app/core/common-components/entity-form/entity-form/entity-form.component.ts
@@ -85,6 +85,7 @@ export class EntityFormComponent
}
if (changes.form && this.form) {
this.initialFormValues = this.form.getRawValue();
+ this.disableForLockedEntity();
}
}
@@ -142,4 +143,14 @@ export class EntityFormComponent
JSON.stringify(entityValue) === JSON.stringify(formValue)
);
}
+
+ /**
+ * Disable the form for certain states of the entity, like it being already anonymized.
+ * @private
+ */
+ private disableForLockedEntity() {
+ if (this.entity?.anonymized) {
+ this.form.disable();
+ }
+ }
}
diff --git a/src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.html b/src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.html
index 487abc8be4..a2908b24f1 100644
--- a/src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.html
+++ b/src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.html
@@ -1,8 +1,24 @@
+
-
+
+
+
+
diff --git a/src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.scss b/src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.scss
index 81846c3786..a79b44d627 100644
--- a/src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.scss
+++ b/src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.scss
@@ -24,7 +24,17 @@
justify-content: center;
}
-:host {
+.table {
+ @include mat-elevation.elevation(2);
+}
+
+.table-footer {
@include mat-elevation.elevation(1);
- display: block;
+ border-top: colors.$grey-darker solid 2px;
+}
+
+.filter-inactive-toggle {
+ padding: sizes.$regular;
+ background-color: white;
+ border-top: none;
}
diff --git a/src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.spec.ts b/src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.spec.ts
index 806079e239..827eab3465 100644
--- a/src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.spec.ts
+++ b/src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.spec.ts
@@ -27,8 +27,8 @@ import { UpdatedEntity } from "../../../entity/model/entity-update";
import { EntityAbility } from "../../../permissions/ability/entity-ability";
import { ScreenWidthObserver } from "../../../../utils/media/screen-size-observer.service";
import { WINDOW_TOKEN } from "../../../../utils/di-tokens";
-import { DateWithAge } from "../../../../child-dev-project/children/model/dateWithAge";
import { FormDialogService } from "../../../form-dialog/form-dialog.service";
+import { DateWithAge } from "../../../basic-datatypes/date-with-age/dateWithAge";
describe("EntitySubrecordComponent", () => {
let component: EntitySubrecordComponent;
@@ -410,4 +410,17 @@ describe("EntitySubrecordComponent", () => {
expect(component.recordsDataSource.data).toEqual([]);
}));
+
+ it("should only show active relations by default", async () => {
+ const active1 = new Entity();
+ active1.inactive = false;
+ const inactive = new Entity();
+ inactive.inactive = true;
+
+ component.records = [active1, inactive];
+
+ component.ngOnChanges({ records: undefined, filter: undefined });
+
+ expect(component.recordsDataSource.data).toEqual([{ record: active1 }]);
+ });
});
diff --git a/src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.ts b/src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.ts
index e63338eb51..b76a780380 100644
--- a/src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.ts
+++ b/src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.ts
@@ -24,7 +24,7 @@ import {
} from "../../entity-form/entity-form.service";
import { LoggingService } from "../../../logging/logging.service";
import { AnalyticsService } from "../../../analytics/analytics.service";
-import { EntityRemoveService } from "../../../entity/entity-remove.service";
+import { EntityActionsService } from "../../../entity/entity-actions/entity-actions.service";
import { EntityMapperService } from "../../../entity/entity-mapper/entity-mapper.service";
import { tableSort } from "./table-sort";
import {
@@ -50,6 +50,12 @@ import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
import { DisableEntityOperationDirective } from "../../../permissions/permission-directive/disable-entity-operation.directive";
import { Angulartics2Module } from "angulartics2";
import { ListPaginatorComponent } from "../list-paginator/list-paginator.component";
+import {
+ MatCheckboxChange,
+ MatCheckboxModule,
+} from "@angular/material/checkbox";
+import { MatSlideToggleModule } from "@angular/material/slide-toggle";
+import { applyUpdate } from "../../../entity/model/entity-update";
export interface TableRow {
record: T;
@@ -87,14 +93,28 @@ export interface TableRow {
DisableEntityOperationDirective,
Angulartics2Module,
ListPaginatorComponent,
+ MatCheckboxModule,
+ MatSlideToggleModule,
],
standalone: true,
})
export class EntitySubrecordComponent implements OnChanges {
@Input() isLoading: boolean;
-
@Input() clickMode: "popup" | "navigate" | "none" = "popup";
+ /**
+ * outputs an event containing an array of currently selected records (checkmarked by the user)
+ *
+ * Checkboxes to select rows are only displayed if you set "selectable" also.
+ */
+ @Output() selectedRecordsChange: EventEmitter = new EventEmitter();
+ @Input() selectedRecords: T[] = [];
+ readonly COLUMN_ROW_SELECT = "_selectRows";
+ @Input() selectable: boolean = false;
+
+ @Input() showInactive = false;
+ @Output() showInactiveChange = new EventEmitter();
+
/** configuration what kind of columns to be generated for the table */
@Input() set columns(columns: ColumnConfig[]) {
if (columns) {
@@ -110,6 +130,9 @@ export class EntitySubrecordComponent implements OnChanges {
/** data to be displayed, can also be used as two-way-binding */
@Input() records: T[] = [];
+ /** output the currently displayed records, whenever filters for the user change */
+ @Output() filteredRecordsChange = new EventEmitter(true);
+
/**
* factory method to create a new instance of the displayed Entity type
* used when the user adds a new entity to the list.
@@ -163,7 +186,7 @@ export class EntitySubrecordComponent implements OnChanges {
private router: Router,
private analyticsService: AnalyticsService,
private loggingService: LoggingService,
- public entityRemoveService: EntityRemoveService,
+ public entityRemoveService: EntityActionsService,
private entityMapper: EntityMapperService,
private filterService: FilterService,
) {
@@ -180,6 +203,10 @@ export class EntitySubrecordComponent implements OnChanges {
@Input() getBackgroundColor?: (rec: T) => string = (rec: T) => rec.getColor();
private initDataSource() {
+ this.filter = this.filter ?? ({} as DataFilter);
+ this.filterActiveInactive();
+ this.predicate = this.filterService.getFilterPredicate(this.filter);
+
this.recordsDataSource.data = this.records
.filter(this.predicate)
.map((record) => ({ record }));
@@ -228,8 +255,10 @@ export class EntitySubrecordComponent implements OnChanges {
}
}
}
- if (changes.hasOwnProperty("filter") && this.filter) {
- this.predicate = this.filterService.getFilterPredicate(this.filter);
+ if (
+ (changes.hasOwnProperty("filter") && this.filter) ||
+ changes.hasOwnProperty("showInactive")
+ ) {
reinitDataSource = true;
}
if (changes.hasOwnProperty("columns")) {
@@ -240,6 +269,13 @@ export class EntitySubrecordComponent implements OnChanges {
}
if (changes.hasOwnProperty("columnsToDisplay")) {
this.mediaSubscription.unsubscribe();
+ resetupTable = true;
+ }
+ if (
+ changes.hasOwnProperty("editable") ||
+ changes.hasOwnProperty("selectable")
+ ) {
+ resetupTable = true;
}
if (reinitDataSource) {
@@ -255,6 +291,9 @@ export class EntitySubrecordComponent implements OnChanges {
this.sortDefault();
}
+ this.filteredRecordsChange.emit(
+ this.recordsDataSource.filteredData.map((item) => item.record),
+ );
this.listenToEntityUpdates();
}
@@ -262,7 +301,7 @@ export class EntitySubrecordComponent implements OnChanges {
if (this.entityConstructorIsAvailable()) {
try {
this.entityFormService.extendFormFieldConfig(
- this._columns,
+ this.filteredColumns,
this.getEntityConstructor(),
true,
);
@@ -275,7 +314,7 @@ export class EntitySubrecordComponent implements OnChanges {
private sortDefault() {
if (
this.records.length === 0 ||
- this._columns.length === 0 ||
+ this.filteredColumns.length === 0 ||
this.sort.active
) {
// do not overwrite existing sort
@@ -301,11 +340,10 @@ export class EntitySubrecordComponent implements OnChanges {
private inferDefaultSort(): Sort {
// initial sorting by first column, ensure that not the 'action' column is used
- const sortBy =
- this.columnsToDisplay[0] === "actions"
- ? this.columnsToDisplay[1]
- : this.columnsToDisplay[0];
- const sortByColumn = this._columns.find((c) => c.id === sortBy);
+ const sortBy = this.columnsToDisplay.filter(
+ (c) => c !== "actions" && c !== this.COLUMN_ROW_SELECT,
+ )[0];
+ const sortByColumn = this.filteredColumns.find((c) => c.id === sortBy);
let sortDirection: SortDirection = "asc";
if (
@@ -324,19 +362,12 @@ export class EntitySubrecordComponent implements OnChanges {
this.updateSubscription = this.entityMapper
.receiveUpdates(this.getEntityConstructor())
.pipe(untilDestroyed(this))
- .subscribe(({ entity, type }) => {
- if (type === "new") {
- this.addToTable(entity);
- } else if (type === "remove") {
- this.removeFromDataTable(entity);
- } else if (
- type === "update" &&
- !this.records.find((rec) => rec.getId() === entity.getId())
- ) {
- this.addToTable(entity);
- }
+ .subscribe((next) => {
+ this.records = applyUpdate(this.records, next, true);
- if (!this.predicate(entity)) {
+ if (this.predicate(next.entity)) {
+ this.initDataSource();
+ } else {
// hide after a short delay to give a signal in the UI why records disappear by showing the changed values first
setTimeout(() => this.initDataSource(), 5000);
}
@@ -348,7 +379,7 @@ export class EntitySubrecordComponent implements OnChanges {
if (this.screenWidthObserver.isDesktop()) {
if (!row.formGroup) {
row.formGroup = this.entityFormService.createFormGroup(
- this._columns,
+ this.filteredColumns,
row.record,
true,
);
@@ -385,20 +416,6 @@ export class EntitySubrecordComponent implements OnChanges {
row.formGroup = null;
}
- private removeFromDataTable(deleted: T) {
- // use setter so datasource is also updated
- this.records = this.records.filter(
- (rec) => rec.getId() !== deleted.getId(),
- );
- this.initDataSource();
- }
-
- private addToTable(record: T) {
- // use setter so datasource is also updated
- this.records = [record].concat(this.records);
- this.initDataSource();
- }
-
/**
* Create a new entity.
* The entity is only written to the database when the user saves this record which is newly added in edit mode.
@@ -443,12 +460,32 @@ export class EntitySubrecordComponent implements OnChanges {
* resets columnsToDisplay depending on current screensize
*/
private setupTable() {
- if (this._columns !== undefined && this.screenWidth !== undefined) {
- this.columnsToDisplay = this._columns
- .filter((col) => this.isVisible(col))
- .map((col) => col.id);
- this.columnsToDisplay.unshift("actions");
+ let columns =
+ this.columnsToDisplay?.filter((c) =>
+ this.filteredColumns.some((column) => column.id === c),
+ ) ?? [];
+
+ if (
+ !(columns.length > 0) &&
+ this.filteredColumns !== undefined &&
+ this.screenWidth !== undefined
+ ) {
+ columns = [
+ ...this._columns
+ .filter((col) => this.isVisible(col))
+ .map((col) => col.id),
+ ];
+ }
+
+ if (this.editable) {
+ columns.unshift("actions");
+ }
+ if (this.selectable) {
+ // only show selection checkboxes if Output is used in parent
+ columns.unshift(this.COLUMN_ROW_SELECT);
}
+
+ this.columnsToDisplay = [...columns];
}
/**
@@ -468,4 +505,34 @@ export class EntitySubrecordComponent implements OnChanges {
}
return this.screenWidthObserver.currentScreenSize() >= numericValue;
}
+
+ selectRow(row: TableRow, event: MatCheckboxChange) {
+ if (event.checked) {
+ this.selectedRecords.push(row.record);
+ } else {
+ const index = this.selectedRecords.indexOf(row.record);
+ if (index > -1) {
+ this.selectedRecords.splice(index, 1);
+ }
+ }
+
+ this.selectedRecordsChange.emit(this.selectedRecords);
+ }
+
+ filterActiveInactive() {
+ if (this.showInactive) {
+ // @ts-ignore type has issues with getters
+ delete this.filter.isActive;
+ } else {
+ this.filter["isActive"] = true;
+ }
+ }
+
+ setActiveInactiveFilter(newValue: boolean) {
+ if (newValue !== this.showInactive) {
+ this.showInactive = newValue;
+ this.showInactiveChange.emit(newValue);
+ }
+ this.initDataSource();
+ }
}
diff --git a/src/app/core/common-components/entity-subrecord/row-details/row-details.component.html b/src/app/core/common-components/entity-subrecord/row-details/row-details.component.html
index 1a414fccfa..9f55fc6fac 100644
--- a/src/app/core/common-components/entity-subrecord/row-details/row-details.component.html
+++ b/src/app/core/common-components/entity-subrecord/row-details/row-details.component.html
@@ -1,28 +1,34 @@
+
-
-
+
+
+
+
+
-
-
- {{ col.label }}:
-
-
+
+
+ {{ col.label }}:
+
+
+
+
diff --git a/src/app/core/common-components/entity-subrecord/row-details/row-details.component.ts b/src/app/core/common-components/entity-subrecord/row-details/row-details.component.ts
index 9046cf1cd9..4f84211622 100644
--- a/src/app/core/common-components/entity-subrecord/row-details/row-details.component.ts
+++ b/src/app/core/common-components/entity-subrecord/row-details/row-details.component.ts
@@ -14,6 +14,7 @@ import { DynamicComponentDirective } from "../../../config/dynamic-components/dy
import { MatTooltipModule } from "@angular/material/tooltip";
import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
import { DialogButtonsComponent } from "../../../form-dialog/dialog-buttons/dialog-buttons.component";
+import { EntityArchivedInfoComponent } from "../../../entity-details/entity-archived-info/entity-archived-info.component";
/**
* Data interface that must be given when opening the dialog
@@ -44,6 +45,7 @@ export interface DetailsComponentData {
NgIf,
DynamicComponentDirective,
DialogButtonsComponent,
+ EntityArchivedInfoComponent,
],
standalone: true,
})
diff --git a/src/app/core/config/config-fix.ts b/src/app/core/config/config-fix.ts
index 0c160bf969..a7db8c1390 100644
--- a/src/app/core/config/config-fix.ts
+++ b/src/app/core/config/config-fix.ts
@@ -258,20 +258,6 @@ export const defaultJsonConfig = {
]
}
},
- "appConfig:note-details": {
- "topForm": ["date", "warningLevel", "category", "authors", "attachment"]
- },
- "entity:Note": {
- "attributes": [
- {
- "name": "attachment",
- "schema": {
- "label": $localize`Attachment`,
- "dataType": "file"
- }
- }
- ]
- },
"view:site-settings/:id": {
"component": "EntityDetails",
"config": {
@@ -556,15 +542,6 @@ export const defaultJsonConfig = {
]
},
"filters": [
- {
- "id": "isActive",
- "type": "boolean",
- "default": "true",
- "label": $localize`Children`,
- "true": $localize`:Active children filter label - true case:Active`,
- "false": $localize`:Active children filter label - false case:Inactive`,
- "all": $localize`:Active children unselect option:All`
- },
{
"id": "center"
},
@@ -573,6 +550,13 @@ export const defaultJsonConfig = {
"type": "School",
"label": $localize`:Label of schools filter:School`
}
+ ],
+ "exportConfig": [
+ { "label": "Name", "query": "name" },
+ { "label": "Gender", "query": "gender" },
+ { "label": "Date of Birth", "query": "dateOfBirth" },
+ { "label": "School", "query": ".schoolId:toEntities(School).name" },
+ { "label": "more fields can be configured - or all data exported", "query": "projectNumber" }
]
}
},
@@ -771,17 +755,6 @@ export const defaultJsonConfig = {
"type",
"assignedTo"
],
- "filters": [
- {
- "id": "isActive",
- "type": "boolean",
- "default": "true",
- "label": $localize`Status`,
- "true": $localize`:Active records filter label - true case:Active`,
- "false": $localize`:Active records filter label - false case:Inactive`,
- "all": $localize`:Active records unselect option:All`
- },
- ],
"exportConfig": [
{ "label": "Title", "query": "title" },
{ "label": "Type", "query": "type" },
@@ -909,6 +882,19 @@ export const defaultJsonConfig = {
"label": $localize`:Name of a column of a report:Name`,
"query": `.participant:toEntities(Child).name`
},
+ {
+ "query": ".participant:toEntities(Child):getRelated(ChildSchoolRelation, childId)[*isActive=true]",
+ "subQueries": [
+ {
+ "label": "Class",
+ "query": ".schoolClass"
+ },
+ {
+ "label": "School",
+ "query": ".schoolId:toEntities(School).name"
+ },
+ ]
+ },
{
"label": $localize`:Name of a column of a report:Total`,
"query": `total`
diff --git a/src/app/core/config/dynamic-routing/router.service.spec.ts b/src/app/core/config/dynamic-routing/router.service.spec.ts
index e78ab00c14..d4b4dcca37 100644
--- a/src/app/core/config/dynamic-routing/router.service.spec.ts
+++ b/src/app/core/config/dynamic-routing/router.service.spec.ts
@@ -10,9 +10,9 @@ import { ViewConfig } from "./view-config.interface";
import { UserRoleGuard } from "../../permissions/permission-guard/user-role.guard";
import { ApplicationLoadingComponent } from "./empty/application-loading.component";
import { NotFoundComponent } from "./not-found/not-found.component";
-import { componentRegistry } from "../../../dynamic-components";
import { MockedTestingModule } from "../../../utils/mocked-testing.module";
import { AuthGuard } from "../../session/auth.guard";
+import { RoutedViewComponent } from "../../ui/routed-view/routed-view.component";
class TestComponent extends Component {}
@@ -63,24 +63,24 @@ describe("RouterService", () => {
const expectedRoutes = [
{
path: "child",
- loadComponent: componentRegistry.get("ChildrenList"),
- data: {},
+ component: RoutedViewComponent,
+ data: { component: "ChildrenList" },
canDeactivate: [jasmine.any(Function)],
canActivate: [AuthGuard],
},
{
path: "child/:id",
- loadComponent: componentRegistry.get("EntityDetails"),
- data: { config: testViewConfig },
+ component: RoutedViewComponent,
+ data: { component: "EntityDetails", config: testViewConfig },
canDeactivate: [jasmine.any(Function)],
canActivate: [AuthGuard],
},
{
path: "list",
- loadComponent: componentRegistry.get("EntityList"),
+ component: RoutedViewComponent,
+ data: { component: "EntityList", permittedUserRoles: ["user_app"] },
canActivate: [AuthGuard, UserRoleGuard],
canDeactivate: [jasmine.any(Function)],
- data: { permittedUserRoles: ["user_app"] },
},
];
@@ -144,9 +144,11 @@ describe("RouterService", () => {
const router = TestBed.inject
(Router);
expect(router.config.find((r) => r.path === "child").data).toEqual({
+ component: "ChildrenList",
config: { foo: 1 },
});
expect(router.config.find((r) => r.path === "child2").data).toEqual({
+ component: "ChildrenList",
config: { foo: 2 },
});
});
@@ -162,10 +164,10 @@ describe("RouterService", () => {
const expectedRoutes = [
{
path: "list",
- loadComponent: componentRegistry.get("EntityList"),
+ component: RoutedViewComponent,
+ data: { component: "EntityList", permittedUserRoles: ["admin"] },
canActivate: [AuthGuard, UserRoleGuard],
canDeactivate: [jasmine.any(Function)],
- data: { permittedUserRoles: ["admin"] },
},
];
const router = TestBed.inject(Router);
@@ -186,14 +188,4 @@ describe("RouterService", () => {
expect(wildcardRoute).toEqual({ path: "**", component: NotFoundComponent });
});
-
- it("should log a warning if a view config has a component which is not registered", () => {
- const testViewConfigs: ViewConfig[] = [
- { _id: "view:child", component: "Support" },
- ];
-
- service.reloadRouting(testViewConfigs);
-
- expect(mockLoggingService.warn).toHaveBeenCalled();
- });
});
diff --git a/src/app/core/config/dynamic-routing/router.service.ts b/src/app/core/config/dynamic-routing/router.service.ts
index d279b85737..f087dfd363 100644
--- a/src/app/core/config/dynamic-routing/router.service.ts
+++ b/src/app/core/config/dynamic-routing/router.service.ts
@@ -2,16 +2,12 @@ import { inject, Injectable } from "@angular/core";
import { Route, Router } from "@angular/router";
import { ConfigService } from "../config.service";
import { LoggingService } from "../../logging/logging.service";
-import {
- PREFIX_VIEW_CONFIG,
- RouteData,
- ViewConfig,
-} from "./view-config.interface";
+import { PREFIX_VIEW_CONFIG, ViewConfig } from "./view-config.interface";
import { UserRoleGuard } from "../../permissions/permission-guard/user-role.guard";
import { NotFoundComponent } from "./not-found/not-found.component";
-import { ComponentRegistry } from "../../../dynamic-components";
import { AuthGuard } from "../../session/auth.guard";
import { UnsavedChangesService } from "../../entity-details/form/unsaved-changes.service";
+import { RoutedViewComponent } from "../../ui/routed-view/routed-view.component";
/**
* The RouterService dynamically sets up Angular routing from config loaded through the {@link ConfigService}.
@@ -27,7 +23,6 @@ export class RouterService {
private configService: ConfigService,
private router: Router,
private loggingService: LoggingService,
- private components: ComponentRegistry,
) {}
/**
@@ -82,14 +77,15 @@ export class RouterService {
return this.generateRouteFromConfig(view, route);
} else {
return this.generateRouteFromConfig(view, {
- loadComponent: this.components.get(view.component),
path,
+ component: RoutedViewComponent,
+ data: { component: view.component },
});
}
}
private generateRouteFromConfig(view: ViewConfig, route: Route): Route {
- const routeData: RouteData = {};
+ route.data = route.data ?? {};
route.canActivate = [AuthGuard];
route.canDeactivate = [
() => inject(UnsavedChangesService).checkUnsavedChanges(),
@@ -97,14 +93,13 @@ export class RouterService {
if (view.permittedUserRoles) {
route.canActivate.push(UserRoleGuard);
- routeData.permittedUserRoles = view.permittedUserRoles;
+ route.data.permittedUserRoles = view.permittedUserRoles;
}
if (view.config) {
- routeData.config = view.config;
+ route.data.config = view.config;
}
- route.data = routeData;
return route;
}
}
diff --git a/src/app/core/config/dynamic-routing/view-config.interface.ts b/src/app/core/config/dynamic-routing/view-config.interface.ts
index 6f6f4dd94f..c2d311ba55 100644
--- a/src/app/core/config/dynamic-routing/view-config.interface.ts
+++ b/src/app/core/config/dynamic-routing/view-config.interface.ts
@@ -44,10 +44,13 @@ export const PREFIX_VIEW_CONFIG = "view:";
* It contains static data which are used to build components and manage permissions.
* The generic type defines the interface for the component specific configuration.
*
- * It can be accessed through the activated route:
- * ```
- * constructor(private route: ActivatedRoute) {
- * this.route.data.subscribe(routeData: RouteData => { ...what to do with the data })'
+ * The properties given in the `config` object here are automatically assigned to the component as `@Input()` properties.
+ * e.g. for an RouteData `{ config: { "entityType: "Child", "filtered": true } }`
+ * your component `MyViewComponent` will receive the values mapped to its properties:
+ * ```javascript
+ * class MyViewComponent {
+ * @Input() entityType: string;
+ * @Input() filtered: boolean;
* }
* ```
*/
diff --git a/src/app/core/core-components.ts b/src/app/core/core-components.ts
index eb43460952..093bf0b140 100644
--- a/src/app/core/core-components.ts
+++ b/src/app/core/core-components.ts
@@ -225,4 +225,11 @@ export const coreComponents: ComponentTuple[] = [
"./entity-details/related-time-period-entities/related-time-period-entities.component"
).then((c) => c.RelatedTimePeriodEntitiesComponent),
],
+ [
+ "RelatedEntitiesWithSummary",
+ () =>
+ import(
+ "./entity-details/related-entities-with-summary/related-entities-with-summary.component"
+ ).then((c) => c.RelatedEntitiesWithSummaryComponent),
+ ],
];
diff --git a/src/app/core/dashboard/dashboard/dashboard.component.spec.ts b/src/app/core/dashboard/dashboard/dashboard.component.spec.ts
index 4c5692beb7..27b11bd14b 100644
--- a/src/app/core/dashboard/dashboard/dashboard.component.spec.ts
+++ b/src/app/core/dashboard/dashboard/dashboard.component.spec.ts
@@ -1,26 +1,13 @@
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { DashboardComponent } from "./dashboard.component";
-import { ActivatedRoute } from "@angular/router";
-import { BehaviorSubject } from "rxjs";
-import { RouteData } from "../../config/dynamic-routing/view-config.interface";
-import { DynamicComponentConfig } from "../../config/dynamic-components/dynamic-component-config.interface";
describe("DashboardComponent", () => {
let component: DashboardComponent;
let fixture: ComponentFixture;
- let mockRouteData: BehaviorSubject<
- RouteData<{ widgets: DynamicComponentConfig[] }>
- >;
-
beforeEach(() => {
- mockRouteData = new BehaviorSubject({ config: { widgets: [] } });
-
TestBed.configureTestingModule({
imports: [DashboardComponent],
- providers: [
- { provide: ActivatedRoute, useValue: { data: mockRouteData } },
- ],
}).compileComponents();
});
@@ -33,21 +20,4 @@ describe("DashboardComponent", () => {
it("should create", () => {
expect(component).toBeTruthy();
});
-
- it("should init with widget config from activated route", () => {
- const testDashboardConfig = {
- widgets: [
- {
- component: "ProgressDashboard",
- },
- {
- component: "ProgressDashboard",
- },
- ],
- };
-
- mockRouteData.next({ config: testDashboardConfig });
-
- expect(component.widgets).toEqual(testDashboardConfig.widgets);
- });
});
diff --git a/src/app/core/dashboard/dashboard/dashboard.component.ts b/src/app/core/dashboard/dashboard/dashboard.component.ts
index 0ea0fd0444..e0ca13a494 100644
--- a/src/app/core/dashboard/dashboard/dashboard.component.ts
+++ b/src/app/core/dashboard/dashboard/dashboard.component.ts
@@ -15,10 +15,8 @@
* along with ndb-core. If not, see .
*/
-import { Component, OnInit } from "@angular/core";
-import { ActivatedRoute } from "@angular/router";
+import { Component, Input } from "@angular/core";
import { DynamicComponentConfig } from "../../config/dynamic-components/dynamic-component-config.interface";
-import { RouteData } from "../../config/dynamic-routing/view-config.interface";
import { RouteTarget } from "../../../app.routing";
import { NgFor } from "@angular/common";
import { DynamicComponentDirective } from "../../config/dynamic-components/dynamic-component.directive";
@@ -34,16 +32,10 @@ import { DynamicComponentDirective } from "../../config/dynamic-components/dynam
imports: [NgFor, DynamicComponentDirective],
standalone: true,
})
-export class DashboardComponent implements OnInit {
- widgets: DynamicComponentConfig[] = [];
-
- constructor(private activatedRoute: ActivatedRoute) {}
+export class DashboardComponent implements DashboardConfig {
+ @Input() widgets: DynamicComponentConfig[] = [];
+}
- ngOnInit() {
- this.activatedRoute.data.subscribe(
- (data: RouteData<{ widgets: DynamicComponentConfig[] }>) => {
- this.widgets = data.config.widgets;
- },
- );
- }
+export interface DashboardConfig {
+ widgets: DynamicComponentConfig[];
}
diff --git a/src/app/core/database/pouch-database.spec.ts b/src/app/core/database/pouch-database.spec.ts
index 49f9774b61..7d455c9049 100644
--- a/src/app/core/database/pouch-database.spec.ts
+++ b/src/app/core/database/pouch-database.spec.ts
@@ -259,7 +259,11 @@ describe("PouchDatabase tests", () => {
},
];
- const results = await database.putAll(dataWithConflicts);
+ await expectAsync(database.putAll(dataWithConflicts)).toBeRejectedWith([
+ conflictError,
+ jasmine.objectContaining({ id: "4", ok: true }),
+ jasmine.objectContaining({ id: "5", ok: true }),
+ ]);
expect(resolveConflictSpy.calls.allArgs()).toEqual([
[
{
@@ -271,11 +275,6 @@ describe("PouchDatabase tests", () => {
jasmine.objectContaining({ status: 409 }),
],
]);
- expect(results).toEqual([
- conflictError,
- jasmine.objectContaining({ id: "4", ok: true }),
- jasmine.objectContaining({ id: "5", ok: true }),
- ]);
});
it("should correctly determine if database is empty", async () => {
diff --git a/src/app/core/database/pouch-database.ts b/src/app/core/database/pouch-database.ts
index 8a3ae8e649..90fc67fdd8 100644
--- a/src/app/core/database/pouch-database.ts
+++ b/src/app/core/database/pouch-database.ts
@@ -211,7 +211,8 @@ export class PouchDatabase extends Database {
* Save an array of documents to the database
* @param objects the documents to be saved
* @param forceOverwrite whether conflicting versions should be overwritten
- * @returns array holding `{ ok: true, ... }` or `{ error: true, ... }` depending on whether the document could be saved
+ * @returns array with the result for each object to be saved, if any item fails to be saved, this returns a rejected Promise.
+ * The save can partially fail and return a mix of success and error states in the array (e.g. `[{ ok: true, ... }, { error: true, ... }]`)
*/
async putAll(objects: any[], forceOverwrite = false): Promise {
if (forceOverwrite) {
@@ -227,11 +228,17 @@ export class PouchDatabase extends Database {
if (result.status === 409) {
results[i] = await this.resolveConflict(
objects.find((obj) => obj._id === result.id),
- false,
+ forceOverwrite,
result,
- ).catch((e) => e);
+ ).catch((e) => {
+ return new DatabaseException(e);
+ });
}
}
+
+ if (results.some((r) => r instanceof Error)) {
+ return Promise.reject(results);
+ }
return results;
}
diff --git a/src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.html b/src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.html
new file mode 100644
index 0000000000..dc0ba188be
--- /dev/null
+++ b/src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.html
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ a.label }}
+
+
+
+
+
+
diff --git a/src/app/child-dev-project/attendance/activities-overview/activities-overview.component.scss b/src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.scss
similarity index 100%
rename from src/app/child-dev-project/attendance/activities-overview/activities-overview.component.scss
rename to src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.scss
diff --git a/src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.spec.ts b/src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.spec.ts
new file mode 100644
index 0000000000..9854810c04
--- /dev/null
+++ b/src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.spec.ts
@@ -0,0 +1,48 @@
+import {
+ ComponentFixture,
+ fakeAsync,
+ TestBed,
+ tick,
+} from "@angular/core/testing";
+
+import { EntityActionsMenuComponent } from "./entity-actions-menu.component";
+import { EntityActionsService } from "../../entity/entity-actions/entity-actions.service";
+import { MockedTestingModule } from "../../../utils/mocked-testing.module";
+
+describe("EntityActionsMenuComponent", () => {
+ let component: EntityActionsMenuComponent;
+ let fixture: ComponentFixture;
+
+ let mockEntityRemoveService: jasmine.SpyObj;
+
+ beforeEach(() => {
+ mockEntityRemoveService = jasmine.createSpyObj(["delete"]);
+ TestBed.configureTestingModule({
+ imports: [EntityActionsMenuComponent, MockedTestingModule],
+ providers: [
+ { provide: EntityActionsService, useValue: mockEntityRemoveService },
+ ],
+ });
+ fixture = TestBed.createComponent(EntityActionsMenuComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it("should create", () => {
+ expect(component).toBeTruthy();
+ });
+
+ it("should emit actionTriggered Output upon action", fakeAsync(() => {
+ mockEntityRemoveService.delete.and.resolveTo(true);
+
+ let actionEvent;
+ component.actionTriggered.subscribe((x) => (actionEvent = x));
+
+ component.executeAction(
+ component.defaultActions.find((x) => x.action === "delete"),
+ );
+ tick();
+
+ expect(actionEvent).toBe("delete");
+ }));
+});
diff --git a/src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts b/src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
new file mode 100644
index 0000000000..625821d4af
--- /dev/null
+++ b/src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
@@ -0,0 +1,119 @@
+import {
+ Component,
+ EventEmitter,
+ Input,
+ OnChanges,
+ Output,
+ SimpleChanges,
+} from "@angular/core";
+import { EntityActionsService } from "../../entity/entity-actions/entity-actions.service";
+import { Entity } from "../../entity/model/entity";
+import { NgForOf, NgIf } from "@angular/common";
+import { MatButtonModule } from "@angular/material/button";
+import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
+import { MatMenuModule } from "@angular/material/menu";
+import { Angulartics2Module } from "angulartics2";
+import { DisableEntityOperationDirective } from "../../permissions/permission-directive/disable-entity-operation.directive";
+import { IconProp } from "@fortawesome/fontawesome-svg-core";
+import { EntityAction } from "../../permissions/permission-types";
+import { MatTooltipModule } from "@angular/material/tooltip";
+
+export type EntityMenuAction = "archive" | "anonymize" | "delete";
+type EntityMenuActionItem = {
+ action: EntityMenuAction;
+ execute: (entity: Entity, navigateOnDelete?: boolean) => Promise;
+ permission?: EntityAction;
+ icon: IconProp;
+ label: string;
+ tooltip?: string;
+};
+
+@Component({
+ selector: "app-entity-actions-menu",
+ templateUrl: "./entity-actions-menu.component.html",
+ styleUrls: ["./entity-actions-menu.component.scss"],
+ standalone: true,
+ imports: [
+ NgIf,
+ MatButtonModule,
+ FontAwesomeModule,
+ MatMenuModule,
+ Angulartics2Module,
+ DisableEntityOperationDirective,
+ NgForOf,
+ MatTooltipModule,
+ ],
+})
+export class EntityActionsMenuComponent implements OnChanges {
+ @Input() entity: Entity;
+
+ /**
+ * whether the "delete" action will trigger a navigation back to the parent list.
+ * This is useful when the entity is deleted from a fullscreen detail view but not for an overlay.
+ */
+ @Input() navigateOnDelete: boolean = false;
+
+ @Output() actionTriggered = new EventEmitter();
+
+ /**
+ * The actions being displayed as menu items.
+ */
+ actions: EntityMenuActionItem[];
+
+ readonly defaultActions: EntityMenuActionItem[] = [
+ {
+ action: "archive",
+ execute: (e) => this.entityRemoveService.archive(e),
+ permission: "update",
+ icon: "box-archive",
+ label: $localize`:entity context menu:Archive`,
+ tooltip: $localize`:entity context menu tooltip:Mark the record as inactive, hiding it from lists by default while keeping the data.`,
+ },
+ {
+ action: "anonymize",
+ execute: (e) => this.entityRemoveService.anonymize(e),
+ permission: "update",
+ icon: "user-secret",
+ label: $localize`:entity context menu:Anonymize`,
+ tooltip: $localize`:entity context menu tooltip:Remove all personal data and keep an archived basic record for statistical reporting.`,
+ },
+ {
+ action: "delete",
+ execute: (e, nav) => this.entityRemoveService.delete(e, nav),
+ permission: "delete",
+ icon: "trash",
+ label: $localize`:entity context menu:Delete`,
+ tooltip: $localize`:entity context menu tooltip:Remove the record completely from the database.`,
+ },
+ ];
+
+ constructor(private entityRemoveService: EntityActionsService) {}
+
+ ngOnChanges(changes: SimpleChanges): void {
+ if (changes.entity) {
+ this.filterAvailableActions();
+ }
+ }
+
+ private filterAvailableActions() {
+ this.actions = this.defaultActions.filter((action) => {
+ switch (action.action) {
+ case "archive":
+ return this.entity?.isActive && !this.entity?.anonymized;
+ case "anonymize":
+ return (
+ !this.entity?.anonymized && this.entity?.getConstructor().hasPII
+ );
+ default:
+ return true;
+ }
+ });
+ }
+
+ async executeAction(action: EntityMenuActionItem) {
+ const result = await action.execute(this.entity, this.navigateOnDelete);
+ if (result) {
+ this.actionTriggered.emit(action.action);
+ }
+ }
+}
diff --git a/src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html b/src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
new file mode 100644
index 0000000000..a86f54544a
--- /dev/null
+++ b/src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
@@ -0,0 +1,34 @@
+
+
+
+
+
+ This record has been anonymized. Details containing personal information
+ have been deleted and cannot be restored. For statistical reporting, this
+ basic record has been kept.
+
+
+
+ This record is archived and will be be hidden from lists and select
+ options by default.
+
+
+
+
+
+ Reactivate
+
+
+
diff --git a/src/app/core/entity-details/entity-archived-info/entity-archived-info.component.scss b/src/app/core/entity-details/entity-archived-info/entity-archived-info.component.scss
new file mode 100644
index 0000000000..e6253f7cf6
--- /dev/null
+++ b/src/app/core/entity-details/entity-archived-info/entity-archived-info.component.scss
@@ -0,0 +1,17 @@
+@use "src/styles/variables/colors";
+
+.card {
+ background-color: colors.$grey-transparent;
+}
+
+.card-header {
+ display: flex;
+ align-items: center;
+}
+
+.card-icon {
+ justify-content: center;
+ align-items: center;
+ display: flex;
+ margin: 0;
+}
diff --git a/src/app/core/entity-details/entity-archived-info/entity-archived-info.component.spec.ts b/src/app/core/entity-details/entity-archived-info/entity-archived-info.component.spec.ts
new file mode 100644
index 0000000000..9ac50cea43
--- /dev/null
+++ b/src/app/core/entity-details/entity-archived-info/entity-archived-info.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from "@angular/core/testing";
+
+import { EntityArchivedInfoComponent } from "./entity-archived-info.component";
+import { EntityActionsService } from "../../entity/entity-actions/entity-actions.service";
+
+describe("EntityArchivedInfoComponent", () => {
+ let component: EntityArchivedInfoComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [EntityArchivedInfoComponent],
+ providers: [{ provide: EntityActionsService, useValue: null }],
+ });
+ fixture = TestBed.createComponent(EntityArchivedInfoComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it("should create", () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/core/entity-details/entity-archived-info/entity-archived-info.component.ts b/src/app/core/entity-details/entity-archived-info/entity-archived-info.component.ts
new file mode 100644
index 0000000000..0724b65363
--- /dev/null
+++ b/src/app/core/entity-details/entity-archived-info/entity-archived-info.component.ts
@@ -0,0 +1,23 @@
+import { Component, Input } from "@angular/core";
+import { CommonModule } from "@angular/common";
+import { MatCardModule } from "@angular/material/card";
+import { MatButtonModule } from "@angular/material/button";
+import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
+import { Entity } from "../../entity/model/entity";
+import { EntityActionsService } from "../../entity/entity-actions/entity-actions.service";
+
+/**
+ * Informs users that the entity is inactive (or anonymized) and provides options to change the status.
+ */
+@Component({
+ selector: "app-entity-archived-info",
+ standalone: true,
+ imports: [CommonModule, MatCardModule, MatButtonModule, FontAwesomeModule],
+ templateUrl: "./entity-archived-info.component.html",
+ styleUrls: ["./entity-archived-info.component.scss"],
+})
+export class EntityArchivedInfoComponent {
+ @Input() entity: Entity;
+
+ constructor(public entityRemoveService: EntityActionsService) {}
+}
diff --git a/src/app/core/entity-details/entity-archived-info/entity-archived-info.stories.ts b/src/app/core/entity-details/entity-archived-info/entity-archived-info.stories.ts
new file mode 100644
index 0000000000..876b0cf72e
--- /dev/null
+++ b/src/app/core/entity-details/entity-archived-info/entity-archived-info.stories.ts
@@ -0,0 +1,31 @@
+import { applicationConfig, Meta, StoryFn } from "@storybook/angular";
+import { StorybookBaseModule } from "../../../utils/storybook-base.module";
+import { importProvidersFrom } from "@angular/core";
+import { EntityArchivedInfoComponent } from "./entity-archived-info.component";
+import { Entity } from "../../entity/model/entity";
+
+export default {
+ title: "Core/> App Layout/Entity Details/Entity Archived Info",
+ component: EntityArchivedInfoComponent,
+ decorators: [
+ applicationConfig({
+ providers: [importProvidersFrom(StorybookBaseModule)],
+ }),
+ ],
+} as Meta;
+
+const Template: StoryFn = (
+ args: EntityArchivedInfoComponent,
+) => ({
+ props: args,
+});
+
+export const Archived = Template.bind({});
+Archived.args = {
+ entity: Object.assign(new Entity(), { inactive: true }),
+};
+
+export const Anonymized = Template.bind({});
+Anonymized.args = {
+ entity: Object.assign(new Entity(), { inactive: true, anonymized: true }),
+};
diff --git a/src/app/core/entity-details/entity-details/entity-details.component.html b/src/app/core/entity-details/entity-details/entity-details.component.html
index 9c03c4f7fe..3966c2e644 100644
--- a/src/app/core/entity-details/entity-details/entity-details.component.html
+++ b/src/app/core/entity-details/entity-details/entity-details.component.html
@@ -17,7 +17,7 @@
- {{ entity?.toString() }}
+ {{ record?.toString() }}
-
-
-
+
-
-
-
- Delete
-
-
+
{{ componentConfig.title }}
-
+
diff --git a/src/app/core/entity-details/entity-details/entity-details.component.spec.ts b/src/app/core/entity-details/entity-details/entity-details.component.spec.ts
index 796b31eb03..f324442a7b 100644
--- a/src/app/core/entity-details/entity-details/entity-details.component.spec.ts
+++ b/src/app/core/entity-details/entity-details/entity-details.component.spec.ts
@@ -6,22 +6,20 @@ import {
waitForAsync,
} from "@angular/core/testing";
import { EntityDetailsComponent } from "./entity-details.component";
-import { Observable, of, Subscriber } from "rxjs";
-import { ActivatedRoute, Router } from "@angular/router";
+import { Router } from "@angular/router";
import { EntityDetailsConfig, PanelConfig } from "../EntityDetailsConfig";
import { Child } from "../../../child-dev-project/children/model/child";
import { ChildrenService } from "../../../child-dev-project/children/children.service";
import { MockedTestingModule } from "../../../utils/mocked-testing.module";
-import { EntityRemoveService } from "../../entity/entity-remove.service";
+import { EntityActionsService } from "../../entity/entity-actions/entity-actions.service";
import { EntityAbility } from "../../permissions/ability/entity-ability";
import { EntityMapperService } from "../../entity/entity-mapper/entity-mapper.service";
+import { SimpleChange } from "@angular/core";
describe("EntityDetailsComponent", () => {
let component: EntityDetailsComponent;
let fixture: ComponentFixture;
- let routeObserver: Subscriber;
-
const routeConfig: EntityDetailsConfig = {
entity: "Child",
panels: [
@@ -44,21 +42,9 @@ describe("EntityDetailsComponent", () => {
},
],
};
- const mockedRoute = {
- paramMap: new Observable((observer) => {
- routeObserver = observer;
- observer.next({ get: () => "new" });
- }),
- data: of({ config: routeConfig }),
- snapshot: {
- queryParamMap: {
- get: () => "",
- },
- },
- };
let mockChildrenService: jasmine.SpyObj;
- let mockEntityRemoveService: jasmine.SpyObj;
+ let mockEntityRemoveService: jasmine.SpyObj;
let mockAbility: jasmine.SpyObj;
beforeEach(waitForAsync(() => {
@@ -74,9 +60,8 @@ describe("EntityDetailsComponent", () => {
TestBed.configureTestingModule({
imports: [EntityDetailsComponent, MockedTestingModule.withState()],
providers: [
- { provide: ActivatedRoute, useValue: mockedRoute },
{ provide: ChildrenService, useValue: mockChildrenService },
- { provide: EntityRemoveService, useValue: mockEntityRemoveService },
+ { provide: EntityActionsService, useValue: mockEntityRemoveService },
{ provide: EntityAbility, useValue: mockAbility },
],
}).compileComponents();
@@ -85,6 +70,12 @@ describe("EntityDetailsComponent", () => {
beforeEach(() => {
fixture = TestBed.createComponent(EntityDetailsComponent);
component = fixture.componentInstance;
+
+ Object.assign(component, routeConfig);
+ component.ngOnChanges(
+ simpleChangesFor(component, ...Object.keys(routeConfig)),
+ );
+
fixture.detectChanges();
});
@@ -97,7 +88,8 @@ describe("EntityDetailsComponent", () => {
TestBed.inject(EntityMapperService).save(testChild);
tick();
component.creatingNew = false;
- routeObserver.next({ get: () => testChild.getId() });
+ component.id = testChild.getId();
+ component.ngOnChanges(simpleChangesFor(component, "id"));
tick();
component.panels.forEach((p) =>
@@ -117,12 +109,13 @@ describe("EntityDetailsComponent", () => {
tick();
spyOn(entityMapper, "load").and.callThrough();
- routeObserver.next({ get: () => testChild.getId() });
+ component.id = testChild.getId();
+ component.ngOnChanges(simpleChangesFor(component, "id"));
expect(component.isLoading).toBeTrue();
tick();
expect(entityMapper.load).toHaveBeenCalledWith(Child, testChild.getId());
- expect(component.entity).toBe(testChild);
+ expect(component.record).toBe(testChild);
expect(component.isLoading).toBeFalse();
}));
@@ -130,7 +123,16 @@ describe("EntityDetailsComponent", () => {
mockAbility.cannot.and.returnValue(true);
const router = fixture.debugElement.injector.get(Router);
spyOn(router, "navigate");
- routeObserver.next({ get: () => "new" });
+ component.id = "new";
+ component.ngOnChanges(simpleChangesFor(component, "id"));
expect(router.navigate).toHaveBeenCalled();
});
});
+
+function simpleChangesFor(component, ...properties: string[]) {
+ const changes = {};
+ for (const p of properties) {
+ changes[p] = new SimpleChange(null, component[p], true);
+ }
+ return changes;
+}
diff --git a/src/app/core/entity-details/entity-details/entity-details.component.ts b/src/app/core/entity-details/entity-details/entity-details.component.ts
index 462543b54b..bc7f1fe164 100644
--- a/src/app/core/entity-details/entity-details/entity-details.component.ts
+++ b/src/app/core/entity-details/entity-details/entity-details.component.ts
@@ -1,5 +1,5 @@
-import { Component } from "@angular/core";
-import { ActivatedRoute, Router } from "@angular/router";
+import { Component, Input, OnChanges, SimpleChanges } from "@angular/core";
+import { Router } from "@angular/router";
import {
EntityDetailsConfig,
Panel,
@@ -8,9 +8,7 @@ import {
} from "../EntityDetailsConfig";
import { Entity, EntityConstructor } from "../../entity/model/entity";
import { EntityMapperService } from "../../entity/entity-mapper/entity-mapper.service";
-import { RouteData } from "../../config/dynamic-routing/view-config.interface";
import { AnalyticsService } from "../../analytics/analytics.service";
-import { EntityRemoveService } from "../../entity/entity-remove.service";
import { EntityAbility } from "../../permissions/ability/entity-ability";
import { RouteTarget } from "../../../app.routing";
import { EntityRegistry } from "../../entity/database-entity.decorator";
@@ -28,6 +26,11 @@ import { DynamicComponentDirective } from "../../config/dynamic-components/dynam
import { DisableEntityOperationDirective } from "../../permissions/permission-directive/disable-entity-operation.directive";
import { LoggingService } from "../../logging/logging.service";
import { UnsavedChangesService } from "../form/unsaved-changes.service";
+import { EntityActionsMenuComponent } from "../entity-actions-menu/entity-actions-menu.component";
+import { EntityArchivedInfoComponent } from "../entity-archived-info/entity-archived-info.component";
+import { filter } from "rxjs/operators";
+import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
+import { Subscription } from "rxjs";
/**
* This component can be used to display an entity in more detail.
@@ -36,6 +39,7 @@ import { UnsavedChangesService } from "../form/unsaved-changes.service";
* The subcomponents will be provided with the Entity object and the creating new status, as well as its static config.
*/
@RouteTarget("EntityDetails")
+@UntilDestroy()
@Component({
selector: "app-entity-details",
templateUrl: "./entity-details.component.html",
@@ -55,67 +59,83 @@ import { UnsavedChangesService } from "../form/unsaved-changes.service";
ViewTitleComponent,
DynamicComponentDirective,
DisableEntityOperationDirective,
+ EntityActionsMenuComponent,
+ EntityArchivedInfoComponent,
],
})
-export class EntityDetailsComponent {
- entity: Entity;
+export class EntityDetailsComponent implements EntityDetailsConfig, OnChanges {
creatingNew = false;
isLoading = true;
+ private changesSubscription: Subscription;
- panels: Panel[] = [];
- config: EntityDetailsConfig;
+ /** @deprecated use "entityType" instead, this remains for config backwards compatibility */
+ @Input() set entity(v: string) {
+ this.entityType = v;
+ }
+ @Input() entityType: string;
entityConstructor: EntityConstructor;
+ @Input() id: string;
+ record: Entity;
+
+ @Input() panels: Panel[] = [];
+
constructor(
private entityMapperService: EntityMapperService,
- private route: ActivatedRoute,
private router: Router,
private analyticsService: AnalyticsService,
- public entityRemoveService: EntityRemoveService,
private ability: EntityAbility,
private entities: EntityRegistry,
private logger: LoggingService,
public unsavedChanges: UnsavedChangesService,
- ) {
- this.route.data.subscribe((data: RouteData) => {
- this.config = data.config;
- this.entityConstructor = this.entities.get(this.config.entity);
- this.setInitialPanelsConfig();
- this.route.paramMap.subscribe((params) =>
- this.loadEntity(params.get("id")),
- );
- });
+ ) {}
+
+ ngOnChanges(changes: SimpleChanges): void {
+ if (changes.entity || changes.entityType) {
+ this.entityConstructor = this.entities.get(this.entityType);
+ }
+ if (changes.id) {
+ this.loadEntity(this.id);
+ this.subscribeToEntityChanges();
+ // `initPanels()` is already called inside `loadEntity()`
+ } else if (changes.panels) {
+ this.initPanels();
+ }
}
- private loadEntity(id: string) {
+ private subscribeToEntityChanges() {
+ this.changesSubscription?.unsubscribe();
+ this.changesSubscription = this.entityMapperService
+ .receiveUpdates(this.entityConstructor)
+ .pipe(
+ filter(({ entity }) => entity.getId() === this.id),
+ filter(({ type }) => type !== "remove"),
+ untilDestroyed(this),
+ )
+ .subscribe(({ entity }) => (this.record = entity));
+ }
+
+ private async loadEntity(id: string) {
if (id === "new") {
if (this.ability.cannot("create", this.entityConstructor)) {
this.router.navigate([""]);
return;
}
- this.entity = new this.entityConstructor();
+ this.record = new this.entityConstructor();
this.creatingNew = true;
- this.setFullPanelsConfig();
} else {
this.creatingNew = false;
- this.entityMapperService
- .load(this.entityConstructor, id)
- .then((entity) => {
- this.entity = entity;
- this.setFullPanelsConfig();
- });
+ this.record = await this.entityMapperService.load(
+ this.entityConstructor,
+ id,
+ );
}
+ this.initPanels();
+ this.isLoading = false;
}
- private setInitialPanelsConfig() {
- this.panels = this.config.panels.map((p) => ({
- title: p.title,
- components: [],
- }));
- }
-
- private setFullPanelsConfig() {
- this.panels = this.config.panels.map((p) => ({
+ private initPanels() {
+ this.panels = this.panels.map((p) => ({
title: p.title,
components: p.components.map((c) => ({
title: c.title,
@@ -123,12 +143,11 @@ export class EntityDetailsComponent {
config: this.getPanelConfig(c),
})),
}));
- this.isLoading = false;
}
private getPanelConfig(c: PanelComponent): PanelConfig {
let panelConfig: PanelConfig = {
- entity: this.entity,
+ entity: this.record,
creatingNew: this.creatingNew,
};
if (typeof c.config === "object" && !Array.isArray(c.config)) {
@@ -150,8 +169,8 @@ export class EntityDetailsComponent {
trackTabChanged(index: number) {
this.analyticsService.eventTrack("details_tab_changed", {
- category: this.config?.entity,
- label: this.config.panels[index].title,
+ category: this.entityType,
+ label: this.panels[index].title,
});
}
}
diff --git a/src/app/core/entity-details/entity-details/entity-details.stories.ts b/src/app/core/entity-details/entity-details/entity-details.stories.ts
new file mode 100644
index 0000000000..227e799ff1
--- /dev/null
+++ b/src/app/core/entity-details/entity-details/entity-details.stories.ts
@@ -0,0 +1,57 @@
+import { applicationConfig, Meta, StoryFn } from "@storybook/angular";
+import { StorybookBaseModule } from "../../../utils/storybook-base.module";
+import { importProvidersFrom } from "@angular/core";
+import { EntityDetailsComponent } from "./entity-details.component";
+import { Child } from "../../../child-dev-project/children/model/child";
+import { EntityDetailsConfig } from "../EntityDetailsConfig";
+
+const demoEntity = Child.create("John Doe");
+demoEntity._rev = "1"; // make not "isNew"
+
+const config: EntityDetailsConfig = {
+ entity: "Child",
+ panels: [
+ {
+ title: $localize`:Panel title:Basic Information`,
+ components: [
+ {
+ title: "",
+ component: "Form",
+ config: {
+ cols: [
+ ["photo"],
+ ["name", "projectNumber", "admissionDate"],
+ ["center", "phone"],
+ ],
+ headers: [null, "Personal Information", "Contact Details"],
+ },
+ },
+ ],
+ },
+ { title: "Other Details", components: [] },
+ ],
+};
+
+export default {
+ title: "Core/> App Layout/Entity Details",
+ component: EntityDetailsComponent,
+ decorators: [
+ applicationConfig({
+ providers: [
+ importProvidersFrom(StorybookBaseModule.withData([demoEntity])),
+ ],
+ }),
+ ],
+} as Meta;
+
+const Template: StoryFn = (
+ args: EntityDetailsComponent,
+) => ({
+ props: args,
+});
+
+export const Primary = Template.bind({});
+Primary.args = {
+ id: demoEntity.getId(false),
+ ...config,
+};
diff --git a/src/app/core/entity-details/form/form.component.html b/src/app/core/entity-details/form/form.component.html
index 78e724ab27..8fe88ce3e6 100644
--- a/src/app/core/entity-details/form/form.component.html
+++ b/src/app/core/entity-details/form/form.component.html
@@ -20,7 +20,7 @@
Cancel
-
+
diff --git a/src/app/core/entity-details/related-entities/related-entities.component.ts b/src/app/core/entity-details/related-entities/related-entities.component.ts
index 7e5a4eb93e..ddefb12814 100644
--- a/src/app/core/entity-details/related-entities/related-entities.component.ts
+++ b/src/app/core/entity-details/related-entities/related-entities.component.ts
@@ -44,6 +44,8 @@ export class RelatedEntitiesComponent implements OnInit {
@Input() filter?: DataFilter;
+ @Input() showInactive: boolean;
+
data: E[] = [];
isLoading = false;
private isArray = false;
@@ -77,6 +79,10 @@ export class RelatedEntitiesComponent implements OnInit {
: this.entity.getId(),
};
+ if (this.showInactive === undefined) {
+ this.showInactive = this.entity.anonymized;
+ }
+
this.isLoading = false;
}
diff --git a/src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html b/src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
index ab15fe4954..52a97c8865 100644
--- a/src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
+++ b/src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
@@ -1,4 +1,4 @@
-
+
Currently there is no active entry. To add a new entry, click on the
-
-
-
- Include inactive past records
-
-
diff --git a/src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.spec.ts b/src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.spec.ts
index e5ad40422f..8977992c20 100644
--- a/src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.spec.ts
+++ b/src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.spec.ts
@@ -144,16 +144,6 @@ describe("RelatedTimePeriodEntitiesComponent", () => {
).toBeTrue();
});
- it("should only show active relations by default", async () => {
- const loadType = spyOn(entityMapper, "loadType");
- loadType.and.resolveTo([active1, active2, inactive]);
-
- await component.ngOnInit();
-
- expect(loadType).toHaveBeenCalledWith("ChildSchoolRelation");
- expect(getFilteredData(component)).toEqual([active1, active2]);
- });
-
it("should show all relations if configured; with active ones being highlighted", async () => {
const loadType = spyOn(entityMapper, "loadType");
loadType.and.resolveTo([active1, active2, inactive]);
diff --git a/src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts b/src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
index 43009b8f9f..84433d354c 100644
--- a/src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
+++ b/src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
@@ -12,7 +12,6 @@ import { PillComponent } from "../../common-components/pill/pill.component";
import { ChildSchoolRelation } from "../../../child-dev-project/children/model/childSchoolRelation";
import { RelatedEntitiesComponent } from "../related-entities/related-entities.component";
import { TimePeriod } from "./time-period";
-import { DataFilter } from "../../common-components/entity-subrecord/entity-subrecord/entity-subrecord-config";
/**
* Display a list of entity subrecords (entities related to the current entity details view)
@@ -65,25 +64,18 @@ export class RelatedTimePeriodEntitiesComponent
hasCurrentlyActiveEntry: boolean;
async ngOnInit() {
+ this.onIsActiveFilterChange(this.showInactive);
await super.initData();
-
- this.filterActiveInactive();
}
- filterActiveInactive() {
+ onIsActiveFilterChange(newValue: boolean) {
this.hasCurrentlyActiveEntry = this.data.some((record) => record.isActive);
- const filters = this.filter ?? {};
if (this.showInactive) {
this.backgroundColorFn = (r: E) => r.getColor();
- // @ts-ignore type has issues with getters
- delete filters.isActive;
} else {
this.backgroundColorFn = undefined; // Do not highlight active ones when only active are shown
- filters["isActive"] = true;
}
- // recreate to trigger change detection and update displayed data
- this.filter = { ...filters } as DataFilter;
}
generateNewRecordFactory() {
diff --git a/src/app/core/entity-details/related-time-period-entities/time-period.ts b/src/app/core/entity-details/related-time-period-entities/time-period.ts
index fc07636e95..d101d32810 100644
--- a/src/app/core/entity-details/related-time-period-entities/time-period.ts
+++ b/src/app/core/entity-details/related-time-period-entities/time-period.ts
@@ -26,6 +26,11 @@ export class TimePeriod extends Entity {
* Returns true if this relation is currently active
*/
get isActive(): boolean {
+ if (this.inactive) {
+ // manual archiving of records takes precendence
+ return false;
+ }
+
return this.isActiveAt(new Date());
}
diff --git a/src/app/core/entity-list/EntityListConfig.ts b/src/app/core/entity-list/EntityListConfig.ts
index a942e31ff7..0491f51340 100644
--- a/src/app/core/entity-list/EntityListConfig.ts
+++ b/src/app/core/entity-list/EntityListConfig.ts
@@ -16,11 +16,6 @@ export interface EntityListConfig {
*/
entity?: string;
- /**
- * Placeholder string in the filter input
- */
- filterPlaceholder?: string;
-
/**
* The columns to be displayed in the table
*/
diff --git a/src/app/core/entity-list/duplicate-records/duplicate-records.service.spec.ts b/src/app/core/entity-list/duplicate-records/duplicate-records.service.spec.ts
new file mode 100644
index 0000000000..e93eb156f0
--- /dev/null
+++ b/src/app/core/entity-list/duplicate-records/duplicate-records.service.spec.ts
@@ -0,0 +1,87 @@
+import { TestBed } from "@angular/core/testing";
+import { DuplicateRecordService } from "./duplicate-records.service";
+import { EntityMapperService } from "../../entity/entity-mapper/entity-mapper.service";
+import {
+ DatabaseEntity,
+ entityRegistry,
+ EntityRegistry,
+} from "../../entity/database-entity.decorator";
+import { Database } from "../../database/database";
+import { SessionService } from "../../session/session-service/session.service";
+import { Entity } from "../../entity/model/entity";
+import { DatabaseField } from "../../entity/database-field.decorator";
+import { CoreModule } from "../../core.module";
+import { ComponentRegistry } from "../../../dynamic-components";
+import { UpdateMetadata } from "../../entity/model/update-metadata";
+import { MatDialog } from "@angular/material/dialog";
+import { MatSnackBar } from "@angular/material/snack-bar";
+import { FileService } from "../../../features/file/file.service";
+
+describe("DuplicateRecordsService", () => {
+ let service: DuplicateRecordService;
+ let entityMapperService: EntityMapperService;
+
+ @DatabaseEntity("DuplicateTestEntity")
+ class DuplicateTestEntity extends Entity {
+ static toStringAttributes = ["name"];
+ @DatabaseField() name: String;
+ @DatabaseField() boolProperty: boolean;
+ @DatabaseField() created: UpdateMetadata;
+ @DatabaseField() updated: UpdateMetadata;
+ @DatabaseField() inactive: boolean;
+ }
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [CoreModule],
+ providers: [
+ DuplicateRecordService,
+ Database,
+ EntityMapperService,
+ SessionService,
+ { provide: EntityRegistry, useValue: entityRegistry },
+ { provide: MatDialog, useValue: {} },
+ { provide: MatSnackBar, useValue: {} },
+ { provide: FileService, useValue: {} },
+ ComponentRegistry,
+ ],
+ });
+ service = TestBed.inject(DuplicateRecordService);
+ entityMapperService = TestBed.inject(EntityMapperService);
+ });
+
+ it("should be created", () => {
+ expect(service).toBeTruthy();
+ });
+
+ it("should transform data correctly", () => {
+ const duplicateTest = new DuplicateTestEntity();
+ duplicateTest.name = "TestName";
+ duplicateTest.boolProperty = true;
+
+ const originalData = [duplicateTest];
+ const transformedData = service.clone(originalData);
+
+ expect(transformedData[0]).toBeInstanceOf(Entity);
+ expect(transformedData[0]._id).toBeDefined();
+ expect(transformedData[0]._id).not.toBe(duplicateTest["_id"]);
+ expect(transformedData[0].name).toMatch(/^Copy of /);
+ expect(transformedData[0].boolProperty).toBe(true);
+ });
+
+ it("should save duplicate record", async () => {
+ const duplicateTestEntity = new DuplicateTestEntity();
+ duplicateTestEntity.name = "TestName";
+ duplicateTestEntity.boolProperty = true;
+ duplicateTestEntity.inactive = false;
+
+ const originalData = [duplicateTestEntity];
+ const cloneSpy = spyOn(service, "clone").and.callThrough();
+ const saveAllSpy = spyOn(entityMapperService, "saveAll");
+
+ await service.duplicateRecord(originalData);
+
+ expect(cloneSpy).toHaveBeenCalledWith(originalData);
+ expect(saveAllSpy).toHaveBeenCalled();
+ });
+});
diff --git a/src/app/core/entity-list/duplicate-records/duplicate-records.service.ts b/src/app/core/entity-list/duplicate-records/duplicate-records.service.ts
new file mode 100644
index 0000000000..a365400772
--- /dev/null
+++ b/src/app/core/entity-list/duplicate-records/duplicate-records.service.ts
@@ -0,0 +1,48 @@
+import { Injectable } from "@angular/core";
+import { EntityMapperService } from "../../entity/entity-mapper/entity-mapper.service";
+import { EntityRegistry } from "../../entity/database-entity.decorator";
+import { EntitySchemaService } from "../../entity/schema/entity-schema.service";
+import { Entity } from "../../entity/model/entity";
+
+@Injectable({
+ providedIn: "root",
+})
+export class DuplicateRecordService {
+ get: jasmine.Spy;
+ constructor(
+ private entitymapperservice: EntityMapperService,
+ private entityTypes: EntityRegistry,
+ private entityService: EntitySchemaService,
+ ) {}
+
+ async duplicateRecord(sourceData: Entity[]) {
+ const duplicateData = this.clone(sourceData);
+ return await this.entitymapperservice.saveAll(duplicateData);
+ }
+
+ clone(sourceData: Entity[]): any {
+ const duplicateData = [];
+
+ sourceData.map((item: Entity) => {
+ const entityConstructor = item.getConstructor();
+ const keys = [...entityConstructor.schema.keys()].filter(
+ (key) => key !== "_id" && key !== "_rev",
+ );
+ const dbEntity = this.entityService.transformEntityToDatabaseFormat(item);
+ const entityformat = this.entityService.transformDatabaseToEntityFormat(
+ dbEntity,
+ entityConstructor.schema,
+ );
+ const entity = new entityConstructor();
+ const nameAttribute = entityConstructor.toStringAttributes[0];
+ for (const key of keys) {
+ if (nameAttribute === key && nameAttribute !== "entityId") {
+ entityformat[key] = `Copy of ${entityformat[key]}`;
+ }
+ entity[key] = entityformat[key];
+ }
+ duplicateData.push(entity);
+ });
+ return duplicateData;
+ }
+}
diff --git a/src/app/core/entity-list/entity-list/entity-list.component.html b/src/app/core/entity-list/entity-list/entity-list.component.html
index 57305b76a0..fc0e1b6c60 100644
--- a/src/app/core/entity-list/entity-list/entity-list.component.html
+++ b/src/app/core/entity-list/entity-list/entity-list.component.html
@@ -4,10 +4,12 @@
- {{ listName }}
+ {{ title }}
+
+
-
1">
+
1">
-
{{ listName }}
+
{{ title }}
@@ -86,6 +86,8 @@
{{ listName }}
+
+
@@ -127,7 +129,11 @@ {{ listName }}
[columnsToDisplay]="columnsToDisplay"
[isLoading]="isLoading"
[filter]="filterObj"
- [defaultSort]="listConfig?.defaultSort"
+ [defaultSort]="defaultSort"
+ [(selectedRecords)]="selectedRows"
+ [selectable]="!!selectedRows"
+ [showInactive]="showInactive"
+ (filteredRecordsChange)="filteredData = $event"
>
@@ -138,9 +144,7 @@ {{ listName }}
(click)="addNew()"
angulartics2On="click"
angularticsCategory="UserAction"
- [angularticsAction]="
- listName.toLowerCase().replace(' ', '_') + '_add_new'
- "
+ [angularticsAction]="title.toLowerCase().replace(' ', '_') + '_add_new'"
*appDisabledEntityOperation="{
entity: entityConstructor,
operation: 'create'
@@ -171,8 +175,26 @@ {{ listName }}
mat-menu-item
[appExportData]="allEntities"
format="csv"
- [exportConfig]="listConfig?.exportConfig"
- [filename]="listName.replace(' ', '')"
+ [exportConfig]="exportConfig"
+ [filename]="title.replace(' ', '')"
+ angulartics2On="click"
+ [angularticsCategory]="entityConstructor?.ENTITY_TYPE"
+ angularticsAction="list_csv_export"
+ >
+
+ Download all data (.csv)
+
+
+ {{ listName }}
aria-label="download csv"
icon="download"
>
- Download CSV
+ Download current (.csv)
{{ listName }}
Import from file
+
+
+ Bulk Actions
+
+
+
+
+
+
diff --git a/src/app/core/entity-list/entity-list/entity-list.component.scss b/src/app/core/entity-list/entity-list/entity-list.component.scss
index 8e7586cfb8..2b68a35382 100644
--- a/src/app/core/entity-list/entity-list/entity-list.component.scss
+++ b/src/app/core/entity-list/entity-list/entity-list.component.scss
@@ -1,4 +1,6 @@
@use "../../../../styles/variables/breakpoints";
+@use "src/styles/variables/sizes";
+@use "src/styles/variables/colors";
/**
* Aligns the baseline of the filter-field with the baseline
@@ -16,3 +18,12 @@
background-color: white !important;
height: 100%;
}
+
+.bulk-action-button {
+ position: fixed;
+ right: sizes.$large;
+ z-index: 999;
+
+ padding: sizes.$regular;
+ background-color: colors.$background;
+}
diff --git a/src/app/core/entity-list/entity-list/entity-list.component.spec.ts b/src/app/core/entity-list/entity-list/entity-list.component.spec.ts
index b81f9b23de..0ccba24893 100644
--- a/src/app/core/entity-list/entity-list/entity-list.component.spec.ts
+++ b/src/app/core/entity-list/entity-list/entity-list.component.spec.ts
@@ -109,7 +109,13 @@ describe("EntityListComponent", () => {
createComponent();
initComponentInputs();
tick();
- expect(component.columns).toEqual(testConfig.columns);
+ expect(component.columns).toEqual([
+ ...testConfig.columns,
+ "projectNumber",
+ "name",
+ "gender",
+ "religion",
+ ]);
}));
it("should create column groups from config and set correct one", fakeAsync(() => {
@@ -117,7 +123,7 @@ describe("EntityListComponent", () => {
initComponentInputs();
tick();
- expect(component.columnGroups).toEqual(testConfig.columnGroups.groups);
+ expect(component.groups).toEqual(testConfig.columnGroups.groups);
const defaultGroup = testConfig.columnGroups.groups.findIndex(
(g) => g.name === testConfig.columnGroups.default,
);
@@ -184,23 +190,22 @@ describe("EntityListComponent", () => {
it("should automatically initialize values if directly referenced from config", fakeAsync(() => {
mockActivatedRoute.component = EntityListComponent;
- const config = {
- entity: "Child",
- title: "Some title",
- columns: ["name", "gender"],
- };
const entityMapper = TestBed.inject(EntityMapperService);
const children = [new Child(), new Child()];
spyOn(entityMapper, "loadType").and.resolveTo(children);
createComponent();
- routeData.next({ config });
+ component.listConfig = {
+ entity: "Child",
+ title: "Some title",
+ columns: ["name", "gender"],
+ };
+ component.ngOnChanges({ listConfig: undefined });
tick();
expect(component.entityConstructor).toBe(Child);
- expect(component.listConfig).toEqual(config);
expect(component.allEntities).toEqual(children);
- expect(component.listName).toBe("Some title");
+ expect(component.title).toBe("Some title");
const navigateSpy = spyOn(TestBed.inject(Router), "navigate");
component.addNew();
diff --git a/src/app/core/entity-list/entity-list/entity-list.component.ts b/src/app/core/entity-list/entity-list/entity-list.component.ts
index 6de23057e7..6b8eab4254 100644
--- a/src/app/core/entity-list/entity-list/entity-list.component.ts
+++ b/src/app/core/entity-list/entity-list/entity-list.component.ts
@@ -21,7 +21,6 @@ import { EntitySubrecordComponent } from "../../common-components/entity-subreco
import { entityFilterPredicate } from "../../filter/filter-generator/filter-predicate";
import { AnalyticsService } from "../../analytics/analytics.service";
import { RouteTarget } from "../../../app.routing";
-import { RouteData } from "../../config/dynamic-routing/view-config.interface";
import { EntityMapperService } from "../../entity/entity-mapper/entity-mapper.service";
import { EntityRegistry } from "../../entity/database-entity.decorator";
import { ScreenWidthObserver } from "../../../utils/media/screen-size-observer.service";
@@ -43,6 +42,10 @@ import { TabStateModule } from "../../../utils/tab-state/tab-state.module";
import { ViewTitleComponent } from "../../common-components/view-title/view-title.component";
import { ExportDataDirective } from "../../export/export-data-directive/export-data.directive";
import { DisableEntityOperationDirective } from "../../permissions/permission-directive/disable-entity-operation.directive";
+import { DuplicateRecordService } from "../duplicate-records/duplicate-records.service";
+import { MatTooltipModule } from "@angular/material/tooltip";
+import { Sort } from "@angular/material/sort";
+import { ExportColumnConfig } from "../../export/data-transformation-service/export-column-config";
/**
* This component allows to create a full-blown table with pagination, filtering, searching and grouping.
@@ -58,6 +61,7 @@ import { DisableEntityOperationDirective } from "../../permissions/permission-di
selector: "app-entity-list",
templateUrl: "./entity-list.component.html",
styleUrls: ["./entity-list.component.scss"],
+ providers: [DuplicateRecordService],
imports: [
NgIf,
NgStyle,
@@ -78,36 +82,52 @@ import { DisableEntityOperationDirective } from "../../permissions/permission-di
ExportDataDirective,
DisableEntityOperationDirective,
RouterLink,
+ MatTooltipModule,
],
standalone: true,
})
@UntilDestroy()
export class EntityListComponent
- implements OnChanges, AfterViewInit
+ implements EntityListConfig, OnChanges, AfterViewInit
{
@Input() allEntities: T[];
+
+ /** @deprecated this is often used when this has a wrapper component (e.g. ChildrenList), preferably use individual @Input properties */
@Input() listConfig: EntityListConfig;
+
+ @Input() entity: string;
@Input() entityConstructor: EntityConstructor;
+ @Input() defaultSort: Sort;
+ @Input() exportConfig: ExportColumnConfig[];
+
@Input() clickMode: "navigate" | "popup" | "none" = "navigate";
+
+ /** initial / default state whether to include archived records in the list */
+ @Input() showInactive: boolean;
+
@Input() isLoading: boolean;
+
@Output() elementClick = new EventEmitter();
@Output() addNewClick = new EventEmitter();
+ selectedRows: T[];
@ViewChild(EntitySubrecordComponent) entityTable: EntitySubrecordComponent;
isDesktop: boolean;
- listName = "";
- columns: (FormFieldConfig | string)[] = [];
- columnGroups: GroupConfig[] = [];
+ @Input() title = "";
+ @Input() columns: (FormFieldConfig | string)[] = [];
+ @Input() columnGroups: ColumnGroupsConfig;
+ groups: GroupConfig[] = [];
defaultColumnGroup = "";
mobileColumnGroup = "";
- filtersConfig: FilterConfig[] = [];
+ @Input() filters: FilterConfig[] = [];
columnsToDisplay: string[] = [];
filterObj: DataFilter;
filterString = "";
+ filteredData = [];
get selectedColumnGroupIndex(): number {
return this.selectedColumnGroupIndex_;
@@ -115,7 +135,7 @@ export class EntityListComponent
set selectedColumnGroupIndex(newValue: number) {
this.selectedColumnGroupIndex_ = newValue;
- this.columnsToDisplay = this.columnGroups[newValue].columns;
+ this.columnsToDisplay = this.groups[newValue].columns;
}
selectedColumnGroupIndex_: number = 0;
@@ -127,7 +147,7 @@ export class EntityListComponent
* tabs with zero top-padding in this case
*/
get offsetFilterStyle(): object {
- const bottomMargin = this.columnGroups.length > 1 ? 29 : 14;
+ const bottomMargin = this.groups.length > 1 ? 29 : 14;
return {
"margin-bottom": `${bottomMargin}px`,
};
@@ -141,14 +161,8 @@ export class EntityListComponent
private entityMapperService: EntityMapperService,
private entities: EntityRegistry,
private dialog: MatDialog,
+ private duplicateRecord: DuplicateRecordService,
) {
- if (this.activatedRoute.component === EntityListComponent) {
- // the component is used for a route and not inside a template
- this.activatedRoute.data.subscribe((data: RouteData) =>
- this.buildComponentFromConfig(data.config),
- );
- }
-
this.screenWidthObserver
.platform()
.pipe(untilDestroyed(this))
@@ -166,12 +180,22 @@ export class EntityListComponent
});
}
- private async buildComponentFromConfig(newConfig: EntityListConfig) {
- this.listConfig = newConfig;
+ ngOnChanges(changes: SimpleChanges) {
+ if (changes.hasOwnProperty("listConfig")) {
+ Object.assign(this, this.listConfig);
+ }
+ return this.buildComponentFromConfig();
+ }
+
+ ngAfterViewInit() {
+ this.entityTable.recordsDataSource.filterPredicate = (data, filter) =>
+ entityFilterPredicate(data.record, filter);
+ }
- if (this.listConfig?.entity) {
+ private async buildComponentFromConfig() {
+ if (this.entity) {
this.entityConstructor = this.entities.get(
- this.listConfig.entity,
+ this.entity,
) as EntityConstructor;
}
@@ -180,14 +204,10 @@ export class EntityListComponent
await this.loadEntities();
}
- this.listName =
- this.listConfig.title ||
- this.listName ||
- this.entityConstructor?.labelPlural;
+ this.title = this.title || this.entityConstructor?.labelPlural;
this.addColumnsFromColumnGroups();
- this.initColumnGroups(this.listConfig.columnGroups);
- this.filtersConfig = this.listConfig.filters ?? this.filtersConfig ?? [];
+ this.initColumnGroups(this.columnGroups);
this.displayColumnGroupByName(
this.screenWidthObserver.isDesktop()
@@ -206,42 +226,41 @@ export class EntityListComponent
this.isLoading = false;
}
- ngAfterViewInit() {
- this.entityTable.recordsDataSource.filterPredicate = (data, filter) =>
- entityFilterPredicate(data.record, filter);
- }
-
- async ngOnChanges(changes: SimpleChanges): Promise {
- if (changes.hasOwnProperty("listConfig")) {
- await this.buildComponentFromConfig(this.listConfig);
- }
- }
-
private addColumnsFromColumnGroups() {
- this.columns = this.listConfig.columns || [];
- this.listConfig.columnGroups?.groups?.forEach((group) =>
- group.columns
- .filter(
- (columnId) =>
- !this.columns.some((column) =>
- // Check if the column is already defined as object or string
- typeof column === "string"
- ? column === columnId
- : column.id === columnId,
- ),
- )
- .forEach((column) => this.columns.push(column)),
+ const allColumns = [...this.columns];
+ const groupColumns = (this.columnGroups?.groups ?? []).reduce(
+ (accumulatedColumns: string[], currentGroup) => [
+ ...accumulatedColumns,
+ ...currentGroup.columns,
+ ],
+ [],
);
+ for (const column of groupColumns) {
+ if (
+ !allColumns.some((existingColumn) =>
+ // Check if the column is already defined as object or string
+ typeof existingColumn === "string"
+ ? existingColumn === column
+ : existingColumn.id === column,
+ )
+ ) {
+ allColumns.push(column);
+ }
+ }
+
+ if (allColumns.length !== this.columns.length) {
+ this.columns = [...allColumns];
+ }
}
private initColumnGroups(columnGroup?: ColumnGroupsConfig) {
if (columnGroup && columnGroup.groups.length > 0) {
- this.columnGroups = columnGroup.groups;
+ this.groups = columnGroup.groups;
this.defaultColumnGroup =
columnGroup.default || columnGroup.groups[0].name;
this.mobileColumnGroup = columnGroup.mobile || columnGroup.groups[0].name;
} else {
- this.columnGroups = [
+ this.groups = [
{
name: "default",
columns: this.columns.map((c) => (typeof c === "string" ? c : c.id)),
@@ -253,10 +272,13 @@ export class EntityListComponent
}
applyFilter(filterValue: string) {
+ // TODO: turn this into one of our filter types, so that all filtering happens the same way (and we avoid accessing internal datasource of sub-component here)
filterValue = filterValue.trim();
filterValue = filterValue.toLowerCase(); // MatTableDataSource defaults to lowercase matches
this.entityTable.recordsDataSource.filter = filterValue;
-
+ this.filteredData = this.entityTable.recordsDataSource.filteredData.map(
+ (x) => x.record,
+ );
this.analyticsService.eventTrack("list_filter_freetext", {
category: this.entityConstructor?.ENTITY_TYPE,
});
@@ -271,7 +293,7 @@ export class EntityListComponent
}
private getSelectedColumnIndexByName(columnGroupName: string) {
- return this.columnGroups.findIndex((c) => c.name === columnGroupName);
+ return this.groups.findIndex((c) => c.name === columnGroupName);
}
/**
@@ -280,7 +302,7 @@ export class EntityListComponent
openFilterOverlay() {
this.dialog.open(FilterOverlayComponent, {
data: {
- filterConfig: this.filtersConfig,
+ filterConfig: this.filters,
entityType: this.entityConstructor,
entities: this.allEntities,
useUrlQueryParams: true,
@@ -295,4 +317,9 @@ export class EntityListComponent
}
this.addNewClick.emit();
}
+
+ duplicateRecords() {
+ this.duplicateRecord.duplicateRecord(this.selectedRows);
+ this.selectedRows = undefined;
+ }
}
diff --git a/src/app/core/entity/default-datatype/default.datatype.ts b/src/app/core/entity/default-datatype/default.datatype.ts
index ffd414bf5e..9545df82c2 100644
--- a/src/app/core/entity/default-datatype/default.datatype.ts
+++ b/src/app/core/entity/default-datatype/default.datatype.ts
@@ -114,4 +114,16 @@ export class DefaultDatatype {
importIncompleteAdditionalConfigBadge(col: ColumnMapping): string {
return undefined;
}
+
+ /**
+ * (Partially) anonymize to "retain-anonymized" for reporting purposes without personal identifiable information.
+ * @param value The original value to be anonymized
+ */
+ async anonymize(
+ value: EntityType,
+ schemaField: EntitySchemaField,
+ parent: any,
+ ): Promise {
+ return undefined;
+ }
}
diff --git a/src/app/core/entity/default-datatype/edit-component.ts b/src/app/core/entity/default-datatype/edit-component.ts
index 9f7e4a4c90..77a86a48ad 100644
--- a/src/app/core/entity/default-datatype/edit-component.ts
+++ b/src/app/core/entity/default-datatype/edit-component.ts
@@ -55,6 +55,9 @@ export abstract class EditComponent implements OnInit {
*/
additional?: any;
+ /** indicating that the value is not in its original state, so that components can explain this to the user */
+ isPartiallyAnonymized: boolean;
+
ngOnInit() {
if (!this.formFieldConfig?.forTable) {
this.label = this.formFieldConfig?.label ?? this.propertySchema?.label;
@@ -68,4 +71,11 @@ export abstract class EditComponent implements OnInit {
// This type casts are needed as the normal types throw errors in the templates
this.parent = this.formControl.parent as FormGroup;
}
+
+ ngOnChanges() {
+ this.isPartiallyAnonymized =
+ this.entity?.anonymized &&
+ this.entity?.getSchema()?.get(this.formFieldConfig?.id)?.anonymize ===
+ "retain-anonymized";
+ }
}
diff --git a/src/app/core/entity/default-datatype/view.directive.ts b/src/app/core/entity/default-datatype/view.directive.ts
index ffded6f6cc..cb155918e3 100644
--- a/src/app/core/entity/default-datatype/view.directive.ts
+++ b/src/app/core/entity/default-datatype/view.directive.ts
@@ -1,11 +1,20 @@
import { Entity } from "../model/entity";
-import { Directive, Input } from "@angular/core";
+import { Directive, Input, OnChanges } from "@angular/core";
@Directive()
-export abstract class ViewDirective {
+export abstract class ViewDirective implements OnChanges {
@Input() entity: Entity;
@Input() id: string;
@Input() tooltip: string;
@Input() value: T;
@Input() config: C;
+
+ /** indicating that the value is not in its original state, so that components can explain this to the user */
+ isPartiallyAnonymized: boolean;
+
+ ngOnChanges() {
+ this.isPartiallyAnonymized =
+ this.entity?.anonymized &&
+ this.entity?.getSchema()?.get(this.id)?.anonymize === "retain-anonymized";
+ }
}
diff --git a/src/app/core/entity/entity-actions/cascading-entity-action.spec.ts b/src/app/core/entity/entity-actions/cascading-entity-action.spec.ts
new file mode 100644
index 0000000000..f72ccf7fef
--- /dev/null
+++ b/src/app/core/entity/entity-actions/cascading-entity-action.spec.ts
@@ -0,0 +1,197 @@
+import { DatabaseEntity } from "../database-entity.decorator";
+import { Entity } from "../model/entity";
+import { DatabaseField } from "../database-field.decorator";
+import {
+ comparableEntityData,
+ expectEntitiesToMatch,
+} from "../../../utils/expect-entity-data.spec";
+import { MockEntityMapperService } from "../entity-mapper/mock-entity-mapper-service";
+
+/*
+ Deleting/Anonymizing referenced & related entities
+ also see doc/compodoc_sources/concepts/entity-anonymization.md
+
+ we distinguish different roles / relations between entities:
+ ♢ "aggregate" (has-a): both entities have meaning independently
+ ♦ "composite" (is-part-of): the entity holding the reference is only meaningful in the context of the referenced
+ */
+@DatabaseEntity("EntityWithAnonRelations")
+export class EntityWithAnonRelations extends Entity {
+ static override hasPII = true;
+
+ @DatabaseField() name: string;
+
+ @DatabaseField({
+ dataType: "entity-array",
+ additional: "EntityWithAnonRelations",
+ anonymize: "retain",
+ entityReferenceRole: "aggregate",
+ })
+ refAggregate: string[];
+
+ @DatabaseField({
+ dataType: "entity-array",
+ additional: "EntityWithAnonRelations",
+ anonymize: "retain",
+ entityReferenceRole: "composite",
+ })
+ refComposite: string[];
+
+ static create(name: string, properties?: Partial) {
+ return Object.assign(new EntityWithAnonRelations(), {
+ name: name,
+ ...properties,
+ });
+ }
+}
+
+export function expectAllUnchangedExcept(
+ changedEntities: EntityWithAnonRelations[],
+ entityMapper: MockEntityMapperService,
+) {
+ const isExpectedUnchanged = (entity: EntityWithAnonRelations) => {
+ !changedEntities.some((c) => entity.getId() === c.getId());
+ };
+
+ const actualEntitiesAfter =
+ entityMapper.getAllData() as EntityWithAnonRelations[];
+
+ expectEntitiesToMatch(
+ actualEntitiesAfter.filter(isExpectedUnchanged),
+ allEntities.filter(isExpectedUnchanged),
+ true,
+ );
+}
+
+export function expectDeleted(
+ deletedEntities: Entity[],
+ entityMapper: MockEntityMapperService,
+) {
+ const actualEntitiesAfter = entityMapper.getAllData();
+
+ for (const deletedEntity of deletedEntities) {
+ expect(actualEntitiesAfter).not.toContain(deletedEntity);
+ }
+}
+
+export function expectUpdated(
+ updatedEntities: EntityWithAnonRelations[],
+ entityMapper: MockEntityMapperService,
+) {
+ const actualEntitiesAfter = entityMapper.getAllData();
+
+ for (const updatedEntity of updatedEntities) {
+ const actualEntity = actualEntitiesAfter.find(
+ (e) => e.getId() === updatedEntity.getId(),
+ );
+ expect(comparableEntityData(actualEntity)).toEqual(
+ comparableEntityData(updatedEntity),
+ );
+ }
+}
+
+const WithoutRelations = EntityWithAnonRelations.create(
+ "entity without relations",
+);
+
+const ReferencedAsComposite = EntityWithAnonRelations.create(
+ "entity referenced as composite",
+);
+const ReferencingSingleComposite = EntityWithAnonRelations.create(
+ "entity having a composite reference",
+ {
+ refComposite: [ReferencedAsComposite.getId()],
+ },
+);
+
+const ReferencedAsOneOfMultipleComposites1 = EntityWithAnonRelations.create(
+ "entity referenced as one composite (1)",
+);
+const ReferencedAsOneOfMultipleComposites2 = EntityWithAnonRelations.create(
+ "entity referenced as one composite (2)",
+);
+const ReferencingTwoComposites = EntityWithAnonRelations.create(
+ "entity referencing two entities as composites",
+ {
+ refComposite: [
+ ReferencedAsOneOfMultipleComposites1.getId(),
+ ReferencedAsOneOfMultipleComposites2.getId(),
+ ],
+ },
+);
+
+const ReferencingCompositeAndAggregate_refComposite =
+ EntityWithAnonRelations.create(
+ "referenced as composite from composite+aggregate referencing entity",
+ );
+const ReferencingCompositeAndAggregate_refAggregate =
+ EntityWithAnonRelations.create(
+ "referenced as aggregate from composite+aggregate referencing entity",
+ );
+const ReferencingCompositeAndAggregate = EntityWithAnonRelations.create(
+ "having both a composite and a aggregate reference",
+ {
+ refComposite: [ReferencingCompositeAndAggregate_refComposite.getId()],
+ refAggregate: [ReferencingCompositeAndAggregate_refAggregate.getId()],
+ },
+);
+
+const ReferencingAggregate_ref = EntityWithAnonRelations.create(
+ "entity referenced as aggregate",
+);
+const ReferencingAggregate = EntityWithAnonRelations.create(
+ "entity having an aggregate reference",
+ {
+ refAggregate: [ReferencingAggregate_ref.getId()],
+ },
+);
+
+const ReferencingTwoAggregates_ref1 = EntityWithAnonRelations.create(
+ "entity referenced as one aggregate (1)",
+);
+const ReferencingTwoAggregates_ref2 = EntityWithAnonRelations.create(
+ "entity referenced as one aggregate (2)",
+);
+const ReferencingTwoAggregates = EntityWithAnonRelations.create(
+ "entity referencing two entities as aggregates",
+ {
+ refAggregate: [
+ ReferencingTwoAggregates_ref1.getId(),
+ ReferencingTwoAggregates_ref2.getId(),
+ ],
+ },
+);
+
+export const ENTITIES = {
+ WithoutRelations,
+ ReferencedAsComposite,
+ ReferencingSingleComposite,
+ ReferencedAsOneOfMultipleComposites1,
+ ReferencedAsOneOfMultipleComposites2,
+ ReferencingTwoComposites,
+ ReferencingCompositeAndAggregate_refComposite,
+ ReferencingCompositeAndAggregate_refAggregate,
+ ReferencingCompositeAndAggregate,
+ ReferencingAggregate_ref,
+ ReferencingAggregate,
+ ReferencingTwoAggregates_ref1,
+ ReferencingTwoAggregates_ref2,
+ ReferencingTwoAggregates,
+};
+
+export const allEntities: EntityWithAnonRelations[] = [
+ ENTITIES.WithoutRelations,
+ ENTITIES.ReferencedAsComposite,
+ ENTITIES.ReferencingSingleComposite,
+ ENTITIES.ReferencedAsOneOfMultipleComposites1,
+ ENTITIES.ReferencedAsOneOfMultipleComposites2,
+ ENTITIES.ReferencingTwoComposites,
+ ENTITIES.ReferencingCompositeAndAggregate_refComposite,
+ ENTITIES.ReferencingCompositeAndAggregate_refAggregate,
+ ENTITIES.ReferencingCompositeAndAggregate,
+ ENTITIES.ReferencingAggregate_ref,
+ ENTITIES.ReferencingAggregate,
+ ENTITIES.ReferencingTwoAggregates_ref1,
+ ENTITIES.ReferencingTwoAggregates_ref2,
+ ENTITIES.ReferencingTwoAggregates,
+];
diff --git a/src/app/core/entity/entity-actions/cascading-entity-action.ts b/src/app/core/entity/entity-actions/cascading-entity-action.ts
new file mode 100644
index 0000000000..177094c56d
--- /dev/null
+++ b/src/app/core/entity/entity-actions/cascading-entity-action.ts
@@ -0,0 +1,114 @@
+import { Entity } from "../model/entity";
+import { asArray } from "../../../utils/utils";
+import { EntitySchemaService } from "../schema/entity-schema.service";
+import { EntityMapperService } from "../entity-mapper/entity-mapper.service";
+
+export class CascadingActionResult {
+ /**
+ * entities that have been updated in the process, in their original state
+ * (can be used for undo action)
+ */
+ originalEntitiesBeforeChange: Entity[];
+
+ /**
+ * entities that may still contain PII related to the primary entity that could not be automatically removed
+ * (may need manual review by the user)
+ */
+ potentiallyRetainingPII: Entity[];
+
+ constructor(changedEntities?: Entity[], potentiallyRetainingPII?: Entity[]) {
+ this.originalEntitiesBeforeChange = changedEntities ?? [];
+ this.potentiallyRetainingPII = potentiallyRetainingPII ?? [];
+ }
+
+ mergeResults(otherResult: CascadingActionResult) {
+ this.originalEntitiesBeforeChange = [
+ ...this.originalEntitiesBeforeChange,
+ ...otherResult.originalEntitiesBeforeChange.filter(
+ (e) =>
+ !this.originalEntitiesBeforeChange.some(
+ (x) => x.getId() === e.getId(),
+ ),
+ ),
+ ];
+ this.potentiallyRetainingPII = [
+ ...this.potentiallyRetainingPII,
+ ...otherResult.potentiallyRetainingPII.filter(
+ (e) =>
+ !this.potentiallyRetainingPII.some((x) => x.getId() === e.getId()),
+ ),
+ ];
+
+ return this;
+ }
+}
+
+/**
+ * extend this class to implement services that perform actions on an entity
+ * that require recursive actions to related entities as well.
+ */
+export abstract class CascadingEntityAction {
+ protected constructor(
+ protected entityMapper: EntityMapperService,
+ protected schemaService: EntitySchemaService,
+ ) {}
+
+ /**
+ * Recursively call the given actions on all related entities that contain a reference to the given entity.
+ *
+ * Returns an array of all affected related entities (excluding the given entity) in their state before the action
+ * to support an undo action.
+ *
+ * @param entity
+ * @param compositeAction
+ * @param aggregateAction
+ * @private
+ */
+ protected async cascadeActionToRelatedEntities(
+ entity: Entity,
+ compositeAction: (
+ relatedEntity: Entity,
+ refField?: string,
+ entity?: Entity,
+ ) => Promise,
+ aggregateAction: (
+ relatedEntity: Entity,
+ refField?: string,
+ entity?: Entity,
+ ) => Promise,
+ ): Promise {
+ const cascadeActionResult = new CascadingActionResult();
+
+ const entityTypesWithReferences =
+ this.schemaService.getEntityTypesReferencingType(entity.getType());
+
+ for (const refType of entityTypesWithReferences) {
+ const entities = await this.entityMapper.loadType(refType.entityType);
+
+ for (const refField of refType.referencingProperties) {
+ const affectedEntities = entities.filter(
+ (e) =>
+ asArray(e[refField]).includes(entity.getId()) ||
+ asArray(e[refField]).includes(entity.getId(true)),
+ );
+
+ for (const e of affectedEntities) {
+ if (
+ refType.entityType.schema.get(refField).entityReferenceRole ===
+ "composite" &&
+ asArray(e[refField]).length === 1
+ ) {
+ // is only composite
+ const result = await compositeAction(e);
+ cascadeActionResult.mergeResults(result);
+ } else {
+ const result = await aggregateAction(e, refField, entity);
+ cascadeActionResult.mergeResults(result);
+ }
+ }
+ }
+ }
+
+ return cascadeActionResult;
+ }
+}
diff --git a/src/app/core/entity/entity-actions/entity-actions.service.spec.ts b/src/app/core/entity/entity-actions/entity-actions.service.spec.ts
new file mode 100644
index 0000000000..9fa08052a8
--- /dev/null
+++ b/src/app/core/entity/entity-actions/entity-actions.service.spec.ts
@@ -0,0 +1,141 @@
+import { fakeAsync, TestBed, tick } from "@angular/core/testing";
+import { EntityActionsService } from "./entity-actions.service";
+import { EntityMapperService } from "../entity-mapper/entity-mapper.service";
+import {
+ MatSnackBar,
+ MatSnackBarRef,
+ TextOnlySnackBar,
+} from "@angular/material/snack-bar";
+import { ConfirmationDialogService } from "../../common-components/confirmation-dialog/confirmation-dialog.service";
+import { Entity } from "../model/entity";
+import { NEVER, of, Subject } from "rxjs";
+import { Router } from "@angular/router";
+import { CoreTestingModule } from "../../../utils/core-testing.module";
+import { EntityDeleteService } from "./entity-delete.service";
+import { EntityAnonymizeService } from "./entity-anonymize.service";
+import { CascadingActionResult } from "./cascading-entity-action";
+
+describe("EntityActionsService", () => {
+ let service: EntityActionsService;
+ let mockedEntityMapper: jasmine.SpyObj;
+ let snackBarSpy: jasmine.SpyObj;
+ let mockSnackBarRef: jasmine.SpyObj>;
+ let mockConfirmationDialog: jasmine.SpyObj;
+ let mockRouter;
+ let mockedEntityDeleteService: jasmine.SpyObj;
+
+ let primaryEntity: Entity;
+
+ beforeEach(() => {
+ primaryEntity = new Entity();
+
+ mockedEntityDeleteService = jasmine.createSpyObj(["deleteEntity"]);
+ mockedEntityDeleteService.deleteEntity.and.resolveTo(
+ new CascadingActionResult([primaryEntity]),
+ );
+ mockedEntityMapper = jasmine.createSpyObj(["save", "saveAll"]);
+
+ snackBarSpy = jasmine.createSpyObj(["open"]);
+ mockSnackBarRef = jasmine.createSpyObj(["onAction", "afterDismissed"]);
+ mockSnackBarRef.onAction.and.returnValue(of());
+ snackBarSpy.open.and.returnValue(mockSnackBarRef);
+
+ mockConfirmationDialog = jasmine.createSpyObj([
+ "getConfirmation",
+ "showProgressDialog",
+ ]);
+ mockConfirmationDialog.getConfirmation.and.resolveTo(true);
+ mockConfirmationDialog.showProgressDialog.and.returnValue(
+ jasmine.createSpyObj(["close"]),
+ );
+
+ TestBed.configureTestingModule({
+ imports: [CoreTestingModule],
+ providers: [
+ EntityActionsService,
+ { provide: EntityDeleteService, useValue: mockedEntityDeleteService },
+ { provide: EntityAnonymizeService, useValue: null },
+ { provide: EntityMapperService, useValue: mockedEntityMapper },
+ { provide: MatSnackBar, useValue: snackBarSpy },
+ Router,
+ {
+ provide: ConfirmationDialogService,
+ useValue: mockConfirmationDialog,
+ },
+ ],
+ });
+ mockRouter = TestBed.inject(Router);
+ spyOn(mockRouter, "navigate");
+
+ service = TestBed.inject(EntityActionsService);
+ });
+
+ it("should return false when user cancels confirmation", async () => {
+ mockConfirmationDialog.getConfirmation.and.resolveTo(false);
+
+ const result = await service.delete(new Entity());
+
+ expect(result).toBe(false);
+ expect(snackBarSpy.open).not.toHaveBeenCalled();
+ expect(mockedEntityDeleteService.deleteEntity).not.toHaveBeenCalled();
+ });
+
+ it("should delete entity, show snackbar confirmation and navigate back", async () => {
+ // onAction is never called
+ mockSnackBarRef.onAction.and.returnValues(NEVER);
+ mockSnackBarRef.afterDismissed.and.returnValue(of(undefined));
+
+ const result = await service.delete(new Entity(), true);
+
+ expect(result).toBe(true);
+ expect(snackBarSpy.open).toHaveBeenCalled();
+ expect(mockedEntityDeleteService.deleteEntity).toHaveBeenCalled();
+ expect(mockRouter.navigate).toHaveBeenCalled();
+ });
+
+ it("should re-save all affected entities and navigate back to entity on undo", fakeAsync(() => {
+ const anotherAffectedEntity = new Entity();
+ mockedEntityDeleteService.deleteEntity.and.resolveTo(
+ new CascadingActionResult([primaryEntity, anotherAffectedEntity]),
+ );
+
+ // Mock a snackbar where 'undo' is pressed
+ const onSnackbarAction = new Subject();
+ mockSnackBarRef.onAction.and.returnValue(onSnackbarAction.asObservable());
+
+ mockedEntityMapper.save.and.resolveTo();
+
+ service.delete(primaryEntity, true);
+ tick();
+
+ mockRouter.navigate.calls.reset();
+ onSnackbarAction.next();
+ onSnackbarAction.complete();
+ tick();
+
+ expect(mockedEntityDeleteService.deleteEntity).toHaveBeenCalled();
+ expect(mockedEntityMapper.saveAll).toHaveBeenCalledWith(
+ [primaryEntity, anotherAffectedEntity],
+ true,
+ );
+ expect(mockRouter.navigate).toHaveBeenCalled();
+ }));
+
+ it("should archive and save entity", async () => {
+ await service.archive(primaryEntity);
+
+ expect(primaryEntity.isActive).toBeFalse();
+ expect(mockedEntityMapper.save).toHaveBeenCalledWith(primaryEntity);
+ });
+
+ it("should archiveUndo and save entity", async () => {
+ await service.archive(primaryEntity);
+ expect(primaryEntity.isActive).toBeFalse();
+ mockedEntityMapper.save.calls.reset();
+
+ await service.undoArchive(primaryEntity);
+
+ expect(primaryEntity.isActive).toBeTrue();
+ expect(mockedEntityMapper.save).toHaveBeenCalledWith(primaryEntity);
+ });
+});
diff --git a/src/app/core/entity/entity-actions/entity-actions.service.ts b/src/app/core/entity/entity-actions/entity-actions.service.ts
new file mode 100644
index 0000000000..ad44a37fcf
--- /dev/null
+++ b/src/app/core/entity/entity-actions/entity-actions.service.ts
@@ -0,0 +1,201 @@
+import { Injectable } from "@angular/core";
+import { EntityMapperService } from "../entity-mapper/entity-mapper.service";
+import { Entity } from "../model/entity";
+import { ConfirmationDialogService } from "../../common-components/confirmation-dialog/confirmation-dialog.service";
+import { MatSnackBar } from "@angular/material/snack-bar";
+import { Router } from "@angular/router";
+import { getUrlWithoutParams } from "../../../utils/utils";
+import { EntityDeleteService } from "./entity-delete.service";
+import { EntityAnonymizeService } from "./entity-anonymize.service";
+import { OkButton } from "../../common-components/confirmation-dialog/confirmation-dialog/confirmation-dialog.component";
+
+/**
+ * A service that can triggers a user flow for entity actions (e.g. to safely remove or anonymize an entity),
+ * including a confirmation dialog.
+ */
+@Injectable({
+ providedIn: "root",
+})
+export class EntityActionsService {
+ constructor(
+ private confirmationDialog: ConfirmationDialogService,
+ private snackBar: MatSnackBar,
+ private router: Router,
+ private entityMapper: EntityMapperService,
+ private entityDelete: EntityDeleteService,
+ private entityAnonymize: EntityAnonymizeService,
+ ) {}
+
+ private showSnackbarConfirmation(
+ entity: Entity,
+ action: string,
+ previousEntitiesForUndo: Entity[],
+ navigateBackToUrl?: string,
+ ) {
+ const snackBarTitle = $localize`:Entity action confirmation message:${
+ entity.getConstructor().label
+ } "${entity.toString()}" ${action}`;
+
+ const snackBarRef = this.snackBar.open(
+ snackBarTitle,
+ $localize`:Undo an entity action:Undo`,
+ {
+ duration: 8000,
+ },
+ );
+
+ // Undo Action
+ snackBarRef.onAction().subscribe(async () => {
+ const undoProgressRef = this.confirmationDialog.showProgressDialog(
+ $localize`:Undo entity action progress dialog: Reverting changes ...`,
+ );
+ await this.entityMapper.saveAll(previousEntitiesForUndo, true);
+ undoProgressRef.close();
+
+ if (navigateBackToUrl) {
+ await this.router.navigate([navigateBackToUrl]);
+ }
+ });
+ }
+
+ /**
+ * Shows a confirmation dialog to the user
+ * and removes the entity if the user confirms.
+ *
+ * This also triggers a toast message, enabling the user to undo the action.
+ *
+ * @param entity The entity to remove
+ * @param navigate whether upon delete the app will navigate back
+ */
+ async delete(
+ entity: E,
+ navigate: boolean = false,
+ ): Promise {
+ if (
+ !(await this.confirmationDialog.getConfirmation(
+ $localize`:Delete confirmation title:Delete?`,
+ $localize`:Delete confirmation dialog:
+ This will remove the data permanently as if it never existed. This cannot be undone. Statistical reports (also for past time periods) will change and not include this record anymore.\n
+ If you have not just created this record accidentally, deleting this is probably not what you want to do. If the record represents something that actually happened in your work, consider to use "anonymize" or just "archive" instead, so that you will not lose your documentation for reports.\n
+ Are you sure you want to delete this ${
+ entity.getConstructor().label
+ } record?`,
+ ))
+ ) {
+ return false;
+ }
+
+ const progressDialogRef = this.confirmationDialog.showProgressDialog(
+ $localize`:Entity action progress dialog:Processing ...`,
+ );
+ const result = await this.entityDelete.deleteEntity(entity);
+ progressDialogRef.close();
+
+ if (result.potentiallyRetainingPII.length > 0) {
+ await this.confirmationDialog.getConfirmation(
+ $localize`:post-delete related PII warning title:Related records may still contain personal data`,
+ $localize`:post-delete related PII warning dialog:Some related records (e.g. notes) may still contain personal data in their text. We have automatically deleted all records that are linked to ONLY this ${
+ entity.getConstructor().label
+ }.
+ However, there are some records that are linked to multiple records. We have not deleted these, so that you will not lose relevant data. Please review them manually to ensure all sensitive information is removed, if required (e.g. by looking through the linked notes and editing a note's text).`,
+ OkButton,
+ );
+ }
+
+ let currentUrl: string;
+ if (navigate) {
+ currentUrl = getUrlWithoutParams(this.router);
+ const parentUrl = currentUrl.substring(0, currentUrl.lastIndexOf("/"));
+ await this.router.navigate([parentUrl]);
+ }
+
+ this.showSnackbarConfirmation(
+ result.originalEntitiesBeforeChange[0],
+ $localize`:Entity action confirmation message verb:Deleted`,
+ result.originalEntitiesBeforeChange,
+ currentUrl,
+ );
+ return true;
+ }
+
+ /**
+ * Anonymize the given entity,
+ * removing properties that are not explicitly configured in the schema to be retained.
+ *
+ * This triggers UX interactions like confirmation request dialog and snackbar message as well.
+ *
+ * @param entity
+ */
+ async anonymize(entity: E) {
+ if (
+ !(await this.confirmationDialog.getConfirmation(
+ $localize`:Anonymize confirmation dialog:Anonymize?`,
+ $localize`:Anonymize confirmation dialog:
+ This will remove all personal information (PII) permanently and keep only a basic record for statistical reports. Details that are removed during anonymization cannot be recovered.\n
+ If this ${
+ entity.getConstructor().label
+ } has only become inactive and you want to keep all details about the record, consider to use "archive" instead.\n
+ Are you sure you want to anonymize this record?`,
+ ))
+ ) {
+ return false;
+ }
+
+ const progressDialogRef = this.confirmationDialog.showProgressDialog(
+ $localize`:Entity action progress dialog:Processing ...`,
+ );
+ const result = await this.entityAnonymize.anonymizeEntity(entity);
+ progressDialogRef.close();
+
+ if (result.potentiallyRetainingPII.length > 0) {
+ await this.confirmationDialog.getConfirmation(
+ $localize`:post-anonymize related PII warning title:Related records may still contain personal data`,
+ $localize`:post-anonymize related PII warning dialog:Some related records (e.g. notes) may still contain personal data in their text. We have automatically anonymized all records that are linked to ONLY this ${
+ entity.getConstructor().label
+ }.
+ However, there are some records that are linked to multiple records. We have not anonymized these, so that you will not lose relevant data. Please review them manually to ensure all sensitive information is removed (e.g. by looking through the linked notes and editing a note's text).`,
+ OkButton,
+ );
+ }
+
+ this.showSnackbarConfirmation(
+ result.originalEntitiesBeforeChange[0],
+ $localize`:Entity action confirmation message verb:Anonymized`,
+ result.originalEntitiesBeforeChange,
+ );
+ return true;
+ }
+
+ /**
+ * Mark the given entity as inactive.
+ * @param entity
+ */
+ async archive(entity: E) {
+ const originalEntity = entity.copy();
+ entity.inactive = true;
+ await this.entityMapper.save(entity);
+
+ this.showSnackbarConfirmation(
+ originalEntity,
+ $localize`:Entity action confirmation message verb:Archived`,
+ [originalEntity],
+ );
+ return true;
+ }
+ /**
+ * Undo the archive action on the given entity.
+ * @param entity
+ */
+ async undoArchive(entity: E) {
+ const originalEntity = entity.copy();
+ entity.inactive = false;
+ await this.entityMapper.save(entity);
+
+ this.showSnackbarConfirmation(
+ originalEntity,
+ $localize`:Entity action confirmation message verb:Reactivated`,
+ [originalEntity],
+ );
+ return true;
+ }
+}
diff --git a/src/app/core/entity/entity-actions/entity-anonymize.service.spec.ts b/src/app/core/entity/entity-actions/entity-anonymize.service.spec.ts
new file mode 100644
index 0000000000..1befc74733
--- /dev/null
+++ b/src/app/core/entity/entity-actions/entity-anonymize.service.spec.ts
@@ -0,0 +1,315 @@
+import { TestBed } from "@angular/core/testing";
+import { EntityMapperService } from "../entity-mapper/entity-mapper.service";
+import { Entity } from "../model/entity";
+import { of } from "rxjs";
+import { DatabaseEntity } from "../database-entity.decorator";
+import { DatabaseField } from "../database-field.decorator";
+import {
+ mockEntityMapper,
+ MockEntityMapperService,
+} from "../entity-mapper/mock-entity-mapper-service";
+import {
+ comparableEntityData,
+ expectEntitiesToMatch,
+} from "../../../utils/expect-entity-data.spec";
+import { UpdateMetadata } from "../model/update-metadata";
+import { FileService } from "../../../features/file/file.service";
+import { CoreTestingModule } from "../../../utils/core-testing.module";
+import { DefaultDatatype } from "../default-datatype/default.datatype";
+import { FileDatatype } from "../../../features/file/file.datatype";
+import moment from "moment";
+import {
+ allEntities,
+ ENTITIES,
+ EntityWithAnonRelations,
+ expectAllUnchangedExcept,
+} from "./cascading-entity-action.spec";
+import { EntityAnonymizeService } from "./entity-anonymize.service";
+
+describe("EntityAnonymizeService", () => {
+ let service: EntityAnonymizeService;
+ let entityMapper: MockEntityMapperService;
+ let mockFileService: jasmine.SpyObj;
+
+ beforeEach(() => {
+ entityMapper = mockEntityMapper(allEntities.map((e) => e.copy()));
+
+ mockFileService = jasmine.createSpyObj(["removeFile"]);
+ mockFileService.removeFile.and.returnValue(of(null));
+
+ TestBed.configureTestingModule({
+ imports: [CoreTestingModule],
+ providers: [
+ EntityAnonymizeService,
+ { provide: EntityMapperService, useValue: entityMapper },
+ { provide: FileService, useValue: mockFileService },
+ { provide: DefaultDatatype, useClass: FileDatatype, multi: true },
+ ],
+ });
+
+ service = TestBed.inject(EntityAnonymizeService);
+ });
+
+ /*
+ * ANONYMIZATION
+ */
+ @DatabaseEntity("AnonymizableEntity")
+ class AnonymizableEntity extends Entity {
+ static override hasPII = true;
+
+ @DatabaseField() defaultField: string;
+
+ @DatabaseField({ anonymize: "retain" })
+ retainedField: string;
+
+ @DatabaseField({
+ anonymize: "retain-anonymized",
+ dataType: "array",
+ innerDataType: "date-only",
+ })
+ retainAnonymizedDates: Date[];
+
+ @DatabaseField({ dataType: "file" }) file: string;
+
+ @DatabaseField({ anonymize: "retain-anonymized", dataType: "entity-array" })
+ referencesToRetainAnonymized: string[];
+
+ static create(properties: Partial) {
+ return Object.assign(new AnonymizableEntity(), properties);
+ }
+
+ static expectAnonymized(
+ entityId: string,
+ expectedEntity: AnonymizableEntity,
+ checkAllBaseProperties = false,
+ ) {
+ const actualResult = entityMapper
+ .get(expectedEntity.getType(), entityId)
+ .copy();
+
+ if (!checkAllBaseProperties) {
+ delete actualResult.inactive;
+ delete actualResult.anonymized;
+ }
+
+ expect(comparableEntityData(actualResult, true)).toEqual(
+ comparableEntityData(expectedEntity, true),
+ );
+ }
+ }
+
+ it("should anonymize and only keep properties marked to be retained", async () => {
+ const entity = new AnonymizableEntity();
+ entity.defaultField = "test";
+ entity.retainedField = "test";
+
+ await service.anonymizeEntity(entity);
+
+ AnonymizableEntity.expectAnonymized(
+ entity.getId(),
+ AnonymizableEntity.create({ retainedField: "test" }),
+ );
+ });
+
+ it("should anonymize and keep empty record without any fields", async () => {
+ const entity = new AnonymizableEntity();
+ entity.defaultField = "test";
+
+ await service.anonymizeEntity(entity);
+
+ AnonymizableEntity.expectAnonymized(
+ entity.getId(),
+ AnonymizableEntity.create({}),
+ );
+ });
+
+ it("should anonymize and retain created and updated", async () => {
+ const entityProperties = {
+ created: new UpdateMetadata("CREATOR", new Date("2020-01-01")),
+ updated: new UpdateMetadata("UPDATER", new Date("2020-01-02")),
+ };
+ const entity = AnonymizableEntity.create({
+ defaultField: "test",
+ ...entityProperties,
+ });
+
+ await service.anonymizeEntity(entity);
+
+ AnonymizableEntity.expectAnonymized(
+ entity.getId(),
+ AnonymizableEntity.create({
+ inactive: true,
+ anonymized: true,
+ ...entityProperties,
+ }),
+ true,
+ );
+ });
+
+ it("should mark anonymized entities as inactive", async () => {
+ const entity = new AnonymizableEntity();
+ entity.defaultField = "test";
+
+ await service.anonymizeEntity(entity);
+
+ AnonymizableEntity.expectAnonymized(
+ entity.getId(),
+ AnonymizableEntity.create({ inactive: true, anonymized: true }),
+ true,
+ );
+ });
+
+ it("should anonymize array values recursively and use datatype implementation for 'retain-anonymized", async () => {
+ const entity = new AnonymizableEntity();
+ entity.retainAnonymizedDates = [
+ moment("2023-09-25").toDate(),
+ moment("2023-10-04").toDate(),
+ ];
+
+ await service.anonymizeEntity(entity);
+
+ AnonymizableEntity.expectAnonymized(
+ entity.getId(),
+ AnonymizableEntity.create({
+ retainAnonymizedDates: [
+ moment("2023-07-01").toDate(),
+ moment("2023-07-01").toDate(),
+ ],
+ }),
+ );
+ });
+
+ it("should anonymize file values, actively deleting file attachments", async () => {
+ const entity = new AnonymizableEntity();
+ entity.file = "test-file.txt";
+
+ await service.anonymizeEntity(entity);
+
+ AnonymizableEntity.expectAnonymized(
+ entity.getId(),
+ AnonymizableEntity.create({}),
+ );
+ expect(mockFileService.removeFile).toHaveBeenCalled();
+ });
+
+ it("should not anonymize fields if Entity type is set to not have PII", async () => {
+ AnonymizableEntity.hasPII = false;
+ const entity = new AnonymizableEntity();
+ // make sure the original entity is available initially (we expect it to remain unchanged)
+ entityMapper.add(entity);
+ entity.defaultField = "test";
+
+ await service.anonymizeEntity(entity);
+
+ AnonymizableEntity.expectAnonymized(
+ entity.getId(),
+ AnonymizableEntity.create({ defaultField: "test" }),
+ true,
+ );
+
+ // reset actual state
+ AnonymizableEntity.hasPII = true;
+ });
+
+ /*
+ CASCADING ANONYMIZATION
+ */
+ function expectAnonymized(
+ expectedToGetAnonymized: EntityWithAnonRelations[],
+ entityMapper: MockEntityMapperService,
+ ) {
+ const actualEntitiesAfter = entityMapper.getAllData();
+
+ for (const anonEntity of expectedToGetAnonymized) {
+ const actualEntity = actualEntitiesAfter.find(
+ (e) => e.getId() === anonEntity.getId(),
+ );
+
+ const expectedAnonymizedEntity = new EntityWithAnonRelations(
+ anonEntity.getId(),
+ );
+ // copy over properties that are marked as `anonymize: "retain"`
+ expectedAnonymizedEntity.refAggregate = anonEntity.refAggregate;
+ expectedAnonymizedEntity.refComposite = anonEntity.refComposite;
+ expectedAnonymizedEntity.inactive = true;
+ expectedAnonymizedEntity.anonymized = true;
+
+ expect(comparableEntityData(actualEntity)).toEqual(
+ comparableEntityData(expectedAnonymizedEntity),
+ );
+ }
+
+ expectAllUnchangedExcept(expectedToGetAnonymized, entityMapper);
+ }
+
+ it("should not cascade anonymize the related entity if the entity holding the reference is anonymized", async () => {
+ // for direct references (e.g. x.referencesToRetainAnonymized --> recursively calls anonymize on referenced entities)
+ // see EntityDatatype & EntityArrayDatatype for unit tests
+
+ await service.anonymizeEntity(ENTITIES.ReferencingSingleComposite);
+
+ expectAnonymized([ENTITIES.ReferencingSingleComposite], entityMapper);
+ });
+
+ it("should cascade anonymize the 'composite'-type entity that references the entity user acts on", async () => {
+ await service.anonymizeEntity(ENTITIES.ReferencedAsComposite);
+
+ expectAnonymized(
+ [ENTITIES.ReferencedAsComposite, ENTITIES.ReferencingSingleComposite],
+ entityMapper,
+ );
+ });
+
+ it("should not cascade anonymize the 'composite'-type entity that still references additional other entities but ask user", async () => {
+ const result = await service.anonymizeEntity(
+ ENTITIES.ReferencedAsOneOfMultipleComposites1,
+ );
+
+ expectAnonymized(
+ [ENTITIES.ReferencedAsOneOfMultipleComposites1],
+ entityMapper,
+ );
+ // warn user that there may be personal details in referencing entity which have not been deleted
+ expectEntitiesToMatch(result.potentiallyRetainingPII, [
+ ENTITIES.ReferencingTwoComposites,
+ ]);
+ });
+
+ it("should cascade anonymize the 'composite'-type entity that references the entity user acts on even when another property holds other id (e.g. ChildSchoolRelation)", async () => {
+ await service.anonymizeEntity(
+ ENTITIES.ReferencingCompositeAndAggregate_refComposite,
+ );
+
+ expectAnonymized(
+ [
+ ENTITIES.ReferencingCompositeAndAggregate_refComposite,
+ ENTITIES.ReferencingCompositeAndAggregate,
+ ],
+ entityMapper,
+ );
+ });
+
+ it("should not cascade anonymize the 'aggregate'-type entity that only references the entity user acts on but ask user", async () => {
+ const result = await service.anonymizeEntity(
+ ENTITIES.ReferencingAggregate_ref,
+ );
+
+ expectAnonymized([ENTITIES.ReferencingAggregate_ref], entityMapper);
+ // warn user that there may be personal details in referencing entity which have not been deleted
+ expectEntitiesToMatch(result.potentiallyRetainingPII, [
+ ENTITIES.ReferencingAggregate,
+ ]);
+ });
+
+ it("should not cascade anonymize the 'aggregate'-type entity that still references additional other entities but ask user", async () => {
+ const result = await service.anonymizeEntity(
+ ENTITIES.ReferencingTwoAggregates_ref1,
+ );
+
+ expectAnonymized([ENTITIES.ReferencingTwoAggregates_ref1], entityMapper);
+ // warn user that there may be personal details in referencing entity which have not been deleted
+ expectEntitiesToMatch(result.potentiallyRetainingPII, [
+ ENTITIES.ReferencingTwoAggregates,
+ ]);
+ });
+});
diff --git a/src/app/core/entity/entity-actions/entity-anonymize.service.ts b/src/app/core/entity/entity-actions/entity-anonymize.service.ts
new file mode 100644
index 0000000000..731e5757e6
--- /dev/null
+++ b/src/app/core/entity/entity-actions/entity-anonymize.service.ts
@@ -0,0 +1,101 @@
+import { Injectable } from "@angular/core";
+import { EntityMapperService } from "../entity-mapper/entity-mapper.service";
+import { EntitySchemaService } from "../schema/entity-schema.service";
+import {
+ CascadingActionResult,
+ CascadingEntityAction,
+} from "./cascading-entity-action";
+import { firstValueFrom } from "rxjs";
+import { FileDatatype } from "../../../features/file/file.datatype";
+import { FileService } from "../../../features/file/file.service";
+import { Entity } from "../model/entity";
+
+/**
+ * Anonymize an entity including handling references with related entities.
+ * This service is usually used in combination with the `EntityActionsService`, which provides user confirmation processes around this.
+ */
+@Injectable({
+ providedIn: "root",
+})
+export class EntityAnonymizeService extends CascadingEntityAction {
+ constructor(
+ protected entityMapper: EntityMapperService,
+ protected schemaService: EntitySchemaService,
+ private fileService: FileService,
+ ) {
+ super(entityMapper, schemaService);
+ }
+
+ /**
+ * The actual anonymize action without user interactions.
+ * @param entity
+ * @private
+ */
+ async anonymizeEntity(entity: Entity): Promise {
+ if (!entity.getConstructor().hasPII) {
+ // entity types that are generally without PII by default retain all fields
+ // this should only be called through a cascade action anyway
+ return new CascadingActionResult();
+ }
+
+ const originalEntity = entity.copy();
+
+ for (const [key, schema] of entity.getSchema().entries()) {
+ if (entity[key] === undefined) {
+ continue;
+ }
+
+ switch (schema.anonymize) {
+ case "retain":
+ break;
+ case "retain-anonymized":
+ await this.anonymizeProperty(entity, key);
+ break;
+ default:
+ await this.removeProperty(entity, key);
+ }
+ }
+
+ entity.anonymized = true;
+ entity.inactive = true;
+
+ await this.entityMapper.save(entity);
+
+ const cascadeResult = await this.cascadeActionToRelatedEntities(
+ entity,
+ (e) => this.anonymizeEntity(e),
+ (e) => this.keepEntityUnchanged(e),
+ );
+
+ return new CascadingActionResult([originalEntity]).mergeResults(
+ cascadeResult,
+ );
+ }
+
+ private async anonymizeProperty(entity: Entity, key: string) {
+ const dataType = this.schemaService.getDatatypeOrDefault(
+ entity.getSchema().get(key).dataType,
+ );
+
+ entity[key] = await dataType.anonymize(
+ entity[key],
+ entity.getSchema().get(key),
+ entity,
+ );
+ }
+
+ private async removeProperty(entity: Entity, key: string) {
+ if (
+ entity.getSchema().get(key).dataType === FileDatatype.dataType &&
+ entity[key]
+ ) {
+ await firstValueFrom(this.fileService.removeFile(entity, key));
+ }
+
+ delete entity[key];
+ }
+
+ private async keepEntityUnchanged(e: Entity): Promise {
+ return new CascadingActionResult([], e.getConstructor().hasPII ? [e] : []);
+ }
+}
diff --git a/src/app/core/entity/entity-actions/entity-delete.service.spec.ts b/src/app/core/entity/entity-actions/entity-delete.service.spec.ts
new file mode 100644
index 0000000000..182f37cf43
--- /dev/null
+++ b/src/app/core/entity/entity-actions/entity-delete.service.spec.ts
@@ -0,0 +1,205 @@
+import { TestBed } from "@angular/core/testing";
+import { CoreTestingModule } from "../../../utils/core-testing.module";
+import { EntityDeleteService } from "./entity-delete.service";
+import {
+ mockEntityMapper,
+ MockEntityMapperService,
+} from "../entity-mapper/mock-entity-mapper-service";
+import { EntityMapperService } from "../entity-mapper/entity-mapper.service";
+import {
+ allEntities,
+ ENTITIES,
+ EntityWithAnonRelations,
+ expectAllUnchangedExcept,
+ expectDeleted,
+ expectUpdated,
+} from "./cascading-entity-action.spec";
+import { expectEntitiesToMatch } from "../../../utils/expect-entity-data.spec";
+import { Note } from "../../../child-dev-project/notes/model/note";
+import { Child } from "../../../child-dev-project/children/model/child";
+
+describe("EntityDeleteService", () => {
+ let service: EntityDeleteService;
+ let entityMapper: MockEntityMapperService;
+
+ beforeEach(() => {
+ entityMapper = mockEntityMapper(allEntities.map((e) => e.copy()));
+
+ TestBed.configureTestingModule({
+ imports: [CoreTestingModule],
+ providers: [
+ EntityDeleteService,
+ { provide: EntityMapperService, useValue: entityMapper },
+ ],
+ });
+
+ service = TestBed.inject(EntityDeleteService);
+ });
+
+ function removeReference(
+ entity: EntityWithAnonRelations,
+ property: "refAggregate" | "refComposite",
+ referencedEntity: EntityWithAnonRelations,
+ ) {
+ const result = entity.copy();
+ result[property] = result[property].filter(
+ (id) =>
+ id !== referencedEntity.getId() && id !== referencedEntity.getId(true),
+ );
+ return result;
+ }
+
+ it("should not cascade delete the related entity if the entity holding the reference is deleted", async () => {
+ // for direct references (e.g. x.referencesToRetainAnonymized --> recursively calls anonymize on referenced entities)
+ // see EntityDatatype & EntityArrayDatatype for unit tests
+
+ await service.deleteEntity(ENTITIES.ReferencingSingleComposite);
+
+ expectDeleted([ENTITIES.ReferencingSingleComposite], entityMapper);
+ expectAllUnchangedExcept(
+ [ENTITIES.ReferencingSingleComposite],
+ entityMapper,
+ );
+ });
+
+ it("should cascade delete the 'composite'-type entity that references the entity user acts on", async () => {
+ await service.deleteEntity(ENTITIES.ReferencedAsComposite);
+
+ expectDeleted(
+ [ENTITIES.ReferencedAsComposite, ENTITIES.ReferencingSingleComposite],
+ entityMapper,
+ );
+ expectAllUnchangedExcept(
+ [ENTITIES.ReferencedAsComposite, ENTITIES.ReferencingSingleComposite],
+ entityMapper,
+ );
+ });
+
+ it("should not cascade delete the 'composite'-type entity that still references additional other entities but remove id", async () => {
+ const result = await service.deleteEntity(
+ ENTITIES.ReferencedAsOneOfMultipleComposites1,
+ );
+
+ const expectedUpdatedRelEntity = removeReference(
+ ENTITIES.ReferencingTwoComposites,
+ "refComposite",
+ ENTITIES.ReferencedAsOneOfMultipleComposites1,
+ );
+ expectDeleted(
+ [ENTITIES.ReferencedAsOneOfMultipleComposites1],
+ entityMapper,
+ );
+ expectUpdated([expectedUpdatedRelEntity], entityMapper);
+ expectAllUnchangedExcept(
+ [
+ ENTITIES.ReferencedAsOneOfMultipleComposites1,
+ ENTITIES.ReferencingTwoComposites,
+ ],
+ entityMapper,
+ );
+ // warn user that there may be personal details in referencing entity which have not been deleted
+ expectEntitiesToMatch(result.potentiallyRetainingPII, [
+ expectedUpdatedRelEntity,
+ ]);
+ });
+
+ it("should cascade delete the 'composite'-type entity that references the entity user acts on even when another property holds other id (e.g. ChildSchoolRelation)", async () => {
+ await service.deleteEntity(
+ ENTITIES.ReferencingCompositeAndAggregate_refComposite,
+ );
+
+ expectDeleted(
+ [
+ ENTITIES.ReferencingCompositeAndAggregate_refComposite,
+ ENTITIES.ReferencingCompositeAndAggregate,
+ ],
+ entityMapper,
+ );
+ expectAllUnchangedExcept(
+ [
+ ENTITIES.ReferencingCompositeAndAggregate_refComposite,
+ ENTITIES.ReferencingCompositeAndAggregate,
+ ],
+ entityMapper,
+ );
+ });
+
+ it("should not cascade delete the 'aggregate'-type entity that only references the entity user acts on but remove id", async () => {
+ const result = await service.deleteEntity(
+ ENTITIES.ReferencingAggregate_ref,
+ );
+
+ const expectedUpdatedRelEntity = removeReference(
+ ENTITIES.ReferencingAggregate,
+ "refAggregate",
+ ENTITIES.ReferencingAggregate_ref,
+ );
+ expectDeleted([ENTITIES.ReferencingAggregate_ref], entityMapper);
+ expectUpdated([expectedUpdatedRelEntity], entityMapper);
+ expectAllUnchangedExcept(
+ [ENTITIES.ReferencingAggregate_ref, ENTITIES.ReferencingAggregate],
+ entityMapper,
+ );
+ // warn user that there may be personal details in referencing entity which have not been deleted
+ expectEntitiesToMatch(result.potentiallyRetainingPII, [
+ expectedUpdatedRelEntity,
+ ]);
+ });
+
+ it("should not cascade delete the 'aggregate'-type entity that still references additional other entities but remove id", async () => {
+ await service.deleteEntity(ENTITIES.ReferencingTwoAggregates_ref1);
+
+ expectDeleted([ENTITIES.ReferencingTwoAggregates_ref1], entityMapper);
+ expectUpdated(
+ [
+ removeReference(
+ ENTITIES.ReferencingTwoAggregates,
+ "refAggregate",
+ ENTITIES.ReferencingTwoAggregates_ref1,
+ ),
+ ],
+ entityMapper,
+ );
+ expectAllUnchangedExcept(
+ [
+ ENTITIES.ReferencingTwoAggregates_ref1,
+ ENTITIES.ReferencingTwoAggregates,
+ ],
+ entityMapper,
+ );
+ });
+
+ it("should remove multiple ref ids from related note", async () => {
+ const schemaField = Note.schema.get("relatedEntities");
+ const originalSchemaAdditional = schemaField.additional;
+ schemaField.additional = [Child.ENTITY_TYPE];
+
+ const primary = new Child();
+ const note = new Note();
+ note.subject = "test";
+ note.children = [primary.getId(), "some-other"];
+ note.relatedEntities = [primary.getId(true)];
+ const originalNote = note.copy();
+ await entityMapper.save(primary);
+ await entityMapper.save(note);
+
+ const result = await service.deleteEntity(primary);
+
+ const actualNote = entityMapper.get(
+ Note.ENTITY_TYPE,
+ note.getId(true),
+ ) as Note;
+
+ expect(actualNote.relatedEntities).toEqual([]);
+ expect(actualNote.children).toEqual(["some-other"]);
+
+ expect(result.originalEntitiesBeforeChange.length).toBe(2);
+ expectEntitiesToMatch(result.originalEntitiesBeforeChange, [
+ primary,
+ originalNote,
+ ]);
+
+ // restore original schema
+ schemaField.additional = originalSchemaAdditional;
+ });
+});
diff --git a/src/app/core/entity/entity-actions/entity-delete.service.ts b/src/app/core/entity/entity-actions/entity-delete.service.ts
new file mode 100644
index 0000000000..6f28fb8280
--- /dev/null
+++ b/src/app/core/entity/entity-actions/entity-delete.service.ts
@@ -0,0 +1,89 @@
+import { Injectable } from "@angular/core";
+import { EntityMapperService } from "../entity-mapper/entity-mapper.service";
+import { Entity } from "../model/entity";
+import { EntitySchemaService } from "../schema/entity-schema.service";
+import {
+ CascadingActionResult,
+ CascadingEntityAction,
+} from "./cascading-entity-action";
+
+/**
+ * Safely delete an entity including handling references with related entities.
+ * This service is usually used in combination with the `EntityActionsService`, which provides user confirmation processes around this.
+ */
+@Injectable({
+ providedIn: "root",
+})
+export class EntityDeleteService extends CascadingEntityAction {
+ constructor(
+ protected entityMapper: EntityMapperService,
+ protected schemaService: EntitySchemaService,
+ ) {
+ super(entityMapper, schemaService);
+ }
+
+ /**
+ * The actual delete action without user interactions.
+ *
+ * Returns an array of all affected entities (including the given entity) in their state before the action
+ * to support an undo action.
+ *
+ * @param entity
+ * @private
+ */
+ async deleteEntity(entity: Entity): Promise {
+ const cascadeResult = await this.cascadeActionToRelatedEntities(
+ entity,
+ (e) => this.deleteEntity(e),
+ (e, refField, entity) =>
+ this.removeReferenceFromEntity(e, refField, entity),
+ );
+
+ const originalEntity = entity.copy();
+ await this.entityMapper.remove(entity);
+
+ return new CascadingActionResult([originalEntity]).mergeResults(
+ cascadeResult,
+ );
+ }
+
+ /**
+ * Change and save the entity, removing referenced ids of the given referenced entity.
+ *
+ * Returns an array of the affected entities (which here is only the given entity) in the state before the action
+ * to support an undo action.
+ *
+ * @param relatedEntityWithReference
+ * @param refField
+ * @param referencedEntity
+ * @private
+ */
+ private async removeReferenceFromEntity(
+ relatedEntityWithReference: Entity,
+ refField: string,
+ referencedEntity: Entity,
+ ): Promise {
+ const originalEntity = relatedEntityWithReference.copy();
+
+ if (Array.isArray(relatedEntityWithReference[refField])) {
+ relatedEntityWithReference[refField] = relatedEntityWithReference[
+ refField
+ ].filter(
+ (id) =>
+ id !== referencedEntity.getId() &&
+ id !== referencedEntity.getId(true),
+ );
+ } else {
+ delete relatedEntityWithReference[refField];
+ }
+
+ await this.entityMapper.save(relatedEntityWithReference);
+
+ return new CascadingActionResult(
+ [originalEntity],
+ relatedEntityWithReference.getConstructor().hasPII
+ ? [relatedEntityWithReference]
+ : [],
+ );
+ }
+}
diff --git a/src/app/core/entity/entity-config.service.ts b/src/app/core/entity/entity-config.service.ts
index e7a54c18b9..b33bbd307d 100644
--- a/src/app/core/entity/entity-config.service.ts
+++ b/src/app/core/entity/entity-config.service.ts
@@ -1,9 +1,5 @@
import { Injectable } from "@angular/core";
-import {
- Entity,
- ENTITY_CONFIG_PREFIX,
- EntityConstructor,
-} from "./model/entity";
+import { Entity, EntityConstructor } from "./model/entity";
import { ConfigService } from "../config/config.service";
import { EntitySchemaField } from "./schema/entity-schema-field";
import { addPropertySchema } from "./database-field.decorator";
@@ -35,8 +31,10 @@ export class EntityConfigService {
setupEntitiesFromConfig() {
for (const config of this.configService.getAllConfigs<
EntityConfig & { _id: string }
- >(ENTITY_CONFIG_PREFIX)) {
- const id = config._id.substring(ENTITY_CONFIG_PREFIX.length);
+ >(EntityConfigService.PREFIX_ENTITY_CONFIG)) {
+ const id = config._id.substring(
+ EntityConfigService.PREFIX_ENTITY_CONFIG.length,
+ );
if (!this.entities.has(id)) {
this.createNewEntity(id, config.extends);
}
@@ -78,6 +76,7 @@ export class EntityConfigService {
),
);
}
+ // TODO: shall we just assign all properties that are present in the config object?
entityType.toStringAttributes =
entityConfig.toStringAttributes ?? entityType.toStringAttributes;
entityType.label = entityConfig.label ?? entityType.label;
@@ -85,6 +84,7 @@ export class EntityConfigService {
entityType.icon = (entityConfig.icon as IconName) ?? entityType.icon;
entityType.color = entityConfig.color ?? entityType.color;
entityType.route = entityConfig.route ?? entityType.route;
+ entityType.hasPII = entityConfig.hasPII ?? entityType.hasPII;
entityType._isCustomizedType = true;
}
@@ -158,4 +158,9 @@ export interface EntityConfig {
* when a new entity is created, all properties from this class will also be available
*/
extends?: string;
+
+ /**
+ * whether the type can contain personally identifiable information (PII)
+ */
+ hasPII?: boolean;
}
diff --git a/src/app/core/entity/entity-mapper/entity-mapper.service.spec.ts b/src/app/core/entity/entity-mapper/entity-mapper.service.spec.ts
index bcc9bf06e1..f8489be4c6 100644
--- a/src/app/core/entity/entity-mapper/entity-mapper.service.spec.ts
+++ b/src/app/core/entity/entity-mapper/entity-mapper.service.spec.ts
@@ -19,18 +19,14 @@ import { EntityMapperService } from "./entity-mapper.service";
import { Entity } from "../model/entity";
import { TestBed, waitForAsync } from "@angular/core/testing";
import { PouchDatabase } from "../../database/pouch-database";
-import {
- DatabaseEntity,
- entityRegistry,
- EntityRegistry,
-} from "../database-entity.decorator";
+import { DatabaseEntity } from "../database-entity.decorator";
import { Child } from "../../../child-dev-project/children/model/child";
import { SessionService } from "../../session/session-service/session.service";
-import { CoreModule } from "../../core.module";
import { Database } from "../../database/database";
-import { ComponentRegistry } from "../../../dynamic-components";
import { TEST_USER } from "../../../utils/mock-local-session";
+import { CoreTestingModule } from "../../../utils/core-testing.module";
+
describe("EntityMapperService", () => {
let entityMapper: EntityMapperService;
let testDatabase: PouchDatabase;
@@ -53,10 +49,8 @@ describe("EntityMapperService", () => {
mockSessionService = jasmine.createSpyObj(["getCurrentUser"]);
TestBed.configureTestingModule({
- imports: [CoreModule],
+ imports: [CoreTestingModule],
providers: [
- ComponentRegistry,
- { provide: EntityRegistry, useValue: entityRegistry },
{ provide: Database, useValue: testDatabase },
{ provide: SessionService, useValue: mockSessionService },
EntityMapperService,
diff --git a/src/app/core/entity/entity-mapper/entity-mapper.service.ts b/src/app/core/entity/entity-mapper/entity-mapper.service.ts
index b7c800b417..29c0e54102 100644
--- a/src/app/core/entity/entity-mapper/entity-mapper.service.ts
+++ b/src/app/core/entity/entity-mapper/entity-mapper.service.ts
@@ -155,13 +155,18 @@ export class EntityMapperService {
* This method should be chosen whenever a bigger number of entities needs to be
* saved
* @param entities The entities to save
+ * @param forceUpdate Optional flag whether any conflicting version in the database will be quietly overwritten.
+ * if a conflict occurs without the forceUpdate flag being set, the save will fail, rejecting the returned promise.
*/
- public async saveAll(entities: Entity[]): Promise {
+ public async saveAll(
+ entities: Entity[],
+ forceUpdate: boolean = false,
+ ): Promise {
entities.forEach((e) => this.setEntityMetadata(e));
const rawData = entities.map((e) =>
this.entitySchemaService.transformEntityToDatabaseFormat(e),
);
- const results = await this._db.putAll(rawData);
+ const results = await this._db.putAll(rawData, forceUpdate);
results.forEach((res, idx) => {
if (res.ok) {
const entity = entities[idx];
diff --git a/src/app/core/entity/entity-mapper/mock-entity-mapper-service.ts b/src/app/core/entity/entity-mapper/mock-entity-mapper-service.ts
index 5823c46ba6..389339c208 100644
--- a/src/app/core/entity/entity-mapper/mock-entity-mapper-service.ts
+++ b/src/app/core/entity/entity-mapper/mock-entity-mapper-service.ts
@@ -157,4 +157,18 @@ export class MockEntityMapperService extends EntityMapperService {
}
return this.observables.get(name);
}
+
+ /**
+ * Get a flat array of all entities in the database overall
+ * for testing and debugging.
+ */
+ public getAllData() {
+ const allData: Entity[] = [];
+ for (const type of this.data.values()) {
+ for (const entity of type.values()) {
+ allData.push(entity);
+ }
+ }
+ return allData;
+ }
}
diff --git a/src/app/core/entity/entity-remove.service.spec.ts b/src/app/core/entity/entity-remove.service.spec.ts
deleted file mode 100644
index 570cc4a1ad..0000000000
--- a/src/app/core/entity/entity-remove.service.spec.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-import { fakeAsync, TestBed, tick } from "@angular/core/testing";
-import { EntityRemoveService } from "./entity-remove.service";
-import { EntityMapperService } from "./entity-mapper/entity-mapper.service";
-import {
- MatSnackBar,
- MatSnackBarRef,
- TextOnlySnackBar,
-} from "@angular/material/snack-bar";
-import { ConfirmationDialogService } from "../common-components/confirmation-dialog/confirmation-dialog.service";
-import { Entity } from "./model/entity";
-import { NEVER, Subject } from "rxjs";
-import { Router } from "@angular/router";
-
-describe("EntityRemoveService", () => {
- let service: EntityRemoveService;
- let mockEntityMapper: jasmine.SpyObj;
- let snackBarSpy: jasmine.SpyObj;
- let mockSnackBarRef: jasmine.SpyObj>;
- let mockConfirmationDialog: jasmine.SpyObj;
- let mockRouter;
-
- beforeEach(() => {
- mockEntityMapper = jasmine.createSpyObj(["remove", "save"]);
- snackBarSpy = jasmine.createSpyObj(["open"]);
- mockSnackBarRef = jasmine.createSpyObj(["onAction"]);
- mockConfirmationDialog = jasmine.createSpyObj(["getConfirmation"]);
- mockConfirmationDialog.getConfirmation.and.resolveTo(true);
- snackBarSpy.open.and.returnValue(mockSnackBarRef);
- mockEntityMapper.remove.and.resolveTo();
- TestBed.configureTestingModule({
- providers: [
- { provide: EntityMapperService, useValue: mockEntityMapper },
- { provide: MatSnackBar, useValue: snackBarSpy },
- Router,
- {
- provide: ConfirmationDialogService,
- useValue: mockConfirmationDialog,
- },
- ],
- });
- mockRouter = TestBed.inject(Router);
- spyOn(mockRouter, "navigate");
-
- service = TestBed.inject(EntityRemoveService);
- });
-
- it("should return false when user cancels confirmation", async () => {
- mockConfirmationDialog.getConfirmation.and.resolveTo(false);
-
- const result = await service.remove(new Entity());
-
- expect(result).toBe(false);
- expect(snackBarSpy.open).not.toHaveBeenCalled();
- expect(mockEntityMapper.remove).not.toHaveBeenCalled();
- });
-
- it("should delete entity, show snackbar confirmation and navigate back", async () => {
- // onAction is never called
- mockSnackBarRef.onAction.and.returnValues(NEVER);
-
- const result = await service.remove(new Entity(), true);
-
- expect(result).toBe(true);
- expect(snackBarSpy.open).toHaveBeenCalled();
- expect(mockEntityMapper.remove).toHaveBeenCalled();
- expect(mockRouter.navigate).toHaveBeenCalled();
- });
-
- it("should re-save entity and navigate back to entity on undo", fakeAsync(() => {
- const entity = new Entity();
-
- // Mock a snackbar where 'undo' is immediately pressed
- const onSnackbarAction = new Subject();
- mockSnackBarRef.onAction.and.returnValue(onSnackbarAction.asObservable());
-
- mockEntityMapper.save.and.resolveTo();
-
- service.remove(entity, true);
- tick();
-
- mockRouter.navigate.calls.reset();
- onSnackbarAction.next();
- onSnackbarAction.complete();
- tick();
-
- expect(mockEntityMapper.remove).toHaveBeenCalled();
- expect(mockEntityMapper.save).toHaveBeenCalledWith(entity, true);
- expect(mockRouter.navigate).toHaveBeenCalled();
- }));
-});
diff --git a/src/app/core/entity/entity-remove.service.ts b/src/app/core/entity/entity-remove.service.ts
deleted file mode 100644
index 0a785df89d..0000000000
--- a/src/app/core/entity/entity-remove.service.ts
+++ /dev/null
@@ -1,109 +0,0 @@
-import { Injectable } from "@angular/core";
-import { ConfirmationDialogService } from "../common-components/confirmation-dialog/confirmation-dialog.service";
-import { EntityMapperService } from "./entity-mapper/entity-mapper.service";
-import { MatSnackBar } from "@angular/material/snack-bar";
-import { Entity } from "./model/entity";
-import { getUrlWithoutParams } from "../../utils/utils";
-import { Router } from "@angular/router";
-
-/**
- * Additional options that can be (partly) specified
- * for the several titles
- */
-export interface RemoveEntityTextOptions {
- dialogTitle?: string;
- dialogText?: string;
- deletedEntityInformation?: string;
-}
-
-/**
- * A service that can triggers a user flow to safely remove an entity,
- * including a confirmation dialog.
- */
-@Injectable({
- providedIn: "root",
-})
-export class EntityRemoveService {
- constructor(
- private confirmationDialog: ConfirmationDialogService,
- private entityMapper: EntityMapperService,
- private snackBar: MatSnackBar,
- private router: Router,
- ) {}
-
- /**
- * Shows a confirmation dialog to the user
- * and removes the entity if the user confirms.
- *
- * This also triggers a toast message, enabling the user to undo the action.
- *
- * @param entity The entity to remove
- * @param textOptions Options that you can specify to override the default options.
- * You can only specify some of the options, the options that you don't specify will then be
- * the default ones.
- * @param navigate whether upon delete the app will navigate back
- */
- async remove(
- entity: E,
- navigate: boolean = false,
- textOptions?: RemoveEntityTextOptions,
- ): Promise {
- const confirmation = await this.showDeleteConfirmationDialog(
- textOptions,
- entity,
- );
- if (!confirmation) {
- return false;
- }
-
- await this.entityMapper.remove(entity);
-
- let currentUrl: string;
- if (navigate) {
- currentUrl = getUrlWithoutParams(this.router);
- const parentUrl = currentUrl.substring(0, currentUrl.lastIndexOf("/"));
- await this.router.navigate([parentUrl]);
- }
-
- this.showSnackbarConfirmation(textOptions, entity, currentUrl);
-
- return true;
- }
-
- private async showDeleteConfirmationDialog(
- textOptions: RemoveEntityTextOptions,
- entity: Entity,
- ) {
- const dialogTitle =
- textOptions?.dialogTitle || $localize`:Delete confirmation title:Delete?`;
- const dialogText =
- textOptions?.dialogText ||
- $localize`:Delete confirmation text:Are you sure you want to delete this ${entity.getType()} record?`;
-
- return this.confirmationDialog.getConfirmation(dialogTitle, dialogText);
- }
-
- private showSnackbarConfirmation(
- textOptions: RemoveEntityTextOptions,
- entity: Entity,
- currentUrl?: string,
- ) {
- const snackBarTitle =
- textOptions?.deletedEntityInformation ||
- $localize`:Deleted Entity information:Deleted Entity ${entity.toString()}`;
-
- const snackBarRef = this.snackBar.open(
- snackBarTitle,
- $localize`:Undo deleting an entity:Undo`,
- {
- duration: 8000,
- },
- );
- snackBarRef.onAction().subscribe(async () => {
- await this.entityMapper.save(entity, true);
- if (currentUrl) {
- await this.router.navigate([currentUrl]);
- }
- });
- }
-}
diff --git a/src/app/core/entity/model/entity-update.ts b/src/app/core/entity/model/entity-update.ts
index a3f9ec6c97..551548f666 100644
--- a/src/app/core/entity/model/entity-update.ts
+++ b/src/app/core/entity/model/entity-update.ts
@@ -28,23 +28,34 @@ export interface UpdatedEntity {
* @param next An entity that should be updated as well as the type of update. This, as well as the entity
* may be undefined or null. In this event, the entities-array is returned as is.
* @param entities The entities to update, must be defined
+ * @param addIfMissing (Optional) whether to add an entity that comes through an update event but is not part of the array yet (default is to ignore)
* @return An array of the given entities with the update applied
*/
export function applyUpdate(
entities: T[],
next: UpdatedEntity,
+ addIfMissing: boolean = false,
): T[] {
if (!next || !next.entity || !entities) {
return entities;
}
- switch (next.type) {
- case "new":
- return [next.entity].concat(entities);
- case "update":
- return entities.map((e) =>
- e.getId() === next.entity.getId() ? next.entity : e,
- );
- case "remove":
- return entities.filter((e) => e.getId() !== next.entity.getId());
+
+ if (
+ next.type === "new" ||
+ (addIfMissing &&
+ next.type === "update" &&
+ !entities.find((e) => e.getId() === next.entity.getId()))
+ ) {
+ return [next.entity].concat(entities);
+ }
+
+ if (next.type === "update") {
+ return entities.map((e) =>
+ e.getId() === next.entity.getId() ? next.entity : e,
+ );
+ }
+
+ if (next.type === "remove") {
+ return entities.filter((e) => e.getId() !== next.entity.getId());
}
}
diff --git a/src/app/core/entity/model/entity.spec.ts b/src/app/core/entity/model/entity.spec.ts
index 3b5b97dd90..b3480503e4 100644
--- a/src/app/core/entity/model/entity.spec.ts
+++ b/src/app/core/entity/model/entity.spec.ts
@@ -117,6 +117,27 @@ describe("Entity", () => {
entity._rev = "123";
expect(entity.isNew).toBeFalse();
});
+
+ it("should convert toString using toStringAttributes config or special [anonymized] label", () => {
+ @DatabaseEntity("TestEntityForToString")
+ class TestEntity extends Entity {
+ static toStringAttributes = ["firstname", "lastname"];
+ static label = "TestEntity";
+ firstname = "John";
+ lastname = "Doe";
+ }
+
+ const testEntity = new TestEntity();
+
+ expect(testEntity.toString()).toBe("John Doe");
+
+ const anonymizedEntity = new TestEntity();
+ anonymizedEntity.firstname = undefined;
+ delete anonymizedEntity.lastname;
+ anonymizedEntity.anonymized = true;
+
+ expect(anonymizedEntity.toString()).toBe("[anonymized TestEntity]");
+ });
});
/**
diff --git a/src/app/core/entity/model/entity.ts b/src/app/core/entity/model/entity.ts
index 1f9f7724a1..1bf954d818 100644
--- a/src/app/core/entity/model/entity.ts
+++ b/src/app/core/entity/model/entity.ts
@@ -36,8 +36,6 @@ export type EntityConstructor = (new (
) => T) &
typeof Entity;
-export const ENTITY_CONFIG_PREFIX = "entity:";
-
/**
* "Entity" is a base class for all domain model classes.
* It implements the basic general properties and methods that are required for all Entity types
@@ -168,34 +166,46 @@ export class Entity {
return;
}
+ /**
+ * whether this entity type can contain "personally identifiable information" (PII)
+ * and therefore should follow strict data protection requirements
+ * and offer a function to anonymize records.
+ */
+ static hasPII: boolean = false;
+
/**
* Internal database id.
* This is usually combined from the ENTITY_TYPE as a prefix with the entityId field `EntityType:entityId`
* @example "Entity:123"
*/
- @DatabaseField() private _id: string;
+ @DatabaseField({ anonymize: "retain" }) private _id: string;
/** internal database doc revision, used to detect conflicts by PouchDB/CouchDB */
- @DatabaseField() _rev: string;
+ @DatabaseField({ anonymize: "retain" }) _rev: string;
@DatabaseField({
dataType: "schema-embed",
additional: UpdateMetadata,
+ anonymize: "retain",
})
created: UpdateMetadata;
@DatabaseField({
dataType: "schema-embed",
additional: UpdateMetadata,
+ anonymize: "retain",
})
updated: UpdateMetadata;
- @DatabaseField({
- label: $localize`:Label of checkbox:Inactive`,
- description: $localize`:Description of checkbox:Ticking this box will archive the record. No data will be lost but the record will be hidden.`,
- })
+ @DatabaseField({ anonymize: "retain" })
inactive: boolean;
+ /**
+ * Whether this entity has been anonymized and therefore cannot be re-activated.
+ */
+ @DatabaseField({ anonymize: "retain" })
+ anonymized: boolean;
+
/** whether this entity object is newly created and not yet saved to database */
get isNew(): boolean {
return !this._rev;
@@ -215,18 +225,21 @@ export class Entity {
}
/**
- * Check, if this entity is considered active.
- * This is either taken from the property "inactive" (configured) or "active" (not configured).
+ * Check, if this entity is considered active or archived.
+ *
+ * This is taken from the property "inactive".
* If the property doesn't exist, the default is `true`.
- * Subclasses may overwrite this functionality.
+ *
+ * Some subclasses overwrite this functionality, but this logic is considered deprecated (!) now
+ * and implementations have to make sure that "inactive" property takes precedence!
*/
get isActive(): boolean {
- if (this["active"] !== undefined) {
- return this["active"];
- }
if (this.inactive !== undefined) {
return !this.inactive;
}
+ if (this["active"] !== undefined) {
+ return this["active"];
+ }
return true;
}
@@ -294,6 +307,17 @@ export class Entity {
* @returns {string} the instance's string representation.
*/
public toString(): string {
+ if (
+ this.anonymized &&
+ this.getConstructor().toStringAttributes.every(
+ (attr) => this[attr] === undefined,
+ )
+ ) {
+ return $localize`:Entity.toString fallback for anonymized record:[anonymized ${
+ this.getConstructor().label
+ }]`;
+ }
+
return this.getConstructor()
.toStringAttributes.map((attr) => this[attr])
.join(" ");
diff --git a/src/app/core/entity/schema/entity-schema-field.ts b/src/app/core/entity/schema/entity-schema-field.ts
index f8c83694d2..c6c5f210b0 100644
--- a/src/app/core/entity/schema/entity-schema-field.ts
+++ b/src/app/core/entity/schema/entity-schema-field.ts
@@ -16,6 +16,7 @@
*/
import { FormValidatorConfig } from "../../common-components/entity-form/dynamic-form-validators/form-validator-config";
+import { EntityReferenceRole } from "../../basic-datatypes/entity/entity-reference-role";
/**
* Interface for additional configuration about a DatabaseField schema.
@@ -66,6 +67,17 @@ export interface EntitySchemaField {
*/
additional?: any;
+ /**
+ * (Optional) If the dataType of this field references another entity,
+ * define the role of this relationship for the entity containing this field.
+ *
+ * i.e. how "important" is the entity this field is referencing?
+ * Does this the entity containing this field (not the referenced entity) still have meaning after the referenced entity has been deleted?
+ *
+ * see options of the `EntityReferenceRole` type
+ */
+ entityReferenceRole?: EntityReferenceRole;
+
/**
* (Optional) Define using which component this property should be displayed in lists and forms.
*
@@ -104,6 +116,15 @@ export interface EntitySchemaField {
/** whether to show this field in the default details view */
showInDetailsView?: boolean;
+
+ /**
+ * whether the field will be retained when the entity is "anonymized".
+ *
+ * By default, fields are removed (data minimization by default).
+ *
+ * "retain-anonymized" triggers a special dataType action to retain the data partially in a special, anonymized form.
+ */
+ anonymize?: "retain" | "retain-anonymized";
}
/**
diff --git a/src/app/core/entity/schema/entity-schema.service.spec.ts b/src/app/core/entity/schema/entity-schema.service.spec.ts
index 2b72caac62..05bede894e 100644
--- a/src/app/core/entity/schema/entity-schema.service.spec.ts
+++ b/src/app/core/entity/schema/entity-schema.service.spec.ts
@@ -26,6 +26,7 @@ import { EntitySchemaField } from "./entity-schema-field";
import { ConfigurableEnumDatatype } from "../../basic-datatypes/configurable-enum/configurable-enum-datatype/configurable-enum.datatype";
import { MockedTestingModule } from "../../../utils/mocked-testing.module";
import { EntityDatatype } from "../../basic-datatypes/entity/entity.datatype";
+import { DatabaseEntity, EntityRegistry } from "../database-entity.decorator";
describe("EntitySchemaService", () => {
let service: EntitySchemaService;
@@ -133,6 +134,52 @@ describe("EntitySchemaService", () => {
EntityDatatype,
);
});
+
+ it("should getEntityTypesReferencingType with all entity types having schema fields referencing the given type", () => {
+ @DatabaseEntity("ReferencingEntity")
+ class ReferencingEntity extends Entity {
+ @DatabaseField({
+ dataType: "entity-array",
+ additional: "Child",
+ })
+ refChildren: string[];
+
+ @DatabaseField({
+ dataType: "entity",
+ additional: "Child",
+ })
+ refChild: string;
+
+ @DatabaseField({
+ dataType: "entity",
+ additional: "School",
+ })
+ refSchool: string;
+
+ @DatabaseField({
+ dataType: "entity-array",
+ additional: ["Child", "School"],
+ })
+ multiTypeRef: string[];
+ }
+
+ const entities = new EntityRegistry();
+ entities.addAll([
+ [ReferencingEntity.ENTITY_TYPE, ReferencingEntity],
+ [Entity.ENTITY_TYPE, Entity],
+ ]);
+ const injector = TestBed.inject(Injector);
+ spyOn(injector, "get").and.returnValue(entities);
+
+ const result = service.getEntityTypesReferencingType("Child");
+
+ expect(result).toEqual([
+ {
+ entityType: ReferencingEntity,
+ referencingProperties: ["refChildren", "refChild", "multiTypeRef"],
+ },
+ ]);
+ });
});
export function testDatatype(
diff --git a/src/app/core/entity/schema/entity-schema.service.ts b/src/app/core/entity/schema/entity-schema.service.ts
index ca89c52a94..4fe5075420 100644
--- a/src/app/core/entity/schema/entity-schema.service.ts
+++ b/src/app/core/entity/schema/entity-schema.service.ts
@@ -15,11 +15,13 @@
* along with ndb-core. If not, see .
*/
-import { Entity } from "../model/entity";
+import { Entity, EntityConstructor } from "../model/entity";
import { Injectable, Injector } from "@angular/core";
import { EntitySchema } from "./entity-schema";
import { EntitySchemaField } from "./entity-schema-field";
import { DefaultDatatype } from "../default-datatype/default.datatype";
+import { EntityRegistry } from "../database-entity.decorator";
+import { asArray } from "../../../utils/utils";
/**
* Transform between entity instances and database objects
@@ -236,4 +238,31 @@ export class EntitySchemaService {
schemaField.dataType,
).transformToObjectFormat(value, schemaField, dataObject);
}
+
+ /**
+ * Get all entity types whose schema includes fields referencing the given type.
+ *
+ * e.g. given Child -> [Note, ChildSchoolRelation, ...]
+ * @param type
+ */
+ getEntityTypesReferencingType(type: string): {
+ entityType: EntityConstructor;
+ referencingProperties: string[];
+ }[] {
+ const referencingTypes = [];
+ for (const t of this.injector.get(EntityRegistry).values()) {
+ for (const [key, field] of t.schema.entries()) {
+ if (asArray(field.additional).includes(type)) {
+ let refType = referencingTypes.find((e) => e.entityType === t);
+ if (!refType) {
+ refType = { entityType: t, referencingProperties: [] };
+ referencingTypes.push(refType);
+ }
+
+ refType.referencingProperties.push(key);
+ }
+ }
+ }
+ return referencingTypes;
+ }
}
diff --git a/src/app/core/export/download-service/download.service.spec.ts b/src/app/core/export/download-service/download.service.spec.ts
index 9ae04ea0ce..c45574a155 100644
--- a/src/app/core/export/download-service/download.service.spec.ts
+++ b/src/app/core/export/download-service/download.service.spec.ts
@@ -49,6 +49,7 @@ describe("DownloadService", () => {
// reset createElement otherwise results in: 'an Error was thrown after all'
document.createElement = oldCreateElement;
});
+
it("should contain a column for every property", async () => {
const docs = [
{ _id: "Test:1", test: 1 },
@@ -77,11 +78,12 @@ describe("DownloadService", () => {
'"_id","_rev","propOne","propTwo"' +
DownloadService.SEPARATOR_ROW +
'"TestForCsvEntity:1","2","first","second"';
+ spyOn(service, "exportFile").and.returnValue(expected);
const result = await service.createCsv([test]);
expect(result).toEqual(expected);
});
- it("should transform object properties to their label for export", async () => {
+ it("should transform object values to their label for export when available (e.g. configurable-enum)", async () => {
const testEnumValue: ConfigurableEnumValue = {
id: "ID VALUE",
label: "label value",
@@ -90,9 +92,10 @@ describe("DownloadService", () => {
@DatabaseEntity("TestEntity")
class TestEntity extends Entity {
- @DatabaseField() enumProperty: ConfigurableEnumValue;
- @DatabaseField() dateProperty: Date;
- @DatabaseField() boolProperty: boolean;
+ @DatabaseField({ label: "test enum" })
+ enumProperty: ConfigurableEnumValue;
+ @DatabaseField({ label: "test date" }) dateProperty: Date;
+ @DatabaseField({ label: "test boolean" }) boolProperty: boolean;
}
const testEntity = new TestEntity();
@@ -105,12 +108,65 @@ describe("DownloadService", () => {
const rows = csvExport.split(DownloadService.SEPARATOR_ROW);
expect(rows).toHaveSize(1 + 1); // includes 1 header line
const columnValues = rows[1].split(DownloadService.SEPARATOR_COL);
- expect(columnValues).toHaveSize(3 + 1); // Properties + _id
+ expect(columnValues).toHaveSize(3); // Properties (_id is filter out by default)
expect(columnValues).toContain('"' + testEnumValue.label + '"');
expect(columnValues).toContain('"' + testDate + '"');
expect(columnValues).toContain('"true"');
});
+ it("should export all properties using object keys as headers, if no schema is available", async () => {
+ const docs = [
+ { _id: "Test:1", name: "Child 1" },
+ { _id: "Test:2", name: "Child 2" },
+ ];
+
+ const csvExport = await service.createCsv(docs);
+
+ const rows = csvExport.split(DownloadService.SEPARATOR_ROW);
+ expect(rows).toHaveSize(2 + 1); // includes 1 header line
+ const columnHeaders = rows[0].split(DownloadService.SEPARATOR_COL);
+ const columnValues = rows[1].split(DownloadService.SEPARATOR_COL);
+
+ expect(columnValues).toHaveSize(2);
+ expect(columnHeaders).toHaveSize(2);
+ expect(columnHeaders).toContain('"_id"');
+ });
+
+ it("should only export columns that have labels defined in entity schema and use the schema labels as export headers", async () => {
+ const testString: string = "Test 1";
+
+ @DatabaseEntity("LabelTestEntity")
+ class LabelTestEntity extends Entity {
+ @DatabaseField({ label: "test string" }) stringProperty: string;
+ @DatabaseField({ label: "test date" }) otherProperty: string;
+ @DatabaseField() boolProperty: boolean;
+ }
+
+ const labelTestEntity = new LabelTestEntity();
+ labelTestEntity.stringProperty = testString;
+ labelTestEntity.otherProperty = "x";
+ labelTestEntity.boolProperty = true;
+
+ const incompleteTestEntity = new LabelTestEntity();
+ incompleteTestEntity.otherProperty = "second row";
+
+ const csvExport = await service.createCsv([
+ labelTestEntity,
+ incompleteTestEntity,
+ ]);
+
+ const rows = csvExport.split(DownloadService.SEPARATOR_ROW);
+ expect(rows).toHaveSize(1 + 2); // includes 1 header line
+
+ const columnHeaders = rows[0].split(DownloadService.SEPARATOR_COL);
+ expect(columnHeaders).toHaveSize(2);
+ expect(columnHeaders).toContain('"test string"');
+ expect(columnHeaders).toContain('"test date"');
+
+ const entity2Values = rows.find((r) => r.includes("second row"));
+ expect(entity2Values).toEqual(',"second row"'); // first column empty!
+ });
+
it("should export a date as YYYY-MM-dd only", async () => {
const dateString = "2021-01-01";
const dateObject = moment(dateString).toDate();
diff --git a/src/app/core/export/download-service/download.service.ts b/src/app/core/export/download-service/download.service.ts
index 147df776db..57fe6180fc 100644
--- a/src/app/core/export/download-service/download.service.ts
+++ b/src/app/core/export/download-service/download.service.ts
@@ -5,6 +5,7 @@ import { LoggingService } from "../../logging/logging.service";
import { DataTransformationService } from "../data-transformation-service/data-transformation.service";
import { transformToReadableFormat } from "../../common-components/entity-subrecord/entity-subrecord/value-accessor";
import { Papa } from "ngx-papaparse";
+import { EntitySchemaField } from "app/core/entity/schema/entity-schema-field";
/**
* This service allows to start a download process from the browser.
@@ -90,17 +91,62 @@ export class DownloadService {
* @returns string a valid CSV string of the input data
*/
async createCsv(data: any[]): Promise {
- // Collect all properties because papa only uses the properties of the first object
+ let entityConstructor: any;
+
+ if (data.length > 0 && typeof data[0]?.getConstructor === "function") {
+ entityConstructor = data[0].getConstructor();
+ }
const keys = new Set();
data.forEach((row) => Object.keys(row).forEach((key) => keys.add(key)));
data = data.map(transformToReadableFormat);
- return this.papa.unparse(data, {
- quotes: true,
- header: true,
- newline: DownloadService.SEPARATOR_ROW,
- columns: [...keys],
+ if (!entityConstructor) {
+ return this.papa.unparse(data, {
+ quotes: true,
+ header: true,
+ newline: DownloadService.SEPARATOR_ROW,
+ columns: [...keys],
+ });
+ }
+
+ const result = this.exportFile(data, entityConstructor);
+ return result;
+ }
+
+ exportFile(data: any[], entityConstructor: { schema: any }) {
+ const entitySchema = entityConstructor.schema;
+ const columnLabels = new Map();
+
+ entitySchema.forEach((value: { label: EntitySchemaField }, key: string) => {
+ if (value.label) columnLabels.set(key, value.label);
});
+
+ const exportEntities = data.map((item) => {
+ let newItem = {};
+ for (const key in item) {
+ if (columnLabels.has(key)) {
+ newItem[key] = item[key];
+ }
+ }
+ return newItem;
+ });
+
+ const columnKeys: string[] = Array.from(columnLabels.keys());
+ const labels: any[] = Array.from(columnLabels.values());
+ const orderedData: any[] = exportEntities.map((item) =>
+ columnKeys.map((key) => item[key]),
+ );
+
+ return this.papa.unparse(
+ {
+ fields: labels,
+ data: orderedData,
+ },
+ {
+ quotes: true,
+ newline: DownloadService.SEPARATOR_ROW,
+ },
+ );
}
}
diff --git a/src/app/core/export/query.service.spec.ts b/src/app/core/export/query.service.spec.ts
index 1b346dfa12..f70d399a05 100644
--- a/src/app/core/export/query.service.spec.ts
+++ b/src/app/core/export/query.service.spec.ts
@@ -497,9 +497,8 @@ describe("QueryService", () => {
const attendanceArrayQuery = `${EventNote.ENTITY_TYPE}:toArray:getAttendanceArray(true)`;
- const attendanceResult: AttendanceInfo = await queryData(
- attendanceArrayQuery,
- );
+ const attendanceResult: AttendanceInfo =
+ await queryData(attendanceArrayQuery);
expect(attendanceResult).toContain({
participant: presentTwiceWithSchool.getId(),
@@ -636,6 +635,34 @@ describe("QueryService", () => {
expect(res).toBe(3);
});
+ it("should calculate the average of values", () => {
+ const data = [
+ { a: 5, b: 2 },
+ { b: "11" },
+ { b: -1 },
+ { b: 100 },
+ { a: "invalid" },
+ ];
+
+ let res = service.queryData("a:avg", undefined, undefined, data);
+ expect(res).toBe("5");
+
+ // Returns valid number if no values are available
+ res = service.queryData("a:avg", undefined, undefined, [{ b: 1 }]);
+ expect(res).toBe("0");
+
+ // Numbers are fixed to provided decimals
+ res = service.queryData("a:avg(2)", undefined, undefined, [
+ { a: 3 },
+ { a: 2 },
+ ]);
+ expect(res).toBe("2.50");
+
+ // Handles 0 correctly
+ res = service.queryData("a:avg", undefined, undefined, [{ a: 0 }]);
+ expect(res).toBe("0");
+ });
+
function queryData(query: string, from?: Date, to?: Date, data?: any) {
return service
.cacheRequiredData(query, from, to)
diff --git a/src/app/core/export/query.service.ts b/src/app/core/export/query.service.ts
index a3379768cf..52c2b3ca2c 100644
--- a/src/app/core/export/query.service.ts
+++ b/src/app/core/export/query.service.ts
@@ -98,6 +98,7 @@ export class QueryService {
unique: this.unique,
count: this.count,
sum: this.sum,
+ avg: this.avg,
addPrefix: this.addPrefix,
toEntities: this.toEntities.bind(this),
getRelated: this.getRelated.bind(this),
@@ -238,7 +239,7 @@ export class QueryService {
/**
* Returns the (integer) sum of the provided array.
* It can also handle integers in strings, e.g. "3"
- * @param data and integer array
+ * @param data an integer array
* @private
*/
private sum(data: any[]): number {
@@ -248,6 +249,25 @@ export class QueryService {
}, 0);
}
+ /**
+ * Returns the avg of the provided array as string.
+ * It can also handle integers in strings, e.g. "3".
+ * The average is only calculated if the value exists and is a valid number.
+ * @param data an integer array
+ * @param decimals the amount of decimals for the result, default 0
+ * @private
+ */
+ private avg(data: any[], decimals = 0): string {
+ const numbers = data
+ .map((d) => Number.parseInt(d))
+ .filter((i) => !Number.isNaN(i));
+ const result =
+ numbers.length === 0
+ ? 0
+ : numbers.reduce((i, sum) => sum + i, 0) / numbers.length;
+ return result.toFixed(decimals);
+ }
+
/**
* Turns a list of ids (with the entity prefix) into a list of entities
* @param ids the array of ids with entity prefix
diff --git a/src/app/core/filter/filter-generator/filter-generator.service.ts b/src/app/core/filter/filter-generator/filter-generator.service.ts
index 60c9fd0094..a07e83e514 100644
--- a/src/app/core/filter/filter-generator/filter-generator.service.ts
+++ b/src/app/core/filter/filter-generator/filter-generator.service.ts
@@ -90,9 +90,8 @@ export class FilterGeneratorService {
this.entities.has(schema.additional)
) {
const entityType = filterConfig.type || schema.additional;
- const filterEntities = await this.entityMapperService.loadType(
- entityType,
- );
+ const filterEntities =
+ await this.entityMapperService.loadType(entityType);
filter = new EntityFilter(
filterConfig.id,
filterConfig.label || schema.label,
diff --git a/src/app/core/filter/filter.service.ts b/src/app/core/filter/filter.service.ts
index 8f58997b93..2c90c2db40 100644
--- a/src/app/core/filter/filter.service.ts
+++ b/src/app/core/filter/filter.service.ts
@@ -68,10 +68,10 @@ export class FilterService {
[key, value] = this.transformNestedKey(key, value);
}
const property = schema.get(key);
- if (property.dataType === "configurable-enum") {
+ if (property?.dataType === "configurable-enum") {
value = this.parseConfigurableEnumValue(property, value);
}
- if (property.dataType.includes("date")) {
+ if (property?.dataType.includes("date")) {
value = moment(value).toDate();
}
newEntity[key] = value;
diff --git a/src/app/core/form-dialog/dialog-buttons/dialog-buttons.component.html b/src/app/core/form-dialog/dialog-buttons/dialog-buttons.component.html
index dfca7af7cc..19d8cabcae 100644
--- a/src/app/core/form-dialog/dialog-buttons/dialog-buttons.component.html
+++ b/src/app/core/form-dialog/dialog-buttons/dialog-buttons.component.html
@@ -33,32 +33,6 @@
Go to details
-
-
-
-
-
-
- Delete
-
+
-
+
diff --git a/src/app/core/form-dialog/dialog-buttons/dialog-buttons.component.spec.ts b/src/app/core/form-dialog/dialog-buttons/dialog-buttons.component.spec.ts
index b25d9903a8..796192eac0 100644
--- a/src/app/core/form-dialog/dialog-buttons/dialog-buttons.component.spec.ts
+++ b/src/app/core/form-dialog/dialog-buttons/dialog-buttons.component.spec.ts
@@ -15,7 +15,6 @@ import { Child } from "../../../child-dev-project/children/model/child";
import { Router } from "@angular/router";
import { MockedTestingModule } from "../../../utils/mocked-testing.module";
import { FormGroup } from "@angular/forms";
-import { EntityRemoveService } from "../../entity/entity-remove.service";
import { firstValueFrom, Subject } from "rxjs";
import { UnsavedChangesService } from "../../entity-details/form/unsaved-changes.service";
@@ -95,16 +94,11 @@ describe("DialogButtonsComponent", () => {
});
it("should close the dialog if a entity is deleted", async () => {
- const removeSpy = spyOn(TestBed.inject(EntityRemoveService), "remove");
+ component.onAction("some other action");
+ expect(dialogRef.close).not.toHaveBeenCalled();
- removeSpy.and.resolveTo(true);
- await component.delete();
+ component.onAction("delete");
expect(dialogRef.close).toHaveBeenCalled();
-
- dialogRef.close.calls.reset();
- removeSpy.and.resolveTo(false);
- await component.delete();
- expect(dialogRef.close).not.toHaveBeenCalled();
});
it("should only close the dialog if user confirms to discard changes", fakeAsync(() => {
diff --git a/src/app/core/form-dialog/dialog-buttons/dialog-buttons.component.ts b/src/app/core/form-dialog/dialog-buttons/dialog-buttons.component.ts
index 8006508e4e..b7567487aa 100644
--- a/src/app/core/form-dialog/dialog-buttons/dialog-buttons.component.ts
+++ b/src/app/core/form-dialog/dialog-buttons/dialog-buttons.component.ts
@@ -7,15 +7,14 @@ import { DisableEntityOperationDirective } from "../../permissions/permission-di
import { Entity } from "../../entity/model/entity";
import { FormGroup } from "@angular/forms";
import { InvalidFormFieldError } from "../../common-components/entity-form/invalid-form-field.error";
-import { EntityRemoveService } from "../../entity/entity-remove.service";
import { EntityFormService } from "../../common-components/entity-form/entity-form.service";
import { AlertService } from "../../alerts/alert.service";
import { MatMenuModule } from "@angular/material/menu";
import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
import { Router, RouterLink } from "@angular/router";
import { EntityAbility } from "../../permissions/ability/entity-ability";
-import { ConfirmationDialogService } from "../../common-components/confirmation-dialog/confirmation-dialog.service";
import { UnsavedChangesService } from "../../entity-details/form/unsaved-changes.service";
+import { EntityActionsMenuComponent } from "../../entity-details/entity-actions-menu/entity-actions-menu.component";
@Component({
selector: "app-dialog-buttons",
@@ -29,6 +28,7 @@ import { UnsavedChangesService } from "../../entity-details/form/unsaved-changes
MatMenuModule,
FontAwesomeModule,
RouterLink,
+ EntityActionsMenuComponent,
],
templateUrl: "./dialog-buttons.component.html",
styleUrls: ["./dialog-buttons.component.scss"],
@@ -42,10 +42,8 @@ export class DialogButtonsComponent implements OnInit {
private entityFormService: EntityFormService,
private dialog: MatDialogRef,
private alertService: AlertService,
- private entityRemoveService: EntityRemoveService,
private router: Router,
private ability: EntityAbility,
- private confirmation: ConfirmationDialogService,
private unsavedChanges: UnsavedChangesService,
) {
this.dialog.disableClose = true;
@@ -97,9 +95,8 @@ export class DialogButtonsComponent implements OnInit {
});
}
- async delete() {
- const result = await this.entityRemoveService.remove(this.entity);
- if (result) {
+ onAction(action: string) {
+ if (action === "delete") {
this.dialog.close();
}
}
diff --git a/src/app/core/import/import.service.spec.ts b/src/app/core/import/import.service.spec.ts
index 6af1df0f2b..34b196179a 100644
--- a/src/app/core/import/import.service.spec.ts
+++ b/src/app/core/import/import.service.spec.ts
@@ -2,10 +2,6 @@ import { TestBed } from "@angular/core/testing";
import { ImportService } from "./import.service";
import { EntityMapperService } from "../entity/entity-mapper/entity-mapper.service";
-import {
- EntityRegistry,
- entityRegistry,
-} from "../entity/database-entity.decorator";
import { Entity } from "../entity/model/entity";
import { ImportMetadata, ImportSettings } from "./import-metadata";
import { ColumnMapping } from "./column-mapping";
@@ -13,32 +9,25 @@ import {
expectEntitiesToBeInDatabase,
expectEntitiesToMatch,
} from "../../utils/expect-entity-data.spec";
-import { HealthCheck } from "../../child-dev-project/children/health-checkup/model/health-check";
import moment from "moment";
import { Child } from "../../child-dev-project/children/model/child";
import { RecurringActivity } from "../../child-dev-project/attendance/model/recurring-activity";
import { ChildSchoolRelation } from "../../child-dev-project/children/model/childSchoolRelation";
-import { mockEntityMapper } from "../entity/entity-mapper/mock-entity-mapper-service";
-import { ConfigurableEnumService } from "../basic-datatypes/configurable-enum/configurable-enum.service";
-import { CoreModule } from "../core.module";
-import { ComponentRegistry } from "../../dynamic-components";
import { EntityArrayDatatype } from "../basic-datatypes/entity-array/entity-array.datatype";
+import { mockEntityMapper } from "../entity/entity-mapper/mock-entity-mapper-service";
+import { CoreTestingModule } from "../../utils/core-testing.module";
+import { EntityRegistry } from "../entity/database-entity.decorator";
+import { DatabaseField } from "../entity/database-field.decorator";
describe("ImportService", () => {
let service: ImportService;
beforeEach(async () => {
TestBed.configureTestingModule({
- imports: [CoreModule],
+ imports: [CoreTestingModule],
providers: [
ImportService,
- { provide: EntityRegistry, useValue: entityRegistry },
{ provide: EntityMapperService, useValue: mockEntityMapper() },
- {
- provide: ConfigurableEnumService,
- useValue: new ConfigurableEnumService(mockEntityMapper(), null),
- },
- ComponentRegistry,
],
});
service = TestBed.inject(ImportService);
@@ -67,49 +56,61 @@ describe("ImportService", () => {
});
it("should transform raw data to mapped entities", async () => {
- HealthCheck.schema.set("entityArray", {
- dataType: EntityArrayDatatype.dataType,
- additional: "Child",
- });
+ class ImportTestTarget extends Entity {
+ @DatabaseField() name: string;
+ @DatabaseField() counter: number;
+ @DatabaseField() date: Date;
+ @DatabaseField({
+ dataType: EntityArrayDatatype.dataType,
+ additional: "Child",
+ })
+ entityRefs: string[];
+ }
+ spyOn(TestBed.inject(EntityRegistry), "get").and.callFake(
+ (entityType: string) =>
+ entityType === "ImportTestTarget" ? ImportTestTarget : Child,
+ );
+
const child = Child.create("Child Name");
await TestBed.inject(EntityMapperService).save(child);
+
const rawData: any[] = [
- { x: "John", y: "111" },
- { x: "Jane" },
- { x: "broken date", y: "foo" }, // date column; ("y") ignored
- { x: "with broken mapping column", brokenMapping: "foo" }, // column mapped to non-existing property ignored
- { x: "", onlyUnmappedColumn: "1" }, // only empty or unmapped columns => row skipped
- { x: "with zero", y: "0" }, // 0 value mapped
- { x: "custom mapping fn", z: "30.01.2023" },
- { x: "entity array", childName: child.name },
+ { rawName: "John", rawCounter: "111" },
+ { rawName: "Jane" },
+ { rawName: "broken date", rawCounter: "foo" }, // number column; ("rawCounter") ignored
+ { rawName: "with broken mapping column", brokenMapping: "foo" }, // column mapped to non-existing property ignored
+ { rawName: "", onlyUnmappedColumn: "1" }, // only empty or unmapped columns => row skipped
+ { rawName: "with zero", rawCounter: "0" }, // 0 value mapped
+ { rawName: "custom mapping fn", rawDate: "30.01.2023" },
+ { rawName: "entity array", rawRefName: child.name },
];
const columnMapping: ColumnMapping[] = [
- { column: "x", propertyName: "child" },
- { column: "y", propertyName: "height" },
- { column: "z", propertyName: "date", additional: "DD.MM.YYYY" },
+ { column: "rawName", propertyName: "name" },
+ { column: "rawCounter", propertyName: "counter" },
+ { column: "rawDate", propertyName: "date", additional: "DD.MM.YYYY" },
{ column: "brokenMapping", propertyName: "brokenMapping" },
- { column: "childName", propertyName: "entityArray", additional: "name" },
+ { column: "rawRefName", propertyName: "entityRefs", additional: "name" },
];
const parsedEntities = await service.transformRawDataToEntities(
rawData,
- HealthCheck.ENTITY_TYPE,
+ "ImportTestTarget",
columnMapping,
);
let expectedEntities: any[] = [
- { child: "John", height: 111 },
- { child: "Jane" },
- { child: "broken date" },
- { child: "with broken mapping column" },
- { child: "with zero", height: 0 },
- { child: "custom mapping fn", date: moment("2023-01-30").toDate() },
- { child: "entity array", entityArray: [child.getId()] },
+ { name: "John", counter: 111 },
+ { name: "Jane" },
+ { name: "broken date" },
+ { name: "with broken mapping column" },
+ { name: "with zero", counter: 0 },
+ { name: "custom mapping fn", date: moment("2023-01-30").toDate() },
+ { name: "entity array", entityRefs: [child.getId()] },
];
expectEntitiesToMatch(
parsedEntities,
- expectedEntities.map((e) => Object.assign(new HealthCheck(), e)),
+ expectedEntities.map((e) => Object.assign(new ImportTestTarget(), e)),
true,
);
});
diff --git a/src/app/core/site-settings/site-settings.service.spec.ts b/src/app/core/site-settings/site-settings.service.spec.ts
index d9aaf3875c..a0dba5c378 100644
--- a/src/app/core/site-settings/site-settings.service.spec.ts
+++ b/src/app/core/site-settings/site-settings.service.spec.ts
@@ -11,14 +11,13 @@ import { SiteSettings } from "./site-settings";
import { of } from "rxjs";
import { Title } from "@angular/platform-browser";
import { availableLocales } from "../language/languages";
-import { CoreModule } from "../core.module";
-import { ComponentRegistry } from "../../dynamic-components";
import { ConfigurableEnumModule } from "../basic-datatypes/configurable-enum/configurable-enum.module";
import { EntityAbility } from "../permissions/ability/entity-ability";
import { FileModule } from "../../features/file/file.module";
import { EntitySchemaService } from "../entity/schema/entity-schema.service";
import { LoggingService } from "../logging/logging.service";
import { ConfigurableEnumService } from "../basic-datatypes/configurable-enum/configurable-enum.service";
+import { CoreTestingModule } from "../../utils/core-testing.module";
describe("SiteSettingsService", () => {
let service: SiteSettingsService;
@@ -30,9 +29,8 @@ describe("SiteSettingsService", () => {
entityMapper = mockEntityMapper();
mockFileService = jasmine.createSpyObj(["loadFile"]);
TestBed.configureTestingModule({
- imports: [CoreModule, ConfigurableEnumModule, FileModule],
+ imports: [CoreTestingModule, ConfigurableEnumModule, FileModule],
providers: [
- ComponentRegistry,
{ provide: FileService, useValue: mockFileService },
{ provide: EntityMapperService, useValue: entityMapper },
EntityAbility,
diff --git a/src/app/core/support/support/support.component.spec.ts b/src/app/core/support/support/support.component.spec.ts
index c1e14b2221..c94c26f7cc 100644
--- a/src/app/core/support/support/support.component.spec.ts
+++ b/src/app/core/support/support/support.component.spec.ts
@@ -24,6 +24,13 @@ import { DownloadService } from "../../export/download-service/download.service"
import { AuthService } from "../../session/auth/auth.service";
import { TEST_USER } from "../../../utils/mock-local-session";
+class MockDeleteRequest {
+ onsuccess: () => {};
+ constructor() {
+ setTimeout(() => this.onsuccess());
+ }
+}
+
describe("SupportComponent", () => {
let component: SupportComponent;
let fixture: ComponentFixture;
@@ -36,6 +43,12 @@ describe("SupportComponent", () => {
userAgent: "mock user agent",
serviceWorker: { getRegistrations: () => [], ready: Promise.resolve() },
},
+ indexedDB: {
+ databases: jasmine.createSpy(),
+ deleteDatabase: jasmine
+ .createSpy()
+ .and.callFake(() => new MockDeleteRequest()),
+ },
};
let mockLocation: any;
@@ -112,13 +125,18 @@ describe("SupportComponent", () => {
mockWindow.navigator.serviceWorker.getRegistrations = () => [
{ unregister: unregisterSpy },
];
+ mockWindow.indexedDB.databases.and.resolveTo([
+ { name: "db1" },
+ { name: "db2" },
+ ]);
await component.resetApplication();
- expect(mockDB.destroy).toHaveBeenCalled();
expect(unregisterSpy).toHaveBeenCalled();
expect(localStorage.getItem("someItem")).toBeNull();
expect(mockLocation.pathname).toBe("");
+ expect(mockWindow.indexedDB.deleteDatabase).toHaveBeenCalledWith("db1");
+ expect(mockWindow.indexedDB.deleteDatabase).toHaveBeenCalledWith("db2");
});
it("should display the service worker logs after they are available", fakeAsync(() => {
diff --git a/src/app/core/support/support/support.component.ts b/src/app/core/support/support/support.component.ts
index 8bb95d6f15..0f5743f03d 100644
--- a/src/app/core/support/support/support.component.ts
+++ b/src/app/core/support/support/support.component.ts
@@ -108,6 +108,11 @@ export class SupportComponent implements OnInit {
}
private initDbInfo() {
+ if (!this.database || !this.database.getPouchDB()) {
+ this.dbInfo = "db not initialized";
+ return;
+ }
+
return this.database
.getPouchDB()
.info()
@@ -154,7 +159,9 @@ export class SupportComponent implements OnInit {
return;
}
- await this.database.destroy();
+ const dbs = await this.window.indexedDB.databases();
+ await Promise.all(dbs.map(({ name }) => this.destroyDatabase(name)));
+
const registrations =
await this.window.navigator.serviceWorker.getRegistrations();
const unregisterPromises = registrations.map((reg) => reg.unregister());
@@ -171,4 +178,12 @@ export class SupportComponent implements OnInit {
"aamdigital_data_" + new Date().toISOString(),
);
}
+
+ private destroyDatabase(name: string) {
+ return new Promise((resolve, reject) => {
+ const del = this.window.indexedDB.deleteDatabase(name);
+ del.onsuccess = resolve;
+ del.onerror = reject;
+ });
+ }
}
diff --git a/src/app/core/ui/routed-view/routed-view.component.spec.ts b/src/app/core/ui/routed-view/routed-view.component.spec.ts
new file mode 100644
index 0000000000..a4a9eab81d
--- /dev/null
+++ b/src/app/core/ui/routed-view/routed-view.component.spec.ts
@@ -0,0 +1,76 @@
+import {
+ ComponentFixture,
+ fakeAsync,
+ TestBed,
+ tick,
+} from "@angular/core/testing";
+
+import { RoutedViewComponent } from "./routed-view.component";
+import { ActivatedRoute } from "@angular/router";
+import { BehaviorSubject } from "rxjs";
+import { ComponentRegistry } from "../../../dynamic-components";
+import { Component } from "@angular/core";
+
+@Component({
+ template: ``,
+})
+class MockComponent {}
+
+describe("RoutedViewComponent", () => {
+ let component: RoutedViewComponent;
+ let fixture: ComponentFixture;
+
+ let mockActivatedRoute;
+
+ function mockParamMap(params: { [key: string]: any }) {
+ return { keys: Object.keys(params), get: (key: string) => params[key] };
+ }
+
+ beforeEach(() => {
+ mockActivatedRoute = {
+ data: new BehaviorSubject({
+ component: "InitialComponent",
+ config: { testFlag: true },
+ }),
+ paramMap: new BehaviorSubject(mockParamMap({})),
+ };
+
+ TestBed.configureTestingModule({
+ imports: [RoutedViewComponent],
+ providers: [
+ {
+ provide: ActivatedRoute,
+ useValue: mockActivatedRoute as unknown as ActivatedRoute,
+ },
+ {
+ provide: ComponentRegistry,
+ useValue: { get: () => async () => MockComponent },
+ },
+ ],
+ });
+ fixture = TestBed.createComponent(RoutedViewComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it("should take component from route data and use it for dynamic component directive", fakeAsync(() => {
+ mockActivatedRoute.data.next({ component: "TestComponent" });
+ tick();
+
+ expect(component.component).toEqual("TestComponent");
+ }));
+
+ it("should pass config route data on as config", fakeAsync(() => {
+ mockActivatedRoute.data.next({ config: { testDetail: "test" } });
+ tick();
+
+ expect(component.config).toEqual({ testDetail: "test" });
+ }));
+
+ it("should add route param '/:id' to config", fakeAsync(() => {
+ mockActivatedRoute.paramMap.next(mockParamMap({ id: "123" }));
+ tick();
+
+ expect(component.config.id).toEqual("123");
+ }));
+});
diff --git a/src/app/core/ui/routed-view/routed-view.component.ts b/src/app/core/ui/routed-view/routed-view.component.ts
new file mode 100644
index 0000000000..20b5ceb3e2
--- /dev/null
+++ b/src/app/core/ui/routed-view/routed-view.component.ts
@@ -0,0 +1,45 @@
+import { Component } from "@angular/core";
+import { CommonModule } from "@angular/common";
+import { RouteTarget } from "../../../app.routing";
+import { ActivatedRoute } from "@angular/router";
+import { DynamicComponentDirective } from "../../config/dynamic-components/dynamic-component.directive";
+import { ViewConfig } from "../../config/dynamic-routing/view-config.interface";
+
+/**
+ * Wrapper component for a primary, full page view
+ * that takes parameters from the route and passes these on to normal @Input properties.
+ *
+ * This allows to develop functional feature components in a way to easily reuse them for display
+ * as a full page view or in a modal dialog.
+ */
+@RouteTarget("RoutedView")
+@Component({
+ selector: "app-routed-view",
+ standalone: true,
+ imports: [CommonModule, DynamicComponentDirective],
+ template: ` `,
+})
+export class RoutedViewComponent {
+ component: string;
+ config: T;
+
+ constructor(route: ActivatedRoute) {
+ route.data.subscribe((data: { component: string } & ViewConfig) => {
+ this.component = data.component;
+ // pass all other config properties to the component as config
+ this.config = Object.assign({}, data.config);
+
+ // merge updated config properties from route params
+ route.paramMap.subscribe((params) => {
+ const config = this.config;
+ for (const key of params.keys) {
+ config[key] = params.get(key);
+ }
+ this.config = { ...config };
+ });
+ });
+ }
+}
diff --git a/src/app/core/ui/ui-config.ts b/src/app/core/ui/ui-config.ts
deleted file mode 100644
index 3ae7f1b1d3..0000000000
--- a/src/app/core/ui/ui-config.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * Interface for the general configuration of the application.
- * This is independent of the routes.
- */
-export interface UiConfig {
- /**
- * The path to a logo icon inside the `assets` folder.
- * This will be displayed on top of the navigation items.
- */
- logo_path?: string;
-
- /**
- * Toggle whether the language select component should be displayed.
- * This should only be used if configurations for multiple languages are available.
- */
- displayLanguageSelect?: boolean;
-
- /**
- * The default language of the application which is used after login if the user doesn't select something else.
- */
- default_language?: string;
-
- /**
- * The title which is shown at the top of the application.
- */
- site_name?: string;
-}
diff --git a/src/app/core/user/user.ts b/src/app/core/user/user.ts
index 3fba9038d6..4c390db113 100644
--- a/src/app/core/user/user.ts
+++ b/src/app/core/user/user.ts
@@ -32,6 +32,7 @@ export class User extends Entity {
static icon: IconName = "user";
static label = $localize`:label for entity:User`;
static labelPlural = $localize`:label (plural) for entity:Users`;
+ static override hasPII = true;
/** username used for login and identification */
@DatabaseField({
diff --git a/src/app/features/dashboard-widgets/birthday-dashboard-widget/birthday-dashboard/birthday-dashboard.component.spec.ts b/src/app/features/dashboard-widgets/birthday-dashboard-widget/birthday-dashboard/birthday-dashboard.component.spec.ts
index 388186b7a7..f058325831 100644
--- a/src/app/features/dashboard-widgets/birthday-dashboard-widget/birthday-dashboard/birthday-dashboard.component.spec.ts
+++ b/src/app/features/dashboard-widgets/birthday-dashboard-widget/birthday-dashboard/birthday-dashboard.component.spec.ts
@@ -11,7 +11,6 @@ import { Child } from "../../../../child-dev-project/children/model/child";
import moment from "moment";
import { ConfigService } from "../../../../core/config/config.service";
import { FontAwesomeTestingModule } from "@fortawesome/angular-fontawesome/testing";
-import { DateWithAge } from "../../../../child-dev-project/children/model/dateWithAge";
import { Entity } from "../../../../core/entity/model/entity";
import { DatabaseField } from "../../../../core/entity/database-field.decorator";
import {
@@ -19,6 +18,7 @@ import {
MockEntityMapperService,
} from "../../../../core/entity/entity-mapper/mock-entity-mapper-service";
import { DatabaseEntity } from "../../../../core/entity/database-entity.decorator";
+import { DateWithAge } from "../../../../core/basic-datatypes/date-with-age/dateWithAge";
describe("BirthdayDashboardComponent", () => {
let component: BirthdayDashboardComponent;
diff --git a/src/app/features/dashboard-widgets/birthday-dashboard-widget/birthday-dashboard/birthday-dashboard.stories.ts b/src/app/features/dashboard-widgets/birthday-dashboard-widget/birthday-dashboard/birthday-dashboard.stories.ts
index 44fb95f390..ecb3afdeed 100644
--- a/src/app/features/dashboard-widgets/birthday-dashboard-widget/birthday-dashboard/birthday-dashboard.stories.ts
+++ b/src/app/features/dashboard-widgets/birthday-dashboard-widget/birthday-dashboard/birthday-dashboard.stories.ts
@@ -3,8 +3,8 @@ import { BirthdayDashboardComponent } from "./birthday-dashboard.component";
import { StorybookBaseModule } from "../../../../utils/storybook-base.module";
import { Child } from "../../../../child-dev-project/children/model/child";
import moment from "moment";
-import { DateWithAge } from "../../../../child-dev-project/children/model/dateWithAge";
import { importProvidersFrom } from "@angular/core";
+import { DateWithAge } from "app/core/basic-datatypes/date-with-age/dateWithAge";
const child1 = Child.create("First Child");
child1.dateOfBirth = new DateWithAge(
diff --git a/src/app/features/dashboard-widgets/progress-dashboard-widget/progress-dashboard-widget.module.ts b/src/app/features/dashboard-widgets/progress-dashboard-widget/progress-dashboard-widget.module.ts
index c015dcc7b0..a05f2445e7 100644
--- a/src/app/features/dashboard-widgets/progress-dashboard-widget/progress-dashboard-widget.module.ts
+++ b/src/app/features/dashboard-widgets/progress-dashboard-widget/progress-dashboard-widget.module.ts
@@ -1,6 +1,6 @@
-import {NgModule} from "@angular/core";
-import {ComponentRegistry} from "../../../dynamic-components";
-import {ProgressDashboardConfig} from "./progress-dashboard/progress-dashboard-config";
+import { NgModule } from "@angular/core";
+import { ComponentRegistry } from "../../../dynamic-components";
+import { ProgressDashboardConfig } from "./progress-dashboard/progress-dashboard-config";
@NgModule({})
export class ProgressDashboardWidgetModule {
diff --git a/src/app/features/file/display-img/display-img.component.html b/src/app/features/file/display-img/display-img.component.html
index baee6d3910..2096edb1b3 100644
--- a/src/app/features/file/display-img/display-img.component.html
+++ b/src/app/features/file/display-img/display-img.component.html
@@ -1,3 +1,6 @@
-
-
-
\ No newline at end of file
+
+
+
diff --git a/src/app/features/file/edit-file/edit-file.component.ts b/src/app/features/file/edit-file/edit-file.component.ts
index 20ec726de9..7844374fc1 100644
--- a/src/app/features/file/edit-file/edit-file.component.ts
+++ b/src/app/features/file/edit-file/edit-file.component.ts
@@ -78,6 +78,7 @@ export class EditFileComponent extends EditComponent implements OnInit {
// directly reset input so subsequent selections with the same name also trigger the change event
this.fileUploadInput.nativeElement.value = "";
this.selectedFile = file;
+ this.formControl.markAsDirty();
this.formControl.setValue(file.name);
}
@@ -104,7 +105,7 @@ export class EditFileComponent extends EditComponent implements OnInit {
}
formClicked(isInputElement?: boolean) {
- if (this.formControl.disabled) {
+ if (this.initialValue && this.formControl.value === this.initialValue) {
this.showFile();
} else if (isInputElement) {
this.fileUploadInput.nativeElement.click();
@@ -118,6 +119,7 @@ export class EditFileComponent extends EditComponent implements OnInit {
}
delete() {
+ this.formControl.markAsDirty();
this.formControl.setValue(null);
this.selectedFile = undefined;
// remove is only necessary if an initial value was set
diff --git a/src/app/features/file/edit-photo/edit-photo.component.html b/src/app/features/file/edit-photo/edit-photo.component.html
index fd84cae2eb..d956f66411 100644
--- a/src/app/features/file/edit-photo/edit-photo.component.html
+++ b/src/app/features/file/edit-photo/edit-photo.component.html
@@ -13,8 +13,14 @@
>
-
+
{
+ // accessing the id of the entity property seems difficult here
+ // file anonymization requires the FileService to actively delete - not supporting partial anonymization for now
+ // --> see EntityRemoveService for full anonymization, removing files
+ throw new Error(
+ "'retain-anonymized' is not implemented for 'file' datatype",
+ );
+ }
}
diff --git a/src/app/features/historical-data/demo-historical-data-generator.ts b/src/app/features/historical-data/demo-historical-data-generator.ts
index 43d398bb97..38fb1341a9 100644
--- a/src/app/features/historical-data/demo-historical-data-generator.ts
+++ b/src/app/features/historical-data/demo-historical-data-generator.ts
@@ -3,9 +3,9 @@ import { HistoricalEntityData } from "./model/historical-entity-data";
import { Injectable } from "@angular/core";
import { DemoChildGenerator } from "../../child-dev-project/children/demo-data-generators/demo-child-generator.service";
import { faker } from "../../core/demo-data/faker";
-import { ENTITY_CONFIG_PREFIX } from "../../core/entity/model/entity";
import { DemoConfigGeneratorService } from "../../core/config/demo-config-generator.service";
import { ratingAnswers } from "./model/rating-answers";
+import { EntityConfigService } from "../../core/entity/entity-config.service";
export class DemoHistoricalDataConfig {
minCountAttributes: number;
@@ -35,7 +35,8 @@ export class DemoHistoricalDataGenerator extends DemoDataGenerator attr.name);
const entities: HistoricalEntityData[] = [];
for (const child of this.childrenGenerator.entities) {
diff --git a/src/app/features/historical-data/model/historical-entity-data.ts b/src/app/features/historical-data/model/historical-entity-data.ts
index 82f669510e..6ed0d39c83 100644
--- a/src/app/features/historical-data/model/historical-entity-data.ts
+++ b/src/app/features/historical-data/model/historical-entity-data.ts
@@ -2,6 +2,7 @@ import { Entity } from "../../../core/entity/model/entity";
import { DatabaseEntity } from "../../../core/entity/database-entity.decorator";
import { DatabaseField } from "../../../core/entity/database-field.decorator";
import { PLACEHOLDERS } from "../../../core/entity/schema/entity-schema-field";
+import { Child } from "../../../child-dev-project/children/model/child";
/**
* A general class that represents data that is collected for a entity over time.
@@ -9,10 +10,20 @@ import { PLACEHOLDERS } from "../../../core/entity/schema/entity-schema-field";
*/
@DatabaseEntity("HistoricalEntityData")
export class HistoricalEntityData extends Entity {
+ static override hasPII = true;
+
@DatabaseField({
label: $localize`:Label for date of historical data:Date`,
defaultValue: PLACEHOLDERS.NOW,
+ anonymize: "retain-anonymized",
})
date: Date;
- @DatabaseField() relatedEntity: string;
+
+ @DatabaseField({
+ dataType: "entity",
+ additional: Child.ENTITY_TYPE,
+ entityReferenceRole: "composite",
+ anonymize: "retain",
+ })
+ relatedEntity: string;
}
diff --git a/src/app/features/location/edit-location/edit-location.component.spec.ts b/src/app/features/location/edit-location/edit-location.component.spec.ts
index 0399e50ff2..06f8e245d1 100644
--- a/src/app/features/location/edit-location/edit-location.component.spec.ts
+++ b/src/app/features/location/edit-location/edit-location.component.spec.ts
@@ -111,7 +111,7 @@ describe("EditLocationComponent", () => {
await clearButton.click();
- expect(component.formControl.value).toBeNull();
+ expect(component.formControl.value).toBeUndefined();
await expectAsync(input.getValue()).toBeResolvedTo("");
});
diff --git a/src/app/features/location/edit-location/edit-location.component.ts b/src/app/features/location/edit-location/edit-location.component.ts
index 7a33627904..f8cb91307e 100644
--- a/src/app/features/location/edit-location/edit-location.component.ts
+++ b/src/app/features/location/edit-location/edit-location.component.ts
@@ -81,7 +81,8 @@ export class EditLocationComponent
);
}
- selectLocation(selected: GeoResult) {
+ selectLocation(selected?: GeoResult) {
+ this.formControl.markAsDirty();
this.formControl.setValue(selected);
this.filteredOptions.next([]);
}
@@ -92,7 +93,7 @@ export class EditLocationComponent
}
clearInput() {
- this.formControl.setValue(null);
+ this.selectLocation();
}
private getGeoLookupResult(searchTerm) {
@@ -122,7 +123,7 @@ export class EditLocationComponent
ref
.afterClosed()
.pipe(concatMap(() => this.lookupCoordinates(marked.value[0])))
- .subscribe((res) => this.formControl.setValue(res));
+ .subscribe((res) => this.selectLocation(res));
}
}
diff --git a/src/app/features/markdown-page/markdown-page/markdown-page.component.ts b/src/app/features/markdown-page/markdown-page/markdown-page.component.ts
index 0e37e69ea0..aeba29b681 100644
--- a/src/app/features/markdown-page/markdown-page/markdown-page.component.ts
+++ b/src/app/features/markdown-page/markdown-page/markdown-page.component.ts
@@ -15,10 +15,7 @@
* along with ndb-core. If not, see .
*/
-import { Component, Input, OnInit } from "@angular/core";
-import { ActivatedRoute } from "@angular/router";
-import { MarkdownPageConfig } from "../MarkdownPageConfig";
-import { RouteData } from "../../../core/config/dynamic-routing/view-config.interface";
+import { Component, Input } from "@angular/core";
import { RouteTarget } from "../../../app.routing";
import { MarkdownPageModule } from "../markdown-page.module";
@@ -32,16 +29,7 @@ import { MarkdownPageModule } from "../markdown-page.module";
imports: [MarkdownPageModule],
standalone: true,
})
-export class MarkdownPageComponent implements OnInit {
+export class MarkdownPageComponent {
/** filepath to be loaded as markdown */
@Input() markdownFile: string;
-
- constructor(private route: ActivatedRoute) {}
-
- ngOnInit() {
- this.route.data.subscribe(
- (data: RouteData) =>
- (this.markdownFile = data.config.markdownFile),
- );
- }
}
diff --git a/src/app/features/reporting/reporting/reporting.component.html b/src/app/features/reporting/reporting/reporting.component.html
index c9252b01fb..291c0d1941 100644
--- a/src/app/features/reporting/reporting/reporting.component.html
+++ b/src/app/features/reporting/reporting/reporting.component.html
@@ -9,7 +9,7 @@
) => {
- this.availableReports = data.config?.reports;
- },
- );
- }
-
async calculateResults(
selectedReport: ReportConfig,
fromDate: Date,
diff --git a/src/app/features/reporting/reporting/select-report/select-report.component.html b/src/app/features/reporting/reporting/select-report/select-report.component.html
index fa2f4f8dbd..d086d2ec20 100644
--- a/src/app/features/reporting/reporting/select-report/select-report.component.html
+++ b/src/app/features/reporting/reporting/select-report/select-report.component.html
@@ -46,6 +46,7 @@
Calculate
+
): Todo {
const instance = new Todo();
@@ -46,6 +47,7 @@ export class Todo extends Entity {
dataType: "date-only",
label: $localize`:Label:Deadline`,
showInDetailsView: true,
+ anonymize: "retain",
})
deadline: Date;
@@ -54,6 +56,7 @@ export class Todo extends Entity {
label: $localize`:Label:Start date`,
description: $localize`:Description:When you are planning to start work so that you keep enough time before the actual hard deadline.`,
showInDetailsView: true,
+ anonymize: "retain",
})
startDate: Date;
@@ -70,6 +73,7 @@ export class Todo extends Entity {
additional: User.ENTITY_TYPE,
showInDetailsView: true,
defaultValue: PLACEHOLDERS.CURRENT_USER,
+ anonymize: "retain",
})
assignedTo: string[] = [];
@@ -86,7 +90,9 @@ export class Todo extends Entity {
School.ENTITY_TYPE,
RecurringActivity.ENTITY_TYPE,
],
+ entityReferenceRole: "composite",
showInDetailsView: true,
+ anonymize: "retain",
})
relatedEntities: string[] = [];
@@ -103,16 +109,23 @@ export class Todo extends Entity {
},
] as { label: string; interval: TimeInterval }[],
showInDetailsView: true,
+ anonymize: "retain",
})
repetitionInterval: TimeInterval;
@DatabaseField({
label: $localize`:label for Todo entity property:completed`,
viewComponent: "DisplayTodoCompletion",
+ anonymize: "retain",
})
completed?: TodoCompletion;
get isActive(): boolean {
+ if (this.inactive) {
+ // manual archiving of records takes precendence
+ return false;
+ }
+
return !this.completed;
}
diff --git a/src/app/features/todos/todo-list/todo-list.component.ts b/src/app/features/todos/todo-list/todo-list.component.ts
index 04ad795466..06893502b3 100644
--- a/src/app/features/todos/todo-list/todo-list.component.ts
+++ b/src/app/features/todos/todo-list/todo-list.component.ts
@@ -25,6 +25,7 @@ import { FilterSelectionOption } from "../../../core/filter/filters/filters";
clickMode="none"
(elementClick)="showDetails($event)"
(addNewClick)="createNew()"
+ [showInactive]="true"
>
`,
standalone: true,
@@ -45,6 +46,7 @@ export class TodoListComponent implements OnInit {
ngOnInit() {
this.route.data.subscribe((data: RouteData) =>
+ // TODO replace this use of route and rely on the RoutedViewComponent instead
this.init(data.config),
);
}
diff --git a/src/app/features/todos/todos-related-to-entity/todos-related-to-entity.component.html b/src/app/features/todos/todos-related-to-entity/todos-related-to-entity.component.html
index d170afed77..7f11ce30ab 100644
--- a/src/app/features/todos/todos-related-to-entity/todos-related-to-entity.component.html
+++ b/src/app/features/todos/todos-related-to-entity/todos-related-to-entity.component.html
@@ -8,13 +8,3 @@
(rowClick)="showDetails($event)"
[getBackgroundColor]="backgroundColorFn"
>
-
-
-
- Also show completed
-
-
diff --git a/src/app/features/todos/todos-related-to-entity/todos-related-to-entity.component.ts b/src/app/features/todos/todos-related-to-entity/todos-related-to-entity.component.ts
index c20712ee65..b8f69d9846 100644
--- a/src/app/features/todos/todos-related-to-entity/todos-related-to-entity.component.ts
+++ b/src/app/features/todos/todos-related-to-entity/todos-related-to-entity.component.ts
@@ -66,7 +66,6 @@ export class TodosRelatedToEntityComponent implements OnInit {
async ngOnInit() {
this.entries = await this.loadDataFor(this.entity.getId(true));
- this.toggleInactive();
}
private async loadDataFor(entityId: string): Promise {
@@ -97,13 +96,4 @@ export class TodosRelatedToEntityComponent implements OnInit {
showDetails(entity: Todo) {
this.formDialog.openFormPopup(entity, this.columns, TodoDetailsComponent);
}
-
- toggleInactive() {
- // TODO: move the toggle into its own component to be used like a filter? this is almost copy & paste from ChildSchoolOverview
- if (this.includeInactive) {
- this.filter = {};
- } else {
- this.filter = { isActive: true };
- }
- }
}
diff --git a/src/app/utils/core-testing.module.ts b/src/app/utils/core-testing.module.ts
new file mode 100644
index 0000000000..647ddaaa4f
--- /dev/null
+++ b/src/app/utils/core-testing.module.ts
@@ -0,0 +1,37 @@
+import { NgModule } from "@angular/core";
+import { CoreModule } from "../core/core.module";
+import {
+ entityRegistry,
+ EntityRegistry,
+} from "../core/entity/database-entity.decorator";
+import { EntityMapperService } from "../core/entity/entity-mapper/entity-mapper.service";
+import { mockEntityMapper } from "../core/entity/entity-mapper/mock-entity-mapper-service";
+import { ConfigurableEnumService } from "../core/basic-datatypes/configurable-enum/configurable-enum.service";
+import { ComponentRegistry } from "../dynamic-components";
+import { EntityActionsService } from "../core/entity/entity-actions/entity-actions.service";
+
+/**
+ * A basic module that can be imported in unit tests to provide default datatypes.
+ * In contrast to MockedTestingModule this imports a much more limited set of modules.
+ */
+@NgModule({
+ imports: [CoreModule],
+ providers: [
+ { provide: EntityRegistry, useValue: entityRegistry },
+ { provide: EntityMapperService, useValue: mockEntityMapper() },
+ {
+ provide: ConfigurableEnumService,
+ useValue: new ConfigurableEnumService(mockEntityMapper(), null),
+ },
+ {
+ provide: EntityActionsService,
+ useValue: jasmine.createSpyObj(["anonymize"]),
+ },
+ ComponentRegistry,
+ ],
+})
+export class CoreTestingModule {
+ constructor(components: ComponentRegistry) {
+ components.allowDuplicates();
+ }
+}
diff --git a/src/app/utils/expect-entity-data.spec.ts b/src/app/utils/expect-entity-data.spec.ts
index 515628a172..0faed45e0e 100644
--- a/src/app/utils/expect-entity-data.spec.ts
+++ b/src/app/utils/expect-entity-data.spec.ts
@@ -152,7 +152,10 @@ function printArrayDifferences(name: string, a1: Array, a2: Array) {
* @param obj The object or array of objects to simplify
* @param withoutId (Optional) set to true to remove _id as well
*/
-function comparableEntityData(obj: any | any[], withoutId: boolean = false) {
+export function comparableEntityData(
+ obj: any | any[],
+ withoutId: boolean = false,
+) {
if (Array.isArray(obj)) {
return obj.map((o) => comparableEntityData(o, withoutId));
} else {
diff --git a/src/assets/locale/messages.de.xlf b/src/assets/locale/messages.de.xlf
index 50827d2e70..4870e0ee75 100644
--- a/src/assets/locale/messages.de.xlf
+++ b/src/assets/locale/messages.de.xlf
@@ -58,7 +58,7 @@
Speichern
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 54
+ 45
@@ -67,7 +67,7 @@
Discard changes made to a form
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 63
+ 54
@@ -76,7 +76,7 @@
One of the stages while recording child-attendances
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 72
+ 63
@@ -88,6 +88,14 @@
214
+
+ Excluded some archived participants. Click to include.
+ Archivierte Teilnehmende ausgeblendet. Klicken um diese einzubeziehen.
+
+ src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
+ 58
+
+
Attendance completed.
Anwesenheits-Aufzeichnung beendet.
@@ -96,7 +104,7 @@
Attendance completed
src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
- 107
+ 120
@@ -105,7 +113,7 @@
Open details of recorded event for review
src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
- 117
+ 130
@@ -114,7 +122,23 @@
Back to overview button after finishing a roll call
src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
- 127
+ 140
+
+
+
+ Also include archived participants?
+ Archivierte Teilnehmende mit berücksichtigen?
+
+ src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.ts
+ 271
+
+
+
+ This event has some participants who are "archived". We automatically remove them from the attendance list for you. Do you want to also include archived participants for this event?
+ Dieses Event hat Teilnehmende, die "archiviert" wurden. Wir haben diese von der Teilname-Liste entfernt. Wollen Sie die archivierten Teilnehmenden für dieses Event ebenfalls berücksichtigen?
+
+ src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.ts
+ 272
@@ -462,7 +486,7 @@
src/app/features/todos/model/todo.ts
- 61
+ 64
@@ -615,7 +639,7 @@
Label for height in cm of a health check
src/app/child-dev-project/children/health-checkup/model/health-check.ts
- 39
+ 52
@@ -624,7 +648,7 @@
Label for weight in kg of a health check
src/app/child-dev-project/children/health-checkup/model/health-check.ts
- 47
+ 60
@@ -1122,7 +1146,7 @@
Label for the children of a note
src/app/child-dev-project/notes/model/note.ts
- 76
+ 77
src/app/core/config/config-fix.ts
@@ -1130,11 +1154,7 @@
src/app/core/config/config-fix.ts
- 563
-
-
- src/app/core/config/config-fix.ts
- 960
+ 946
@@ -1143,11 +1163,11 @@
Label for the subject of a note
src/app/child-dev-project/notes/model/note.ts
- 97
+ 106
src/app/features/todos/model/todo.ts
- 42
+ 43
@@ -1168,7 +1188,7 @@
Download note details as CSV
src/app/child-dev-project/notes/note-details/note-details.component.html
- 90
+ 94
@@ -1197,7 +1217,7 @@
Filter-option for notes
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 66
+ 65
@@ -1206,7 +1226,7 @@
Filter-option for notes
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 71
+ 70
src/app/child-dev-project/warning-level.ts
@@ -1219,7 +1239,7 @@
Filter-option for notes
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 82
+ 81
@@ -1228,36 +1248,7 @@
Filter-option for notes
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 87
-
-
-
- Show entries where the end date is in the past
- Zeige Einträge, dessen End-Datum in der Vergangenheit liegt
- Tooltip that will appear when hovered over the
- show-ended button
- Show ended tooltip
-
- src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
- 32
-
-
- src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
- 32
-
-
-
- Include inactive past records
- Inaktive, vergangene Einträge anzeigen
- also show entries that are inactive
- slider
-
- src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
- 34
-
-
- src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
- 34
+ 86
@@ -1380,7 +1371,7 @@
src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
- 18
+ 24
src/app/features/dashboard-widgets/progress-dashboard-widget/edit-progress-dashboard/edit-progress-dashboard.component.html
@@ -1411,27 +1402,10 @@
86
-
- Select matching property
- Wähle zugeordnetes Feld von " "
- Label for property selection
-
- src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
- 2
-
-
Select which property of the target entity is matching with the values of this column. E.g. if your column contains names of children then select 'Name'.
Wählen Sie welches Feld des Ziel-Datentyps mit den Werten der Spalte der importierten Werte abgeglichen werden soll. z.B. wenn Ihre importierte Spalte die Telefonnummern als Identifikator für Schüler:innen enthält, wählen Sie "Telefonnummer"
import - value mapping (entity) - help text
-
- src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
- 9
-
-
-
- Save & Close
- Speichern & Schließen
src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
15
@@ -1619,7 +1593,7 @@
Label for the currently active status
src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
- 105
+ 97
@@ -1628,7 +1602,7 @@
Tooltip for the status of currently active or not
src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
- 108
+ 100
@@ -1637,7 +1611,7 @@
Indication for the currently active status of an entry
src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
- 111
+ 103
@@ -1646,7 +1620,7 @@
Indication for the currently inactive status of an entry
src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
- 112
+ 104
@@ -1812,7 +1786,7 @@
src/app/features/file/edit-photo/edit-photo.component.html
- 17
+ 22
@@ -1821,7 +1795,7 @@
Message for user
src/app/features/file/edit-file/edit-file.component.ts
- 132
+ 134
@@ -1904,6 +1878,10 @@
src/app/core/basic-datatypes/discrete/discrete-import-config/discrete-import-config.component.html
32
+
+ src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
+ 21
+
not at all
@@ -2043,7 +2021,7 @@
help text in map popup
src/app/features/location/edit-location/edit-location.component.ts
- 118
+ 119
@@ -2195,7 +2173,7 @@
src/app/core/config/config-fix.ts
- 661
+ 645
@@ -2375,19 +2353,19 @@
src/app/core/config/config-fix.ts
- 495
+ 481
src/app/core/config/config-fix.ts
- 549
+ 535
Attachment
Anhang
- src/app/core/config/config-fix.ts
- 269
+ src/app/child-dev-project/notes/model/note.ts
+ 134
@@ -2395,7 +2373,7 @@
App-Einstellungen
src/app/core/config/config-fix.ts
- 281
+ 267
@@ -2404,7 +2382,7 @@
Panel title
src/app/core/config/config-fix.ts
- 328
+ 314
@@ -2413,7 +2391,7 @@
Panel title
src/app/core/config/config-fix.ts
- 347
+ 333
@@ -2422,7 +2400,7 @@
Filename of markdown help page (make sure the filename you enter as a translation actually exists on the server!)
src/app/core/config/config-fix.ts
- 361
+ 347
@@ -2431,15 +2409,15 @@
Panel title
src/app/core/config/config-fix.ts
- 393
+ 379
src/app/core/config/config-fix.ts
- 585
+ 569
src/app/core/config/config-fix.ts
- 798
+ 771
@@ -2448,7 +2426,7 @@
Panel title
src/app/core/config/config-fix.ts
- 421
+ 407
@@ -2457,7 +2435,7 @@
Panel title
src/app/core/config/config-fix.ts
- 430
+ 416
@@ -2466,7 +2444,7 @@
Column label for age of child
src/app/core/config/config-fix.ts
- 452
+ 438
@@ -2475,7 +2453,7 @@
Column label for school attendance of child
src/app/core/config/config-fix.ts
- 470
+ 456
@@ -2484,7 +2462,7 @@
Column label for coaching attendance of child
src/app/core/config/config-fix.ts
- 479
+ 465
@@ -2493,11 +2471,11 @@
Translated name of default column group
src/app/core/config/config-fix.ts
- 494
+ 480
src/app/core/config/config-fix.ts
- 498
+ 484
@@ -2506,7 +2484,7 @@
Column group name
src/app/core/config/config-fix.ts
- 511
+ 497
@@ -2515,41 +2493,11 @@
Column group name
src/app/core/config/config-fix.ts
- 534
-
-
- src/app/core/config/config-fix.ts
- 683
-
-
-
- Active
- Aktiv
- Active children filter label - true case
-
- src/app/core/config/config-fix.ts
- 564
+ 520
src/app/core/config/config-fix.ts
- 780
-
-
-
- Inactive
- Inaktiv
- Active children filter label - false case
-
- src/app/core/config/config-fix.ts
- 565
-
-
- src/app/core/config/config-fix.ts
- 781
-
-
- src/app/core/entity/model/entity.ts
- 194
+ 667
@@ -2558,7 +2506,7 @@
Header for form section
src/app/core/config/config-fix.ts
- 613
+ 597
@@ -2567,7 +2515,7 @@
Header for form section
src/app/core/config/config-fix.ts
- 614
+ 598
@@ -2576,7 +2524,7 @@
Header for form section
src/app/core/config/config-fix.ts
- 615
+ 599
@@ -2585,7 +2533,7 @@
Panel title
src/app/core/config/config-fix.ts
- 622
+ 606
@@ -2594,7 +2542,7 @@
Title inside a panel
src/app/core/config/config-fix.ts
- 625
+ 609
@@ -2603,7 +2551,7 @@
Title inside a panel
src/app/core/config/config-fix.ts
- 645
+ 629
@@ -2612,7 +2560,7 @@
Child details section title
src/app/core/config/config-fix.ts
- 649
+ 633
@@ -2621,7 +2569,7 @@
Panel title
src/app/core/config/config-fix.ts
- 670
+ 654
@@ -2630,7 +2578,7 @@
description section
src/app/core/config/config-fix.ts
- 692
+ 676
@@ -2639,7 +2587,7 @@
Title inside a panel
src/app/core/config/config-fix.ts
- 699
+ 683
@@ -2648,7 +2596,7 @@
Panel title
src/app/core/config/config-fix.ts
- 705
+ 689
@@ -2657,7 +2605,7 @@
Panel title
src/app/core/config/config-fix.ts
- 730
+ 714
@@ -2675,7 +2623,7 @@
Panel title
src/app/core/config/config-fix.ts
- 828
+ 801
@@ -2684,7 +2632,7 @@
Name of a report
src/app/core/config/config-fix.ts
- 843
+ 816
@@ -2693,7 +2641,7 @@
Label of report query
src/app/core/config/config-fix.ts
- 847
+ 820
@@ -2702,7 +2650,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 852
+ 825
@@ -2711,7 +2659,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 855
+ 828
@@ -2720,7 +2668,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 859
+ 832
@@ -2729,7 +2677,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 864
+ 837
@@ -2738,7 +2686,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 868
+ 841
@@ -2747,7 +2695,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 873
+ 846
@@ -2756,7 +2704,7 @@
Name of a report
src/app/core/config/config-fix.ts
- 881
+ 854
@@ -2765,7 +2713,7 @@
Name of a report
src/app/core/config/config-fix.ts
- 898
+ 871
@@ -2884,7 +2832,7 @@
src/app/core/config/config-fix.ts
- 747
+ 731
@@ -2893,11 +2841,11 @@
Label for the phone number of a child
src/app/child-dev-project/children/model/child.ts
- 118
+ 126
src/app/core/config/config-fix.ts
- 1041
+ 1027
@@ -2946,7 +2894,7 @@
One of the stages while recording child-attendances
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 73
+ 64
@@ -2955,7 +2903,7 @@
Exit from the current screen
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 94
+ 80
@@ -2963,7 +2911,7 @@
Wollen Sie die Änderungen speichern?
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 95
+ 81
@@ -3015,7 +2963,7 @@
src/app/child-dev-project/notes/model/note.ts
- 100
+ 110
src/app/core/config/config-fix.ts
@@ -3028,7 +2976,7 @@
Label for the social worker(s) who created the note
src/app/child-dev-project/notes/model/note.ts
- 106
+ 117
@@ -3037,7 +2985,7 @@
Label for the category of a note
src/app/child-dev-project/notes/model/note.ts
- 114
+ 126
@@ -3046,11 +2994,11 @@
label for the related Entities
src/app/child-dev-project/notes/model/note.ts
- 132
+ 154
src/app/features/todos/model/todo.ts
- 83
+ 87
@@ -3059,7 +3007,7 @@
Label for date of the ASER results
src/app/child-dev-project/children/aser/model/aser.ts
- 30
+ 39
src/app/child-dev-project/children/educational-material/model/educational-material.ts
@@ -3067,15 +3015,15 @@
src/app/child-dev-project/children/health-checkup/model/health-check.ts
- 34
+ 45
src/app/child-dev-project/notes/model/note.ts
- 92
+ 99
src/app/features/historical-data/model/historical-entity-data.ts
- 13
+ 16
@@ -3084,7 +3032,7 @@
Label of the Math ASER result
src/app/child-dev-project/children/aser/model/aser.ts
- 53
+ 64
@@ -3093,7 +3041,7 @@
Label of the English ASER result
src/app/child-dev-project/children/aser/model/aser.ts
- 47
+ 58
src/app/child-dev-project/schools/demo-school-generator.service.ts
@@ -3106,7 +3054,7 @@
Label of the Hindi ASER result
src/app/child-dev-project/children/aser/model/aser.ts
- 35
+ 46
src/app/child-dev-project/schools/demo-school-generator.service.ts
@@ -3119,7 +3067,7 @@
Label of the Bengali ASER result
src/app/child-dev-project/children/aser/model/aser.ts
- 41
+ 52
src/app/child-dev-project/schools/demo-school-generator.service.ts
@@ -3132,7 +3080,7 @@
Label for the name of a child
src/app/child-dev-project/children/model/child.ts
- 46
+ 47
src/app/child-dev-project/schools/model/school.ts
@@ -3140,15 +3088,15 @@
src/app/core/config/config-fix.ts
- 447
+ 433
src/app/core/config/config-fix.ts
- 909
+ 882
src/app/core/config/config-fix.ts
- 1013
+ 999
@@ -3157,7 +3105,7 @@
Label for the project number of a child
src/app/child-dev-project/children/model/child.ts
- 54
+ 55
@@ -3165,19 +3113,11 @@
Alle
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 76
+ 75
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 90
-
-
- src/app/core/config/config-fix.ts
- 566
-
-
- src/app/core/config/config-fix.ts
- 782
+ 89
src/app/core/filter/filters/filters.ts
@@ -3276,11 +3216,11 @@
Label for the remarks of a ASER result
src/app/child-dev-project/children/aser/model/aser.ts
- 59
+ 71
src/app/core/config/config-fix.ts
- 1055
+ 1041
@@ -3384,7 +3324,7 @@
Short label for the project number
src/app/child-dev-project/children/model/child.ts
- 55
+ 56
@@ -3393,7 +3333,7 @@
Label for the date of birth of a child
src/app/child-dev-project/children/model/child.ts
- 61
+ 63
@@ -3402,7 +3342,7 @@
Short label for the date of birth
src/app/child-dev-project/children/model/child.ts
- 62
+ 64
@@ -3411,7 +3351,7 @@
Label for the gender of a child
src/app/child-dev-project/children/model/child.ts
- 68
+ 71
@@ -3540,11 +3480,11 @@
Label for the class of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 32
+ 38
src/app/core/config/config-fix.ts
- 458
+ 444
@@ -3553,7 +3493,7 @@
Label for the start date of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 37
+ 43
src/app/core/entity-details/related-time-period-entities/time-period.ts
@@ -3561,7 +3501,7 @@
src/app/features/todos/model/todo.ts
- 54
+ 56
@@ -3570,7 +3510,7 @@
Description of the start date of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 38
+ 44
@@ -3579,7 +3519,7 @@
Label for the end date of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 44
+ 51
src/app/core/entity-details/related-time-period-entities/time-period.ts
@@ -3592,7 +3532,7 @@
Description of the end date of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 45
+ 52
@@ -3601,7 +3541,7 @@
Label for the percentage result of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 51
+ 59
@@ -3610,7 +3550,7 @@
Error assertValid failed
src/app/core/entity-details/related-time-period-entities/time-period.ts
- 63
+ 68
@@ -3619,7 +3559,7 @@
Error assertValid failed
src/app/core/entity-details/related-time-period-entities/time-period.ts
- 67
+ 72
@@ -3682,7 +3622,7 @@
Label for the school of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 23
+ 27
src/app/child-dev-project/schools/demo-school-generator.service.ts
@@ -3694,11 +3634,11 @@
src/app/core/config/config-fix.ts
- 463
+ 449
src/app/core/config/config-fix.ts
- 574
+ 551
@@ -3822,11 +3762,11 @@
src/app/core/config/config-fix.ts
- 813
+ 786
src/app/core/config/config-fix.ts
- 891
+ 864
@@ -3839,7 +3779,7 @@
src/app/child-dev-project/notes/model/note.ts
- 144
+ 167
@@ -3902,7 +3842,7 @@
Label for the center of a child
src/app/child-dev-project/children/model/child.ts
- 76
+ 80
@@ -3911,7 +3851,7 @@
Label for the admission date of a child
src/app/child-dev-project/children/model/child.ts
- 81
+ 86
@@ -3920,11 +3860,11 @@
Label for the status of a child
src/app/child-dev-project/children/model/child.ts
- 86
+ 92
src/app/child-dev-project/notes/model/note.ts
- 151
+ 176
src/app/core/config/config-fix.ts
@@ -3932,11 +3872,7 @@
src/app/core/config/config-fix.ts
- 524
-
-
- src/app/core/config/config-fix.ts
- 779
+ 510
@@ -3945,7 +3881,7 @@
Label for the dropout date of a child
src/app/child-dev-project/children/model/child.ts
- 91
+ 97
@@ -3954,7 +3890,7 @@
Label for the type of dropout of a child
src/app/child-dev-project/children/model/child.ts
- 96
+ 103
@@ -3963,17 +3899,17 @@
Label for the remarks about a dropout of a child
src/app/child-dev-project/children/model/child.ts
- 101
+ 109
Photo
Foto
+ Label for the file field of a photo of a child
src/app/child-dev-project/children/model/child.ts
- 112
+ 120
- Label for the file field of a photo of a child
Child
@@ -3981,11 +3917,11 @@
Label for the child of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 13
+ 15
src/app/core/config/config-fix.ts
- 959
+ 945
@@ -3998,7 +3934,7 @@
src/app/core/config/config-fix.ts
- 488
+ 474
@@ -4020,7 +3956,7 @@
src/app/core/config/config-fix.ts
- 886
+ 859
@@ -4233,11 +4169,11 @@
Label for the address of a child
src/app/core/config/config-fix.ts
- 966
+ 952
src/app/core/config/config-fix.ts
- 1034
+ 1020
@@ -4246,7 +4182,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 973
+ 959
@@ -4255,7 +4191,7 @@
Label for the religion of a child
src/app/core/config/config-fix.ts
- 980
+ 966
@@ -4264,7 +4200,7 @@
Label for the mother tongue of a child
src/app/core/config/config-fix.ts
- 987
+ 973
@@ -4273,7 +4209,7 @@
Tooltip description for the mother tongue of a child
src/app/core/config/config-fix.ts
- 988
+ 974
@@ -4282,7 +4218,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 995
+ 981
@@ -4291,7 +4227,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1002
+ 988
@@ -4299,11 +4235,11 @@
Privatschule
src/app/core/config/config-fix.ts
- 382
+ 368
src/app/core/config/config-fix.ts
- 1020
+ 1006
@@ -4312,7 +4248,7 @@
Label for the language of a school
src/app/core/config/config-fix.ts
- 1027
+ 1013
@@ -4321,7 +4257,7 @@
Label for the timing of a school
src/app/core/config/config-fix.ts
- 1048
+ 1034
@@ -4330,7 +4266,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1067
+ 1053
@@ -4339,7 +4275,7 @@
Description for a child attribute
src/app/core/config/config-fix.ts
- 1068
+ 1054
@@ -4348,7 +4284,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1076
+ 1062
@@ -4357,7 +4293,7 @@
Description for a child attribute
src/app/core/config/config-fix.ts
- 1077
+ 1063
@@ -4366,7 +4302,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1085
+ 1071
@@ -4375,7 +4311,7 @@
Description for a child attribute
src/app/core/config/config-fix.ts
- 1086
+ 1072
@@ -4384,7 +4320,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1094
+ 1080
@@ -4393,7 +4329,7 @@
Description for a child attribute
src/app/core/config/config-fix.ts
- 1095
+ 1081
@@ -4402,7 +4338,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1103
+ 1089
@@ -4411,7 +4347,7 @@
Description for a child attribute
src/app/core/config/config-fix.ts
- 1104
+ 1090
@@ -4420,7 +4356,7 @@
Label of user phone
src/app/core/config/config-fix.ts
- 1115
+ 1101
@@ -4462,13 +4398,21 @@
1
+
+ Add new option
+ Neue Option hinzufügen
+
+ src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.html
+ 32
+
+
Close
Schließen
Close popup
src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.html
- 29
+ 46
src/app/core/filter/filter-overlay/filter-overlay.component.html
@@ -4481,7 +4425,7 @@
Name of a column of a report
src/app/core/config/config-fix.ts
- 913
+ 899
@@ -4490,7 +4434,7 @@
Name of a column of a report
src/app/core/config/config-fix.ts
- 917
+ 903
@@ -4499,7 +4443,7 @@
Name of a column of a report
src/app/core/config/config-fix.ts
- 921
+ 907
@@ -4508,7 +4452,7 @@
Name of a column of a report
src/app/core/config/config-fix.ts
- 925
+ 911
@@ -4517,7 +4461,7 @@
Name of a report
src/app/core/config/config-fix.ts
- 935
+ 921
@@ -4528,6 +4472,92 @@
28
+
+ Archive
+ Archivieren
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 69
+
+ entity context menu
+
+
+ Mark the record as inactive, hiding it from lists by default while keeping the data.
+ Datensatz als "inaktiv" markieren, um diesen für Listen standardmäßig auszublenden. Die Daten bleiben dabei aber erhalten.
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 70
+
+ entity context menu tooltip
+
+
+ Anonymize
+ Anonymisieren
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 77
+
+ entity context menu
+
+
+ Remove all personal data and keep an archived basic record for statistical reporting.
+ Alle persönlichen Daten entfernen und nur einen archivierten Basis-Datensatz für statistische Auswertungen behalten.
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 78
+
+ entity context menu tooltip
+
+
+ Delete
+ Löschen
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 85
+
+ entity context menu
+
+
+ Remove the record completely from the database.
+ Datensatz vollständig aus der Datenbank entfernen.
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 86
+
+ entity context menu tooltip
+
+
+ Archived
+ Archiviert
+
+ src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
+ 6
+
+
+
+ Anonymized & Archived
+ Anonymisiert & Archiviert
+
+ src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
+ 8
+
+
+
+ This record has been anonymized. Details containing personal information have been deleted and cannot be restored. For statistical reporting, this basic record has been kept.
+ Dieser Datensatz wurde anonymisiert. Details, die persönliche Daten enthalten, wurden gelöscht und können nicht wiederhergestellt werden. Für statistische Auswertungen wurde dieser Basis-Datensatz erhalten.
+
+ src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
+ 13,17
+
+
+
+ This record is archived and will be be hidden from lists and select options by default.
+ Dieser Datensatz ist archiviert und wird standardmäßig von Listen und Auswahloptionen ausgeblendet.
+
+ src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
+ 19,22
+
+
Adding new
Neuer Eintrag
@@ -4538,26 +4568,13 @@
27
-
- Delete
- Löschen
- Generic delete button
-
- src/app/core/entity-details/entity-details/entity-details.component.html
- 58
-
-
- src/app/core/form-dialog/dialog-buttons/dialog-buttons.component.html
- 61
-
-
Save the new record to create it before accessing other details
Speichere den neuen Eintrag bevor weitere Details angezeigt werden können
Tooltip explaining disabled sections when creating new entity
src/app/core/entity-details/entity-details/entity-details.component.html
- 74
+ 51
@@ -4696,48 +4713,170 @@
Löschen?
Delete confirmation title
- src/app/core/entity/entity-remove.service.ts
- 78
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 76
-
- Are you sure you want to delete this record?
- Sind Sie sicher, dass Sie diesen -Datensatz löschen wollen?
+
+
+ This will remove the data permanently as if it never existed. This cannot be undone. Statistical reports (also for past time periods) will change and not include this record anymore.
+
+ If you have not just created this record accidentally, deleting this is probably not what you want to do. If the record represents something that actually happened in your work, consider to use "anonymize" or just "archive" instead, so that you will not lose your documentation for reports.
+
+ Are you sure you want to delete this record?
+
+ Der Datensatz werden dauerhaft gelöscht, als ob dieser nie existiert hätte. Dieser kann nicht wiederhergestellt werden. Statistische Auswertungen (auch für vergangene Zeiträume) werden sich ändern und diesen Datensatz nicht mehr berücksichtigen.
+
+ Wenn Sie diesen Datensatz nicht nur versehentlich erstellt hatten, wollen Sie diesen vermutlich nicht löschen. Wenn der Datensatz etwas repräsentiert, das tatsächlich in Ihrer Arbeit passiert ist, können Sie den Datensatz stattdessen auch "anonymisieren" oder einfach "archivieren", damit Ihre Dokumentation für Berichte nicht verloren geht.
+
+ Sind Sie sicher, dass Sie diesen Datensatz löschen wollen?
+ Delete confirmation dialog
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 77
+
+
+
+ Processing ...
+ Wird bearbeitet ...
- src/app/core/entity/entity-remove.service.ts
- 81
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 89
- Delete confirmation text
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 145
+
+ Entity action progress dialog
-
- Deleted Entity
- gelöscht
- Deleted Entity information
+
+ Related records may still contain personal data
+ Verknüpfte Einträge können noch persönliche Daten enthalten
- src/app/core/entity/entity-remove.service.ts
- 93
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 96
+
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 152
+
+ post-delete related PII warning title
+
+
+ Some related records (e.g. notes) may still contain personal data in their text. We have automatically deleted all records that are linked to ONLY this .
+ However, there are some records that are linked to multiple records. We have not deleted these, so that you will not lose relevant data. Please review them manually to ensure all sensitive information is removed, if required (e.g. by looking through the linked notes and editing a note's text).
+ Einige verknüpfte Einträge können noch persönliche Daten enthalten (z.B. Notizen in ihrem Text). Wir haben automatisch alle Datensätze gelöscht, die NUR mit diesem -Datensatz verknüpft waren.
+ Es existieren allerdings einige Datensätze, die mit mehreren Einträgen verknüpft sind. Wir haben diese nicht gelöscht, damit Sie keine relevanten Daten verlieren. Bitte überprüfen Sie diese selbst, um sicherzustellen, dass alle sensiblen Informationen entfern wurden, falls dies notwendig ist (z.B. indem Sie verknüpfte Notizen durchgehen und Notiz-Texte wenn nötig bearbeiten).
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 97,100
+
+ post-delete related PII warning dialog
+
+
+ Deleted
+ gelöscht
+ Entity action confirmation message verb
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 114
+
+
+
+ Anonymize?
+ Anonymisieren?
+ Anonymize confirmation dialog
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 132
+
+
+
+
+ This will remove all personal information (PII) permanently and keep only a basic record for statistical reports. Details that are removed during anonymization cannot be recovered.
+
+ If this has only become inactive and you want to keep all details about the record, consider to use "archive" instead.
+
+ Are you sure you want to anonymize this record?
+
+ Alle persönlichen Informationen werden dauerhaft entfernt und nur ein Basis-Datensatz für statistische Auswertungen bleibt erhalten. Details, die während der Anonymisierung gelöscht werden, können nicht wiederhergestellt werden.
+
+ Wenn diese/r nur inaktiv geworden ist und Sie alle Details dieses Datensatzes erhalten wollen, können Sie diesen stattdessen auch nur "archivieren".
+
+ Sind Sie sicher, dass Sie diesen Datensatz anonymisieren wollen?
+ Anonymize confirmation dialog
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 133
+
+
+
+ Some related records (e.g. notes) may still contain personal data in their text. We have automatically anonymized all records that are linked to ONLY this .
+ However, there are some records that are linked to multiple records. We have not anonymized these, so that you will not lose relevant data. Please review them manually to ensure all sensitive information is removed (e.g. by looking through the linked notes and editing a note's text).
+ Einige verknüpfte Einträge können noch persönliche Daten enthalten (z.B. Notizen in ihrem Text). Wir haben automatisch alle Datensätze anonymisiert, die NUR mit diesem -Datensatz verknüpft waren.
+ Es existieren allerdings einige Datensätze, die mit mehreren Einträgen verknüpft sind. Wir haben diese nicht anonymisiert, damit Sie keine relevanten Daten verlieren. Bitte überprüfen Sie diese selbst, um sicherzustellen, dass alle sensiblen Informationen entfern wurden (z.B. indem Sie verknüpfte Notizen durchgehen und Notiz-Texte wenn nötig bearbeiten).
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 153,156
+
+ post-anonymize related PII warning dialog
+
+
+ Anonymized
+ anonymisiert
+ Entity action confirmation message verb
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 163
+
+
+
+ Archived
+ Archived
+ Entity action confirmation message verb
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 180
+
+
+
+ Reactivated
+ reaktiviert
+ Entity action confirmation message verb
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 196
Undo
Zurück
- Undo deleting an entity
+ Undo an entity action
- src/app/core/entity/entity-remove.service.ts
- 97
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 41
src/app/core/import/import-confirm-summary/import-confirm-summary.component.ts
61
-
- Ticking this box will archive the record. No data will be lost but the record will be hidden.
- Durch das Abhaken wird der Eintrag archiviert. Es werden dadurch keine Daten gelöscht, der Eintrag wird aber versteckt.
- Description of checkbox
+
+ Reverting changes ...
+ Änderungen werden rückgängig gemacht ...
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 50
+
+ Undo entity action progress dialog
+
+
+ [anonymized ]
+ [anonymisierte/r ]
+ Entity.toString fallback for anonymized record
src/app/core/entity/model/entity.ts
- 195
+ 316
@@ -4817,7 +4956,7 @@
Examples of things to filter
src/app/core/entity-list/entity-list/entity-list.component.html
- 104
+ 106
@@ -4826,7 +4965,7 @@
Add a new entity to a list of multiple entities
src/app/core/entity-list/entity-list/entity-list.component.html
- 154
+ 158
@@ -4835,9 +4974,27 @@
Show filter options popup for list
src/app/core/entity-list/entity-list/entity-list.component.html
- 166
+ 170
+
+ Download all data (.csv)
+ Download alle (.csv)
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 189
+
+ Download list contents as CSV
+
+
+ Download current (.csv)
+ Download angezeigte (.csv)
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 207
+
+ Download list contents as CSV
+
Filter
Filter
@@ -4845,24 +5002,56 @@
Filter placeholder
src/app/core/entity-list/entity-list/entity-list.component.html
- 98
+ 100
-
- Download CSV
- Download als CSV
- Download list contents as CSV
+
+ Import from file
+ Datei importieren
src/app/core/entity-list/entity-list/entity-list.component.html
- 185
+ 223
-
- Import from file
- Datei importieren
+
+ Select multiple records for bulk actions like duplicating or deleting
+ Wählen Sie mehrere Datensätze aus, um gemeinsame Aktionen für alle auszuführen (z.B. Duplizieren oder Löschen)
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 229
+
+
+
+ Bulk Actions
+ Massen-Bearbeitung
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 237
+
+
+
+ Select rows to clone
+ Wählen Sie Zeilen aus, um diese zu kopieren
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 252
+
+
+
+ Duplicate
+ Duplizieren
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 256,258
+
+ bulk action button
+
+
+ Cancel
+ Abbrechen
src/app/core/entity-list/entity-list/entity-list.component.html
- 201
+ 260,262
@@ -4928,7 +5117,7 @@
Tooltip for the disabled age field
src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.component.html
- 28
+ 34
@@ -4937,7 +5126,7 @@
Placeholder for the input that displays the age
src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.component.html
- 21
+ 27
@@ -4950,6 +5139,15 @@
28
+
+ Select matching property
+ Wähle zugeordnetes Feld von " "
+
+ src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
+ 2,4
+
+ Label for property selection
+
51
+
+ Include archived records
+ Archivierte Datensätze anzeigen
+ also show entries that are archived
+ slider
+
+ src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.html
+ 160
+
+
in total
@@ -5142,6 +5350,15 @@
59
+
+ " "
+ " "
+ Entity action confirmation message
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 35
+
+
Show previous changes
Zeige vorangegangene Veränderungen
@@ -5164,7 +5381,7 @@
Wollen Sie siche die Option " " löschen?
src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.ts
- 71
+ 73
@@ -5176,7 +5393,7 @@
)"/> Einträgen genutzt. Wenn Sie die Option löschen, werden die Einträge nicht gelöscht, aber die Option besonders markiert.
src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.ts
- 73
+ 75
@@ -5184,7 +5401,7 @@
Option Löschen
src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.ts
- 78
+ 80
@@ -5193,7 +5410,7 @@
Discard changes header
src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
- 62
+ 63
@@ -5202,7 +5419,7 @@
Discard changes message
src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
- 63
+ 64
@@ -5661,7 +5878,7 @@
Änderungen laden?
src/app/core/common-components/entity-form/entity-form/entity-form.component.ts
- 110
+ 111
@@ -5669,7 +5886,7 @@
Lokale Änderungen überlappen mit aktualisierten Daten, die vom Server synchronisiert wurden. Wollen Sie die lokalen Änderungen mit den aktuellsten Daten überschreiben?
src/app/core/common-components/entity-form/entity-form/entity-form.component.ts
- 111
+ 112
@@ -5768,7 +5985,7 @@
Label of username
src/app/core/user/user.ts
- 38
+ 39
@@ -5778,7 +5995,7 @@
Error message when trying to change the username
src/app/core/user/user.ts
- 46
+ 47
@@ -6235,6 +6452,14 @@
15
+
+ Please select a report and a date range
+ Bitte wählen Sie einen Bericht und einen Zeitraum
+
+ src/app/features/reporting/reporting/select-report/select-report.component.html
+ 66
+
+
Enter a date range
von – bis
@@ -6274,23 +6499,39 @@
36
+
+ This data has been partially anonymized.
+ Diese Daten wurden teilweise anonymisiert.
+
+ src/app/core/basic-datatypes/date/display-date/display-date.component.html
+ 11
+
+
+ src/app/core/basic-datatypes/date/edit-date/edit-date.component.html
+ 13
+
+
+ src/app/core/basic-datatypes/month/edit-month/edit-month.component.html
+ 13
+
+
Calculate
Berechnen
Calculate the results for a report
src/app/features/reporting/reporting/select-report/select-report.component.html
- 65
+ 70
Download
Herunterladen
+ Button to download data
src/app/features/reporting/reporting/select-report/select-report.component.html
- 87
+ 93
- Button to download data
get signed agreement
@@ -6379,7 +6620,7 @@
Label
src/app/features/todos/model/todo.ts
- 47
+ 48
@@ -6388,7 +6629,7 @@
Description
src/app/features/todos/model/todo.ts
- 55
+ 57
@@ -6397,7 +6638,7 @@
Label
src/app/features/todos/model/todo.ts
- 68
+ 71
@@ -6406,7 +6647,7 @@
label for Todo entity property
src/app/features/todos/model/todo.ts
- 94
+ 100
@@ -6415,7 +6656,7 @@
repetition interval option
src/app/features/todos/model/todo.ts
- 97
+ 103
@@ -6424,7 +6665,7 @@
repetition interval option
src/app/features/todos/model/todo.ts
- 101
+ 107
@@ -6433,7 +6674,7 @@
label for Todo entity property
src/app/features/todos/model/todo.ts
- 110
+ 117
@@ -6616,7 +6857,7 @@
Filter-option for todos
src/app/features/todos/todo-list/todo-list.component.ts
- 129
+ 131
@@ -6625,7 +6866,7 @@
Filter-option for todos
src/app/features/todos/todo-list/todo-list.component.ts
- 99
+ 101
@@ -6634,7 +6875,7 @@
Filter-option for todos
src/app/features/todos/todo-list/todo-list.component.ts
- 104
+ 106
@@ -6643,7 +6884,7 @@
Filter-option for todos
src/app/features/todos/todo-list/todo-list.component.ts
- 109
+ 111
@@ -6651,7 +6892,7 @@
Alle
src/app/features/todos/todo-list/todo-list.component.ts
- 112
+ 114
@@ -6659,7 +6900,7 @@
fällige Aufgaben
src/app/features/todos/todo-list/todo-list.component.ts
- 114
+ 116
@@ -6681,16 +6922,6 @@
dashboard showing open todos
subtitle
-
- Also show completed
- Auch erledigte anzeigen
- also show entries that are inactive
- slider
-
- src/app/features/todos/todos-related-to-entity/todos-related-to-entity.component.html
- 17
-
-
Install App
App installieren
diff --git a/src/assets/locale/messages.fr.xlf b/src/assets/locale/messages.fr.xlf
index 26cbd83145..aeb78da414 100644
--- a/src/assets/locale/messages.fr.xlf
+++ b/src/assets/locale/messages.fr.xlf
@@ -8,7 +8,7 @@
Label for date of the ASER results
src/app/child-dev-project/children/aser/model/aser.ts
- 30
+ 39
src/app/child-dev-project/children/educational-material/model/educational-material.ts
@@ -16,15 +16,15 @@
src/app/child-dev-project/children/health-checkup/model/health-check.ts
- 34
+ 45
src/app/child-dev-project/notes/model/note.ts
- 92
+ 99
src/app/features/historical-data/model/historical-entity-data.ts
- 13
+ 16
@@ -33,7 +33,7 @@
Label of the Hindi ASER result
src/app/child-dev-project/children/aser/model/aser.ts
- 35
+ 46
src/app/child-dev-project/schools/demo-school-generator.service.ts
@@ -46,7 +46,7 @@
Label of the Bengali ASER result
src/app/child-dev-project/children/aser/model/aser.ts
- 41
+ 52
src/app/child-dev-project/schools/demo-school-generator.service.ts
@@ -59,7 +59,7 @@
Label of the English ASER result
src/app/child-dev-project/children/aser/model/aser.ts
- 47
+ 58
src/app/child-dev-project/schools/demo-school-generator.service.ts
@@ -72,7 +72,7 @@
Label of the Math ASER result
src/app/child-dev-project/children/aser/model/aser.ts
- 53
+ 64
@@ -81,11 +81,11 @@
Label for the remarks of a ASER result
src/app/child-dev-project/children/aser/model/aser.ts
- 59
+ 71
src/app/core/config/config-fix.ts
- 1055
+ 1041
@@ -244,7 +244,7 @@
src/app/core/config/config-fix.ts
- 886
+ 859
@@ -285,7 +285,7 @@
Sauvegarder
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 54
+ 45
@@ -294,7 +294,7 @@
Discard changes made to a form
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 63
+ 54
@@ -303,7 +303,7 @@
One of the stages while recording child-attendances
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 72
+ 63
@@ -312,7 +312,7 @@
One of the stages while recording child-attendances
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 73
+ 64
@@ -321,7 +321,7 @@
Exit from the current screen
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 94
+ 80
@@ -329,7 +329,7 @@
Voulez-vous sauvegarder votre progression avant de revenir en arrière ?
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 95
+ 81
@@ -380,6 +380,14 @@
214
+
+ Excluded some archived participants. Click to include.
+ Excluded some archived participants. Click to include.
+
+ src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
+ 58
+
+
Attendance completed.
Appel effectué.
@@ -388,7 +396,7 @@
Attendance completed
src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
- 107
+ 120
@@ -397,7 +405,7 @@
Open details of recorded event for review
src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
- 117
+ 130
@@ -406,7 +414,23 @@
Back to overview button after finishing a roll call
src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
- 127
+ 140
+
+
+
+ Also include archived participants?
+ Also include archived participants?
+
+ src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.ts
+ 271
+
+
+
+ This event has some participants who are "archived". We automatically remove them from the attendance list for you. Do you want to also include archived participants for this event?
+ This event has some participants who are "archived". We automatically remove them from the attendance list for you. Do you want to also include archived participants for this event?
+
+ src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.ts
+ 272
@@ -734,7 +758,7 @@
Label for the school of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 23
+ 27
src/app/child-dev-project/schools/demo-school-generator.service.ts
@@ -746,11 +770,11 @@
src/app/core/config/config-fix.ts
- 463
+ 449
src/app/core/config/config-fix.ts
- 574
+ 551
@@ -874,11 +898,11 @@
src/app/core/config/config-fix.ts
- 813
+ 786
src/app/core/config/config-fix.ts
- 891
+ 864
@@ -891,7 +915,7 @@
src/app/child-dev-project/notes/model/note.ts
- 144
+ 167
@@ -953,19 +977,11 @@
Tous
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 76
+ 75
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 90
-
-
- src/app/core/config/config-fix.ts
- 566
-
-
- src/app/core/config/config-fix.ts
- 782
+ 89
src/app/core/filter/filters/filters.ts
@@ -1072,7 +1088,7 @@
src/app/core/config/config-fix.ts
- 747
+ 731
@@ -1183,7 +1199,7 @@
Label for the name of a child
src/app/child-dev-project/children/model/child.ts
- 46
+ 47
src/app/child-dev-project/schools/model/school.ts
@@ -1191,15 +1207,15 @@
src/app/core/config/config-fix.ts
- 447
+ 433
src/app/core/config/config-fix.ts
- 909
+ 882
src/app/core/config/config-fix.ts
- 1013
+ 999
@@ -1208,7 +1224,7 @@
Label for the project number of a child
src/app/child-dev-project/children/model/child.ts
- 54
+ 55
@@ -1217,7 +1233,7 @@
Short label for the project number
src/app/child-dev-project/children/model/child.ts
- 55
+ 56
@@ -1226,7 +1242,7 @@
Label for the date of birth of a child
src/app/child-dev-project/children/model/child.ts
- 61
+ 63
@@ -1235,7 +1251,7 @@
Short label for the date of birth
src/app/child-dev-project/children/model/child.ts
- 62
+ 64
@@ -1244,7 +1260,7 @@
Label for the gender of a child
src/app/child-dev-project/children/model/child.ts
- 68
+ 71
@@ -1253,7 +1269,7 @@
Label for the center of a child
src/app/child-dev-project/children/model/child.ts
- 76
+ 80
@@ -1262,7 +1278,7 @@
Label for the admission date of a child
src/app/child-dev-project/children/model/child.ts
- 81
+ 86
@@ -1271,11 +1287,11 @@
Label for the status of a child
src/app/child-dev-project/children/model/child.ts
- 86
+ 92
src/app/child-dev-project/notes/model/note.ts
- 151
+ 176
src/app/core/config/config-fix.ts
@@ -1283,11 +1299,7 @@
src/app/core/config/config-fix.ts
- 524
-
-
- src/app/core/config/config-fix.ts
- 779
+ 510
@@ -1296,7 +1308,7 @@
Label for the dropout date of a child
src/app/child-dev-project/children/model/child.ts
- 91
+ 97
@@ -1305,7 +1317,7 @@
Label for the type of dropout of a child
src/app/child-dev-project/children/model/child.ts
- 96
+ 103
@@ -1314,17 +1326,17 @@
Label for the remarks about a dropout of a child
src/app/child-dev-project/children/model/child.ts
- 101
+ 109
Photo
Photo
+ Label for the file field of a photo of a child
src/app/child-dev-project/children/model/child.ts
- 112
+ 120
- Label for the file field of a photo of a child
Phone Number
@@ -1332,11 +1344,11 @@
Label for the phone number of a child
src/app/child-dev-project/children/model/child.ts
- 118
+ 126
src/app/core/config/config-fix.ts
- 1041
+ 1027
@@ -1345,11 +1357,11 @@
Label for the child of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 13
+ 15
src/app/core/config/config-fix.ts
- 959
+ 945
@@ -1358,11 +1370,11 @@
Label for the class of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 32
+ 38
src/app/core/config/config-fix.ts
- 458
+ 444
@@ -1371,7 +1383,7 @@
Label for the start date of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 37
+ 43
src/app/core/entity-details/related-time-period-entities/time-period.ts
@@ -1379,7 +1391,7 @@
src/app/features/todos/model/todo.ts
- 54
+ 56
@@ -1388,7 +1400,7 @@
Description of the start date of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 38
+ 44
@@ -1397,7 +1409,7 @@
Label for the end date of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 44
+ 51
src/app/core/entity-details/related-time-period-entities/time-period.ts
@@ -1410,7 +1422,7 @@
Description of the end date of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 45
+ 52
@@ -1419,7 +1431,7 @@
Label for the percentage result of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 51
+ 59
@@ -1428,7 +1440,7 @@
Error assertValid failed
src/app/core/entity-details/related-time-period-entities/time-period.ts
- 63
+ 68
@@ -1437,7 +1449,7 @@
Error assertValid failed
src/app/core/entity-details/related-time-period-entities/time-period.ts
- 67
+ 72
@@ -1495,7 +1507,7 @@
src/app/features/todos/model/todo.ts
- 61
+ 64
@@ -1652,7 +1664,7 @@
src/app/core/config/config-fix.ts
- 488
+ 474
@@ -1670,7 +1682,7 @@
Label for height in cm of a health check
src/app/child-dev-project/children/health-checkup/model/health-check.ts
- 39
+ 52
@@ -1679,7 +1691,7 @@
Label for weight in kg of a health check
src/app/child-dev-project/children/health-checkup/model/health-check.ts
- 47
+ 60
@@ -2191,7 +2203,7 @@
Label for the children of a note
src/app/child-dev-project/notes/model/note.ts
- 76
+ 77
src/app/core/config/config-fix.ts
@@ -2199,11 +2211,7 @@
src/app/core/config/config-fix.ts
- 563
-
-
- src/app/core/config/config-fix.ts
- 960
+ 946
@@ -2212,11 +2220,11 @@
Label for the subject of a note
src/app/child-dev-project/notes/model/note.ts
- 97
+ 106
src/app/features/todos/model/todo.ts
- 42
+ 43
@@ -2229,7 +2237,7 @@
src/app/child-dev-project/notes/model/note.ts
- 100
+ 110
src/app/core/config/config-fix.ts
@@ -2242,7 +2250,7 @@
Label for the social worker(s) who created the note
src/app/child-dev-project/notes/model/note.ts
- 106
+ 117
@@ -2251,7 +2259,7 @@
Label for the category of a note
src/app/child-dev-project/notes/model/note.ts
- 114
+ 126
@@ -2260,11 +2268,11 @@
label for the related Entities
src/app/child-dev-project/notes/model/note.ts
- 132
+ 154
src/app/features/todos/model/todo.ts
- 83
+ 87
@@ -2285,7 +2293,7 @@
Download note details as CSV
src/app/child-dev-project/notes/note-details/note-details.component.html
- 90
+ 94
@@ -2294,7 +2302,7 @@
Filter-option for notes
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 66
+ 65
@@ -2303,7 +2311,7 @@
Filter-option for notes
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 71
+ 70
src/app/child-dev-project/warning-level.ts
@@ -2316,7 +2324,7 @@
Filter-option for notes
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 82
+ 81
@@ -2325,36 +2333,7 @@
Filter-option for notes
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 87
-
-
-
- Show entries where the end date is in the past
- Show entries where the end date is in the past
- Tooltip that will appear when hovered over the
- show-ended button
- Show ended tooltip
-
- src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
- 32
-
-
- src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
- 32
-
-
-
- Include inactive past records
- Include inactive past records
- also show entries that are inactive
- slider
-
- src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
- 34
-
-
- src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
- 34
+ 86
@@ -2621,7 +2600,7 @@
src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
- 18
+ 24
src/app/features/dashboard-widgets/progress-dashboard-widget/edit-progress-dashboard/edit-progress-dashboard.component.html
@@ -2652,27 +2631,10 @@
86
-
- Select matching property
- Select matching property
- Label for property selection
-
- src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
- 2
-
-
Select which property of the target entity is matching with the values of this column. E.g. if your column contains names of children then select 'Name'.
Select which property of the target entity is matching with the values of this column. E.g. if your column contains names of children then select 'Name'.
import - value mapping (entity) - help text
-
- src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
- 9
-
-
-
- Save & Close
- Save & Close
src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
15
@@ -2860,7 +2822,7 @@
Label for the currently active status
src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
- 105
+ 97
@@ -2869,7 +2831,7 @@
Tooltip for the status of currently active or not
src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
- 108
+ 100
@@ -2878,7 +2840,7 @@
Indication for the currently active status of an entry
src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
- 111
+ 103
@@ -2887,7 +2849,7 @@
Indication for the currently inactive status of an entry
src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
- 112
+ 104
@@ -3388,19 +3350,19 @@
src/app/core/config/config-fix.ts
- 495
+ 481
src/app/core/config/config-fix.ts
- 549
+ 535
Attachment
Attachment
- src/app/core/config/config-fix.ts
- 269
+ src/app/child-dev-project/notes/model/note.ts
+ 134
@@ -3408,7 +3370,7 @@
Site Settings
src/app/core/config/config-fix.ts
- 281
+ 267
@@ -3417,7 +3379,7 @@
Panel title
src/app/core/config/config-fix.ts
- 328
+ 314
@@ -3426,7 +3388,7 @@
Panel title
src/app/core/config/config-fix.ts
- 347
+ 333
@@ -3435,7 +3397,7 @@
Filename of markdown help page (make sure the filename you enter as a translation actually exists on the server!)
src/app/core/config/config-fix.ts
- 361
+ 347
@@ -3443,11 +3405,11 @@
École privée
src/app/core/config/config-fix.ts
- 382
+ 368
src/app/core/config/config-fix.ts
- 1020
+ 1006
@@ -3456,15 +3418,15 @@
Panel title
src/app/core/config/config-fix.ts
- 393
+ 379
src/app/core/config/config-fix.ts
- 585
+ 569
src/app/core/config/config-fix.ts
- 798
+ 771
@@ -3473,7 +3435,7 @@
Panel title
src/app/core/config/config-fix.ts
- 421
+ 407
@@ -3482,7 +3444,7 @@
Panel title
src/app/core/config/config-fix.ts
- 430
+ 416
@@ -3491,7 +3453,7 @@
Column label for age of child
src/app/core/config/config-fix.ts
- 452
+ 438
@@ -3500,7 +3462,7 @@
Column label for school attendance of child
src/app/core/config/config-fix.ts
- 470
+ 456
@@ -3509,7 +3471,7 @@
Column label for coaching attendance of child
src/app/core/config/config-fix.ts
- 479
+ 465
@@ -3518,7 +3480,7 @@
Column group name
src/app/core/config/config-fix.ts
- 511
+ 497
@@ -3527,11 +3489,11 @@
Translated name of default column group
src/app/core/config/config-fix.ts
- 494
+ 480
src/app/core/config/config-fix.ts
- 498
+ 484
@@ -3540,41 +3502,11 @@
Column group name
src/app/core/config/config-fix.ts
- 534
-
-
- src/app/core/config/config-fix.ts
- 683
-
-
-
- Active
- Actifs
- Active children filter label - true case
-
- src/app/core/config/config-fix.ts
- 564
+ 520
src/app/core/config/config-fix.ts
- 780
-
-
-
- Inactive
- Inactifs
- Active children filter label - false case
-
- src/app/core/config/config-fix.ts
- 565
-
-
- src/app/core/config/config-fix.ts
- 781
-
-
- src/app/core/entity/model/entity.ts
- 194
+ 667
@@ -3583,7 +3515,7 @@
Header for form section
src/app/core/config/config-fix.ts
- 613
+ 597
@@ -3592,7 +3524,7 @@
Header for form section
src/app/core/config/config-fix.ts
- 614
+ 598
@@ -3601,7 +3533,7 @@
Header for form section
src/app/core/config/config-fix.ts
- 615
+ 599
@@ -3610,7 +3542,7 @@
Panel title
src/app/core/config/config-fix.ts
- 622
+ 606
@@ -3619,7 +3551,7 @@
Title inside a panel
src/app/core/config/config-fix.ts
- 625
+ 609
@@ -3628,7 +3560,7 @@
Title inside a panel
src/app/core/config/config-fix.ts
- 645
+ 629
@@ -3637,7 +3569,7 @@
Child details section title
src/app/core/config/config-fix.ts
- 649
+ 633
@@ -3646,7 +3578,7 @@
Panel title
src/app/core/config/config-fix.ts
- 670
+ 654
@@ -3655,7 +3587,7 @@
description section
src/app/core/config/config-fix.ts
- 692
+ 676
@@ -3668,7 +3600,7 @@
src/app/core/config/config-fix.ts
- 661
+ 645
@@ -3690,7 +3622,7 @@
Title inside a panel
src/app/core/config/config-fix.ts
- 699
+ 683
@@ -3699,7 +3631,7 @@
Panel title
src/app/core/config/config-fix.ts
- 705
+ 689
@@ -3708,7 +3640,7 @@
Panel title
src/app/core/config/config-fix.ts
- 730
+ 714
@@ -3717,7 +3649,7 @@
Panel title
src/app/core/config/config-fix.ts
- 828
+ 801
@@ -3726,7 +3658,7 @@
Name of a report
src/app/core/config/config-fix.ts
- 843
+ 816
@@ -3735,7 +3667,7 @@
Label of report query
src/app/core/config/config-fix.ts
- 847
+ 820
@@ -3744,7 +3676,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 852
+ 825
@@ -3753,7 +3685,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 855
+ 828
@@ -3762,7 +3694,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 859
+ 832
@@ -3771,7 +3703,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 864
+ 837
@@ -3780,7 +3712,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 868
+ 841
@@ -3789,7 +3721,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 873
+ 846
@@ -3798,7 +3730,7 @@
Name of a report
src/app/core/config/config-fix.ts
- 881
+ 854
@@ -3807,7 +3739,7 @@
Name of a report
src/app/core/config/config-fix.ts
- 898
+ 871
@@ -3816,7 +3748,7 @@
Name of a column of a report
src/app/core/config/config-fix.ts
- 913
+ 899
@@ -3825,7 +3757,7 @@
Name of a column of a report
src/app/core/config/config-fix.ts
- 917
+ 903
@@ -3834,7 +3766,7 @@
Name of a column of a report
src/app/core/config/config-fix.ts
- 921
+ 907
@@ -3843,7 +3775,7 @@
Name of a column of a report
src/app/core/config/config-fix.ts
- 925
+ 911
@@ -3852,7 +3784,7 @@
Name of a report
src/app/core/config/config-fix.ts
- 935
+ 921
@@ -3861,11 +3793,11 @@
Label for the address of a child
src/app/core/config/config-fix.ts
- 966
+ 952
src/app/core/config/config-fix.ts
- 1034
+ 1020
@@ -3874,7 +3806,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 973
+ 959
@@ -3883,7 +3815,7 @@
Label for the religion of a child
src/app/core/config/config-fix.ts
- 980
+ 966
@@ -3892,7 +3824,7 @@
Label for the mother tongue of a child
src/app/core/config/config-fix.ts
- 987
+ 973
@@ -3901,7 +3833,7 @@
Tooltip description for the mother tongue of a child
src/app/core/config/config-fix.ts
- 988
+ 974
@@ -3910,7 +3842,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 995
+ 981
@@ -3919,7 +3851,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1002
+ 988
@@ -3928,7 +3860,7 @@
Label for the language of a school
src/app/core/config/config-fix.ts
- 1027
+ 1013
@@ -3937,7 +3869,7 @@
Label for the timing of a school
src/app/core/config/config-fix.ts
- 1048
+ 1034
@@ -3946,7 +3878,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1067
+ 1053
@@ -3955,7 +3887,7 @@
Description for a child attribute
src/app/core/config/config-fix.ts
- 1068
+ 1054
@@ -3964,7 +3896,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1076
+ 1062
@@ -3973,7 +3905,7 @@
Description for a child attribute
src/app/core/config/config-fix.ts
- 1077
+ 1063
@@ -3982,7 +3914,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1085
+ 1071
@@ -3991,7 +3923,7 @@
Description for a child attribute
src/app/core/config/config-fix.ts
- 1086
+ 1072
@@ -4000,7 +3932,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1094
+ 1080
@@ -4009,7 +3941,7 @@
Description for a child attribute
src/app/core/config/config-fix.ts
- 1095
+ 1081
@@ -4018,7 +3950,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1103
+ 1089
@@ -4027,7 +3959,7 @@
Description for a child attribute
src/app/core/config/config-fix.ts
- 1104
+ 1090
@@ -4036,7 +3968,7 @@
Label of user phone
src/app/core/config/config-fix.ts
- 1115
+ 1101
@@ -4172,13 +4104,21 @@
1
+
+ Add new option
+ Add new option
+
+ src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.html
+ 32
+
+
Close
Fermer
Close popup
src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.html
- 29
+ 46
src/app/core/filter/filter-overlay/filter-overlay.component.html
@@ -4280,6 +4220,92 @@
28
+
+ Archive
+ Archive
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 69
+
+ entity context menu
+
+
+ Mark the record as inactive, hiding it from lists by default while keeping the data.
+ Mark the record as inactive, hiding it from lists by default while keeping the data.
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 70
+
+ entity context menu tooltip
+
+
+ Anonymize
+ Anonymize
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 77
+
+ entity context menu
+
+
+ Remove all personal data and keep an archived basic record for statistical reporting.
+ Remove all personal data and keep an archived basic record for statistical reporting.
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 78
+
+ entity context menu tooltip
+
+
+ Delete
+ Supprimer
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 85
+
+ entity context menu
+
+
+ Remove the record completely from the database.
+ Remove the record completely from the database.
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 86
+
+ entity context menu tooltip
+
+
+ Archived
+ Archived
+
+ src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
+ 6
+
+
+
+ Anonymized & Archived
+ Anonymized & Archived
+
+ src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
+ 8
+
+
+
+ This record has been anonymized. Details containing personal information have been deleted and cannot be restored. For statistical reporting, this basic record has been kept.
+ This record has been anonymized. Details containing personal information have been deleted and cannot be restored. For statistical reporting, this basic record has been kept.
+
+ src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
+ 13,17
+
+
+
+ This record is archived and will be be hidden from lists and select options by default.
+ This record is archived and will be be hidden from lists and select options by default.
+
+ src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
+ 19,22
+
+
Adding new
Ajout d'un(e)
@@ -4290,26 +4316,13 @@
27
-
- Delete
- Supprimer
- Generic delete button
-
- src/app/core/entity-details/entity-details/entity-details.component.html
- 58
-
-
- src/app/core/form-dialog/dialog-buttons/dialog-buttons.component.html
- 61
-
-
Save the new record to create it before accessing other details
Save the new record to create it before accessing other details
Tooltip explaining disabled sections when creating new entity
src/app/core/entity-details/entity-details/entity-details.component.html
- 74
+ 51
@@ -4436,7 +4449,7 @@
Examples of things to filter
src/app/core/entity-list/entity-list/entity-list.component.html
- 104
+ 106
@@ -4445,7 +4458,7 @@
Add a new entity to a list of multiple entities
src/app/core/entity-list/entity-list/entity-list.component.html
- 154
+ 158
@@ -4454,9 +4467,27 @@
Show filter options popup for list
src/app/core/entity-list/entity-list/entity-list.component.html
- 166
+ 170
+
+ Download all data (.csv)
+ Download all data (.csv)
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 189
+
+ Download list contents as CSV
+
+
+ Download current (.csv)
+ Download current (.csv)
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 207
+
+ Download list contents as CSV
+
Filter
Filtrer
@@ -4464,24 +4495,56 @@
Filter placeholder
src/app/core/entity-list/entity-list/entity-list.component.html
- 98
+ 100
-
- Download CSV
- Télécharger au format CSV
- Download list contents as CSV
+
+ Import from file
+ Import from file
src/app/core/entity-list/entity-list/entity-list.component.html
- 185
+ 223
-
- Import from file
- Import from file
+
+ Select multiple records for bulk actions like duplicating or deleting
+ Select multiple records for bulk actions like duplicating or deleting
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 229
+
+
+
+ Bulk Actions
+ Bulk Actions
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 237
+
+
+
+ Select rows to clone
+ Select rows to clone
src/app/core/entity-list/entity-list/entity-list.component.html
- 201
+ 252
+
+
+
+ Duplicate
+ Duplicate
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 256,258
+
+ bulk action button
+
+
+ Cancel
+ Annuler
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 260,262
@@ -4538,7 +4601,7 @@
Tooltip for the disabled age field
src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.component.html
- 28
+ 34
@@ -4547,7 +4610,7 @@
Placeholder for the input that displays the age
src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.component.html
- 21
+ 27
@@ -4560,6 +4623,15 @@
28
+
+ Select matching property
+ Select matching property
+
+ src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
+ 2,4
+
+ Label for property selection
+
51
+
+ Include archived records
+ Include archived records
+ also show entries that are archived
+ slider
+
+ src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.html
+ 160
+
+
in total
@@ -4666,53 +4748,184 @@
59
+
+ " "
+ " "
+ Entity action confirmation message
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 35
+
+
Delete?
Supprimer?
Delete confirmation title
- src/app/core/entity/entity-remove.service.ts
- 78
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 76
-
- Are you sure you want to delete this record?
- Are you sure you want to delete this record?
+
+
+ This will remove the data permanently as if it never existed. This cannot be undone. Statistical reports (also for past time periods) will change and not include this record anymore.
+
+ If you have not just created this record accidentally, deleting this is probably not what you want to do. If the record represents something that actually happened in your work, consider to use "anonymize" or just "archive" instead, so that you will not lose your documentation for reports.
+
+ Are you sure you want to delete this record?
+
+ This will remove the data permanently as if it never existed. This cannot be undone. Statistical reports (also for past time periods) will change and not include this record anymore.
+
+ If you have not just created this record accidentally, deleting this is probably not what you want to do. If the record represents something that actually happened in your work, consider to use "anonymize" or just "archive" instead, so that you will not lose your documentation for reports.
+
+ Are you sure you want to delete this record?
+ Delete confirmation dialog
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 77
+
+
+
+ Processing ...
+ Processing ...
- src/app/core/entity/entity-remove.service.ts
- 81
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 89
- Delete confirmation text
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 145
+
+ Entity action progress dialog
-
- Deleted Entity
- Élément supprimé
- Deleted Entity information
+
+ Related records may still contain personal data
+ Related records may still contain personal data
- src/app/core/entity/entity-remove.service.ts
- 93
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 96
+
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 152
+
+ post-delete related PII warning title
+
+
+ Some related records (e.g. notes) may still contain personal data in their text. We have automatically deleted all records that are linked to ONLY this .
+ However, there are some records that are linked to multiple records. We have not deleted these, so that you will not lose relevant data. Please review them manually to ensure all sensitive information is removed, if required (e.g. by looking through the linked notes and editing a note's text).
+ Some related records (e.g. notes) may still contain personal data in their text. We have automatically deleted all records that are linked to ONLY this .
+ However, there are some records that are linked to multiple records. We have not deleted these, so that you will not lose relevant data. Please review them manually to ensure all sensitive information is removed, if required (e.g. by looking through the linked notes and editing a note's text).
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 97,100
+
+ post-delete related PII warning dialog
+
+
+ Deleted
+ Deleted
+ Entity action confirmation message verb
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 114
+
+
+
+ Anonymize?
+ Anonymize?
+ Anonymize confirmation dialog
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 132
+
+
+
+
+ This will remove all personal information (PII) permanently and keep only a basic record for statistical reports. Details that are removed during anonymization cannot be recovered.
+
+ If this has only become inactive and you want to keep all details about the record, consider to use "archive" instead.
+
+ Are you sure you want to anonymize this record?
+
+ This will remove all personal information (PII) permanently and keep only a basic record for statistical reports. Details that are removed during anonymization cannot be recovered.
+
+ If this has only become inactive and you want to keep all details about the record, consider to use "archive" instead.
+
+ Are you sure you want to anonymize this record?
+ Anonymize confirmation dialog
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 133
+
+
+
+ Some related records (e.g. notes) may still contain personal data in their text. We have automatically anonymized all records that are linked to ONLY this .
+ However, there are some records that are linked to multiple records. We have not anonymized these, so that you will not lose relevant data. Please review them manually to ensure all sensitive information is removed (e.g. by looking through the linked notes and editing a note's text).
+ Some related records (e.g. notes) may still contain personal data in their text. We have automatically anonymized all records that are linked to ONLY this .
+ However, there are some records that are linked to multiple records. We have not anonymized these, so that you will not lose relevant data. Please review them manually to ensure all sensitive information is removed (e.g. by looking through the linked notes and editing a note's text).
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 153,156
+
+ post-anonymize related PII warning dialog
+
+
+ Anonymized
+ Anonymized
+ Entity action confirmation message verb
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 163
+
+
+
+ Archived
+ Archived
+ Entity action confirmation message verb
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 180
+
+
+
+ Reactivated
+ Reactivated
+ Entity action confirmation message verb
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 196
Undo
Annuler l'action
- Undo deleting an entity
+ Undo an entity action
- src/app/core/entity/entity-remove.service.ts
- 97
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 41
src/app/core/import/import-confirm-summary/import-confirm-summary.component.ts
61
-
- Ticking this box will archive the record. No data will be lost but the record will be hidden.
- Ticking this box will archive the record. No data will be lost but the record will be hidden.
- Description of checkbox
+
+ Reverting changes ...
+ Reverting changes ...
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 50
+
+ Undo entity action progress dialog
+
+
+ [anonymized ]
+ [anonymized ]
+ Entity.toString fallback for anonymized record
src/app/core/entity/model/entity.ts
- 195
+ 316
@@ -4791,7 +5004,7 @@
Are you sure that you want to delete the option " "?
src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.ts
- 71
+ 73
@@ -4803,7 +5016,7 @@
)"/> records. If deleted, the records will not be lost but specially marked.
src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.ts
- 73
+ 75
@@ -4811,7 +5024,7 @@
Delete option
src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.ts
- 78
+ 80
@@ -4820,7 +5033,7 @@
Discard changes header
src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
- 62
+ 63
@@ -4829,7 +5042,7 @@
Discard changes message
src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
- 63
+ 64
@@ -5336,7 +5549,7 @@
Load changes?
src/app/core/common-components/entity-form/entity-form/entity-form.component.ts
- 110
+ 111
@@ -5344,7 +5557,7 @@
Local changes are in conflict with updated values synced from the server. Do you want the local changes to be overwritten with the latest values?
src/app/core/common-components/entity-form/entity-form/entity-form.component.ts
- 111
+ 112
@@ -5443,7 +5656,7 @@
Label of username
src/app/core/user/user.ts
- 38
+ 39
@@ -5453,7 +5666,7 @@
Error message when trying to change the username
src/app/core/user/user.ts
- 46
+ 47
@@ -5914,7 +6127,7 @@
src/app/features/file/edit-photo/edit-photo.component.html
- 17
+ 22
@@ -5923,7 +6136,7 @@
Message for user
src/app/features/file/edit-file/edit-file.component.ts
- 132
+ 134
@@ -6006,6 +6219,10 @@
src/app/core/basic-datatypes/discrete/discrete-import-config/discrete-import-config.component.html
32
+
+ src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
+ 21
+
not at all
@@ -6145,7 +6362,7 @@
help text in map popup
src/app/features/location/edit-location/edit-location.component.ts
- 118
+ 119
@@ -6297,6 +6514,14 @@
15
+
+ Please select a report and a date range
+ Please select a report and a date range
+
+ src/app/features/reporting/reporting/select-report/select-report.component.html
+ 66
+
+
Enter a date range
Saisir une plage de dates
@@ -6336,23 +6561,39 @@
36
+
+ This data has been partially anonymized.
+ This data has been partially anonymized.
+
+ src/app/core/basic-datatypes/date/display-date/display-date.component.html
+ 11
+
+
+ src/app/core/basic-datatypes/date/edit-date/edit-date.component.html
+ 13
+
+
+ src/app/core/basic-datatypes/month/edit-month/edit-month.component.html
+ 13
+
+
Calculate
Calculer
Calculate the results for a report
src/app/features/reporting/reporting/select-report/select-report.component.html
- 65
+ 70
Download
Download
+ Button to download data
src/app/features/reporting/reporting/select-report/select-report.component.html
- 87
+ 93
- Button to download data
get signed agreement
@@ -6441,7 +6682,7 @@
Label
src/app/features/todos/model/todo.ts
- 47
+ 48
@@ -6450,7 +6691,7 @@
Description
src/app/features/todos/model/todo.ts
- 55
+ 57
@@ -6459,7 +6700,7 @@
Label
src/app/features/todos/model/todo.ts
- 68
+ 71
@@ -6468,7 +6709,7 @@
label for Todo entity property
src/app/features/todos/model/todo.ts
- 94
+ 100
@@ -6477,7 +6718,7 @@
repetition interval option
src/app/features/todos/model/todo.ts
- 97
+ 103
@@ -6486,7 +6727,7 @@
repetition interval option
src/app/features/todos/model/todo.ts
- 101
+ 107
@@ -6495,7 +6736,7 @@
label for Todo entity property
src/app/features/todos/model/todo.ts
- 110
+ 117
@@ -6678,7 +6919,7 @@
Filter-option for todos
src/app/features/todos/todo-list/todo-list.component.ts
- 129
+ 131
@@ -6687,7 +6928,7 @@
Filter-option for todos
src/app/features/todos/todo-list/todo-list.component.ts
- 99
+ 101
@@ -6696,7 +6937,7 @@
Filter-option for todos
src/app/features/todos/todo-list/todo-list.component.ts
- 104
+ 106
@@ -6705,7 +6946,7 @@
Filter-option for todos
src/app/features/todos/todo-list/todo-list.component.ts
- 109
+ 111
@@ -6713,7 +6954,7 @@
Any
src/app/features/todos/todo-list/todo-list.component.ts
- 112
+ 114
@@ -6721,7 +6962,7 @@
Tasks due
src/app/features/todos/todo-list/todo-list.component.ts
- 114
+ 116
@@ -6743,16 +6984,6 @@
dashboard showing open todos
subtitle
-
- Also show completed
- Also show completed
- also show entries that are inactive
- slider
-
- src/app/features/todos/todos-related-to-entity/todos-related-to-entity.component.html
- 17
-
-
Install App
Installer l'application
diff --git a/src/assets/locale/messages.it.xlf b/src/assets/locale/messages.it.xlf
index b1b0559183..1ad27c41f3 100644
--- a/src/assets/locale/messages.it.xlf
+++ b/src/assets/locale/messages.it.xlf
@@ -63,7 +63,7 @@
src/app/core/config/config-fix.ts
- 886
+ 859
@@ -104,7 +104,7 @@
Save
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 54
+ 45
@@ -113,7 +113,7 @@
Discard changes made to a form
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 63
+ 54
@@ -122,7 +122,7 @@
One of the stages while recording child-attendances
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 72
+ 63
@@ -131,7 +131,7 @@
One of the stages while recording child-attendances
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 73
+ 64
@@ -140,7 +140,7 @@
Exit from the current screen
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 94
+ 80
@@ -148,7 +148,7 @@
Do you want to save your progress before going back?
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 95
+ 81
@@ -199,6 +199,14 @@
214
+
+ Excluded some archived participants. Click to include.
+ Excluded some archived participants. Click to include.
+
+ src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
+ 58
+
+
Attendance completed.
Attendance completed.
@@ -207,7 +215,7 @@
Attendance completed
src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
- 107
+ 120
@@ -216,7 +224,7 @@
Open details of recorded event for review
src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
- 117
+ 130
@@ -225,7 +233,23 @@
Back to overview button after finishing a roll call
src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
- 127
+ 140
+
+
+
+ Also include archived participants?
+ Also include archived participants?
+
+ src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.ts
+ 271
+
+
+
+ This event has some participants who are "archived". We automatically remove them from the attendance list for you. Do you want to also include archived participants for this event?
+ This event has some participants who are "archived". We automatically remove them from the attendance list for you. Do you want to also include archived participants for this event?
+
+ src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.ts
+ 272
@@ -667,11 +691,11 @@
src/app/core/config/config-fix.ts
- 813
+ 786
src/app/core/config/config-fix.ts
- 891
+ 864
@@ -684,7 +708,7 @@
src/app/child-dev-project/notes/model/note.ts
- 144
+ 167
@@ -711,7 +735,7 @@
Label for date of the ASER results
src/app/child-dev-project/children/aser/model/aser.ts
- 30
+ 39
src/app/child-dev-project/children/educational-material/model/educational-material.ts
@@ -719,15 +743,15 @@
src/app/child-dev-project/children/health-checkup/model/health-check.ts
- 34
+ 45
src/app/child-dev-project/notes/model/note.ts
- 92
+ 99
src/app/features/historical-data/model/historical-entity-data.ts
- 13
+ 16
@@ -736,7 +760,7 @@
Label of the Hindi ASER result
src/app/child-dev-project/children/aser/model/aser.ts
- 35
+ 46
src/app/child-dev-project/schools/demo-school-generator.service.ts
@@ -749,7 +773,7 @@
Label of the Bengali ASER result
src/app/child-dev-project/children/aser/model/aser.ts
- 41
+ 52
src/app/child-dev-project/schools/demo-school-generator.service.ts
@@ -762,7 +786,7 @@
Label of the English ASER result
src/app/child-dev-project/children/aser/model/aser.ts
- 47
+ 58
src/app/child-dev-project/schools/demo-school-generator.service.ts
@@ -775,7 +799,7 @@
Label of the Math ASER result
src/app/child-dev-project/children/aser/model/aser.ts
- 53
+ 64
@@ -784,11 +808,11 @@
Label for the remarks of a ASER result
src/app/child-dev-project/children/aser/model/aser.ts
- 59
+ 71
src/app/core/config/config-fix.ts
- 1055
+ 1041
@@ -1029,7 +1053,7 @@
src/app/core/config/config-fix.ts
- 747
+ 731
@@ -1162,7 +1186,7 @@
src/app/features/todos/model/todo.ts
- 61
+ 64
@@ -1319,7 +1343,7 @@
src/app/core/config/config-fix.ts
- 488
+ 474
@@ -1334,20 +1358,20 @@
Height [cm]
Height [cm]
+ Label for height in cm of a health check
src/app/child-dev-project/children/health-checkup/model/health-check.ts
- 39
+ 52
- Label for height in cm of a health check
Weight [kg]
Weight [kg]
+ Label for weight in kg of a health check
src/app/child-dev-project/children/health-checkup/model/health-check.ts
- 47
+ 60
- Label for weight in kg of a health check
Participant
@@ -1364,7 +1388,7 @@
Label for the name of a child
src/app/child-dev-project/children/model/child.ts
- 46
+ 47
src/app/child-dev-project/schools/model/school.ts
@@ -1372,15 +1396,15 @@
src/app/core/config/config-fix.ts
- 447
+ 433
src/app/core/config/config-fix.ts
- 909
+ 882
src/app/core/config/config-fix.ts
- 1013
+ 999
@@ -1389,7 +1413,7 @@
Label for the project number of a child
src/app/child-dev-project/children/model/child.ts
- 54
+ 55
@@ -1398,7 +1422,7 @@
Short label for the project number
src/app/child-dev-project/children/model/child.ts
- 55
+ 56
@@ -1407,7 +1431,7 @@
Label for the date of birth of a child
src/app/child-dev-project/children/model/child.ts
- 61
+ 63
@@ -1416,7 +1440,7 @@
Short label for the date of birth
src/app/child-dev-project/children/model/child.ts
- 62
+ 64
@@ -1425,7 +1449,7 @@
Label for the gender of a child
src/app/child-dev-project/children/model/child.ts
- 68
+ 71
@@ -1434,7 +1458,7 @@
Label for the center of a child
src/app/child-dev-project/children/model/child.ts
- 76
+ 80
@@ -1443,7 +1467,7 @@
Label for the admission date of a child
src/app/child-dev-project/children/model/child.ts
- 81
+ 86
@@ -1452,11 +1476,11 @@
Label for the status of a child
src/app/child-dev-project/children/model/child.ts
- 86
+ 92
src/app/child-dev-project/notes/model/note.ts
- 151
+ 176
src/app/core/config/config-fix.ts
@@ -1464,11 +1488,7 @@
src/app/core/config/config-fix.ts
- 524
-
-
- src/app/core/config/config-fix.ts
- 779
+ 510
@@ -1477,7 +1497,7 @@
Label for the dropout date of a child
src/app/child-dev-project/children/model/child.ts
- 91
+ 97
@@ -1486,7 +1506,7 @@
Label for the type of dropout of a child
src/app/child-dev-project/children/model/child.ts
- 96
+ 103
@@ -1495,17 +1515,17 @@
Label for the remarks about a dropout of a child
src/app/child-dev-project/children/model/child.ts
- 101
+ 109
Photo
Photo
+ Label for the file field of a photo of a child
src/app/child-dev-project/children/model/child.ts
- 112
+ 120
- Label for the file field of a photo of a child
Phone Number
@@ -1513,11 +1533,11 @@
Label for the phone number of a child
src/app/child-dev-project/children/model/child.ts
- 118
+ 126
src/app/core/config/config-fix.ts
- 1041
+ 1027
@@ -1526,11 +1546,11 @@
Label for the child of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 13
+ 15
src/app/core/config/config-fix.ts
- 959
+ 945
@@ -1539,7 +1559,7 @@
Label for the school of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 23
+ 27
src/app/child-dev-project/schools/demo-school-generator.service.ts
@@ -1551,11 +1571,11 @@
src/app/core/config/config-fix.ts
- 463
+ 449
src/app/core/config/config-fix.ts
- 574
+ 551
@@ -1564,11 +1584,11 @@
Label for the class of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 32
+ 38
src/app/core/config/config-fix.ts
- 458
+ 444
@@ -1577,7 +1597,7 @@
Label for the start date of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 37
+ 43
src/app/core/entity-details/related-time-period-entities/time-period.ts
@@ -1585,7 +1605,7 @@
src/app/features/todos/model/todo.ts
- 54
+ 56
@@ -1594,7 +1614,7 @@
Description of the start date of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 38
+ 44
@@ -1603,7 +1623,7 @@
Label for the end date of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 44
+ 51
src/app/core/entity-details/related-time-period-entities/time-period.ts
@@ -1616,7 +1636,7 @@
Description of the end date of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 45
+ 52
@@ -1625,7 +1645,7 @@
Label for the percentage result of a relation
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 51
+ 59
@@ -1634,7 +1654,7 @@
Error assertValid failed
src/app/core/entity-details/related-time-period-entities/time-period.ts
- 63
+ 68
@@ -1643,7 +1663,7 @@
Error assertValid failed
src/app/core/entity-details/related-time-period-entities/time-period.ts
- 67
+ 72
@@ -2176,7 +2196,7 @@
Label for the children of a note
src/app/child-dev-project/notes/model/note.ts
- 76
+ 77
src/app/core/config/config-fix.ts
@@ -2184,11 +2204,7 @@
src/app/core/config/config-fix.ts
- 563
-
-
- src/app/core/config/config-fix.ts
- 960
+ 946
@@ -2197,11 +2213,11 @@
Label for the subject of a note
src/app/child-dev-project/notes/model/note.ts
- 97
+ 106
src/app/features/todos/model/todo.ts
- 42
+ 43
@@ -2214,7 +2230,7 @@
src/app/child-dev-project/notes/model/note.ts
- 100
+ 110
src/app/core/config/config-fix.ts
@@ -2227,7 +2243,7 @@
Label for the social worker(s) who created the note
src/app/child-dev-project/notes/model/note.ts
- 106
+ 117
@@ -2236,7 +2252,7 @@
Label for the category of a note
src/app/child-dev-project/notes/model/note.ts
- 114
+ 126
@@ -2245,11 +2261,11 @@
label for the related Entities
src/app/child-dev-project/notes/model/note.ts
- 132
+ 154
src/app/features/todos/model/todo.ts
- 83
+ 87
@@ -2270,7 +2286,7 @@
Download note details as CSV
src/app/child-dev-project/notes/note-details/note-details.component.html
- 90
+ 94
@@ -2283,6 +2299,15 @@
28
+
+ Select matching property
+ Select matching property
+
+ src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
+ 2,4
+
+ Label for property selection
+
Filter-option for notes
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 66
+ 65
@@ -2315,7 +2340,7 @@
Filter-option for notes
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 71
+ 70
src/app/child-dev-project/warning-level.ts
@@ -2327,19 +2352,11 @@
Tutti
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 76
+ 75
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 90
-
-
- src/app/core/config/config-fix.ts
- 566
-
-
- src/app/core/config/config-fix.ts
- 782
+ 89
src/app/core/filter/filters/filters.ts
@@ -2364,7 +2381,7 @@
Filter-option for notes
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 82
+ 81
@@ -2373,36 +2390,7 @@
Filter-option for notes
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 87
-
-
-
- Show entries where the end date is in the past
- Show entries where the end date is in the past
- Tooltip that will appear when hovered over the
- show-ended button
- Show ended tooltip
-
- src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
- 32
-
-
- src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
- 32
-
-
-
- Include inactive past records
- Include inactive past records
- also show entries that are inactive
- slider
-
- src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
- 34
-
-
- src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
- 34
+ 86
@@ -2412,7 +2400,7 @@
Label for the currently active status
src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
- 105
+ 97
@@ -2421,7 +2409,7 @@
Tooltip for the status of currently active or not
src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
- 108
+ 100
@@ -2430,7 +2418,7 @@
Indication for the currently active status of an entry
src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
- 111
+ 103
@@ -2439,7 +2427,7 @@
Indication for the currently inactive status of an entry
src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
- 112
+ 104
@@ -2760,7 +2748,7 @@
src/app/core/config/config-fix.ts
- 661
+ 645
@@ -2941,19 +2929,19 @@
src/app/core/config/config-fix.ts
- 495
+ 481
src/app/core/config/config-fix.ts
- 549
+ 535
Attachment
Attachment
- src/app/core/config/config-fix.ts
- 269
+ src/app/child-dev-project/notes/model/note.ts
+ 134
@@ -2961,7 +2949,7 @@
Site Settings
src/app/core/config/config-fix.ts
- 281
+ 267
@@ -2970,7 +2958,7 @@
Panel title
src/app/core/config/config-fix.ts
- 328
+ 314
@@ -2979,7 +2967,7 @@
Panel title
src/app/core/config/config-fix.ts
- 347
+ 333
@@ -2988,7 +2976,7 @@
Filename of markdown help page (make sure the filename you enter as a translation actually exists on the server!)
src/app/core/config/config-fix.ts
- 361
+ 347
@@ -2997,15 +2985,15 @@
Panel title
src/app/core/config/config-fix.ts
- 393
+ 379
src/app/core/config/config-fix.ts
- 585
+ 569
src/app/core/config/config-fix.ts
- 798
+ 771
@@ -3014,7 +3002,7 @@
Panel title
src/app/core/config/config-fix.ts
- 421
+ 407
@@ -3023,7 +3011,7 @@
Panel title
src/app/core/config/config-fix.ts
- 430
+ 416
@@ -3032,7 +3020,7 @@
Column label for age of child
src/app/core/config/config-fix.ts
- 452
+ 438
@@ -3041,7 +3029,7 @@
Column label for school attendance of child
src/app/core/config/config-fix.ts
- 470
+ 456
@@ -3050,7 +3038,7 @@
Column label for coaching attendance of child
src/app/core/config/config-fix.ts
- 479
+ 465
@@ -3059,11 +3047,11 @@
Translated name of default column group
src/app/core/config/config-fix.ts
- 494
+ 480
src/app/core/config/config-fix.ts
- 498
+ 484
@@ -3072,7 +3060,7 @@
Column group name
src/app/core/config/config-fix.ts
- 511
+ 497
@@ -3081,41 +3069,11 @@
Column group name
src/app/core/config/config-fix.ts
- 534
-
-
- src/app/core/config/config-fix.ts
- 683
-
-
-
- Active
- Active
- Active children filter label - true case
-
- src/app/core/config/config-fix.ts
- 564
-
-
- src/app/core/config/config-fix.ts
- 780
-
-
-
- Inactive
- Inactive
- Active children filter label - false case
-
- src/app/core/config/config-fix.ts
- 565
+ 520
src/app/core/config/config-fix.ts
- 781
-
-
- src/app/core/entity/model/entity.ts
- 194
+ 667
@@ -3124,7 +3082,7 @@
Header for form section
src/app/core/config/config-fix.ts
- 613
+ 597
@@ -3133,7 +3091,7 @@
Header for form section
src/app/core/config/config-fix.ts
- 614
+ 598
@@ -3142,7 +3100,7 @@
Header for form section
src/app/core/config/config-fix.ts
- 615
+ 599
@@ -3151,7 +3109,7 @@
Panel title
src/app/core/config/config-fix.ts
- 622
+ 606
@@ -3160,7 +3118,7 @@
Title inside a panel
src/app/core/config/config-fix.ts
- 625
+ 609
@@ -3169,7 +3127,7 @@
Title inside a panel
src/app/core/config/config-fix.ts
- 645
+ 629
@@ -3178,7 +3136,7 @@
Child details section title
src/app/core/config/config-fix.ts
- 649
+ 633
@@ -3187,7 +3145,7 @@
Panel title
src/app/core/config/config-fix.ts
- 670
+ 654
@@ -3196,7 +3154,7 @@
description section
src/app/core/config/config-fix.ts
- 692
+ 676
@@ -3205,7 +3163,7 @@
Title inside a panel
src/app/core/config/config-fix.ts
- 699
+ 683
@@ -3214,7 +3172,7 @@
Panel title
src/app/core/config/config-fix.ts
- 705
+ 689
@@ -3223,7 +3181,7 @@
Panel title
src/app/core/config/config-fix.ts
- 730
+ 714
@@ -3241,7 +3199,7 @@
Panel title
src/app/core/config/config-fix.ts
- 828
+ 801
@@ -3250,7 +3208,7 @@
Name of a report
src/app/core/config/config-fix.ts
- 843
+ 816
@@ -3259,7 +3217,7 @@
Label of report query
src/app/core/config/config-fix.ts
- 847
+ 820
@@ -3268,7 +3226,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 852
+ 825
@@ -3277,7 +3235,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 855
+ 828
@@ -3286,7 +3244,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 859
+ 832
@@ -3295,7 +3253,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 864
+ 837
@@ -3304,7 +3262,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 868
+ 841
@@ -3313,7 +3271,7 @@
Label for report query
src/app/core/config/config-fix.ts
- 873
+ 846
@@ -3322,7 +3280,7 @@
Name of a report
src/app/core/config/config-fix.ts
- 881
+ 854
@@ -3331,7 +3289,7 @@
Name of a report
src/app/core/config/config-fix.ts
- 898
+ 871
@@ -3373,13 +3331,21 @@
1
+
+ Add new option
+ Add new option
+
+ src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.html
+ 32
+
+
Close
Chiudere
Close popup
src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.html
- 29
+ 46
src/app/core/filter/filter-overlay/filter-overlay.component.html
@@ -3392,7 +3358,7 @@
Name of a column of a report
src/app/core/config/config-fix.ts
- 913
+ 899
@@ -3401,7 +3367,7 @@
Name of a column of a report
src/app/core/config/config-fix.ts
- 917
+ 903
@@ -3410,7 +3376,7 @@
Name of a column of a report
src/app/core/config/config-fix.ts
- 921
+ 907
@@ -3419,7 +3385,7 @@
Name of a column of a report
src/app/core/config/config-fix.ts
- 925
+ 911
@@ -3428,7 +3394,7 @@
Name of a report
src/app/core/config/config-fix.ts
- 935
+ 921
@@ -3446,11 +3412,11 @@
Label for the address of a child
src/app/core/config/config-fix.ts
- 966
+ 952
src/app/core/config/config-fix.ts
- 1034
+ 1020
@@ -3459,7 +3425,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 973
+ 959
@@ -3468,7 +3434,7 @@
Label for the religion of a child
src/app/core/config/config-fix.ts
- 980
+ 966
@@ -3477,7 +3443,7 @@
Label for the mother tongue of a child
src/app/core/config/config-fix.ts
- 987
+ 973
@@ -3486,7 +3452,7 @@
Tooltip description for the mother tongue of a child
src/app/core/config/config-fix.ts
- 988
+ 974
@@ -3495,7 +3461,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 995
+ 981
@@ -3504,7 +3470,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1002
+ 988
@@ -3512,11 +3478,11 @@
Private School
src/app/core/config/config-fix.ts
- 382
+ 368
src/app/core/config/config-fix.ts
- 1020
+ 1006
@@ -3525,7 +3491,7 @@
Label for the language of a school
src/app/core/config/config-fix.ts
- 1027
+ 1013
@@ -3534,7 +3500,7 @@
Label for the timing of a school
src/app/core/config/config-fix.ts
- 1048
+ 1034
@@ -3543,7 +3509,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1067
+ 1053
@@ -3552,7 +3518,7 @@
Description for a child attribute
src/app/core/config/config-fix.ts
- 1068
+ 1054
@@ -3561,7 +3527,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1076
+ 1062
@@ -3570,7 +3536,7 @@
Description for a child attribute
src/app/core/config/config-fix.ts
- 1077
+ 1063
@@ -3579,7 +3545,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1085
+ 1071
@@ -3588,7 +3554,7 @@
Description for a child attribute
src/app/core/config/config-fix.ts
- 1086
+ 1072
@@ -3597,7 +3563,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1094
+ 1080
@@ -3606,7 +3572,7 @@
Description for a child attribute
src/app/core/config/config-fix.ts
- 1095
+ 1081
@@ -3615,7 +3581,7 @@
Label for a child attribute
src/app/core/config/config-fix.ts
- 1103
+ 1089
@@ -3624,7 +3590,7 @@
Description for a child attribute
src/app/core/config/config-fix.ts
- 1104
+ 1090
@@ -3633,7 +3599,7 @@
Label of user phone
src/app/core/config/config-fix.ts
- 1115
+ 1101
@@ -3824,6 +3790,92 @@
28
+
+ Archive
+ Archive
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 69
+
+ entity context menu
+
+
+ Mark the record as inactive, hiding it from lists by default while keeping the data.
+ Mark the record as inactive, hiding it from lists by default while keeping the data.
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 70
+
+ entity context menu tooltip
+
+
+ Anonymize
+ Anonymize
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 77
+
+ entity context menu
+
+
+ Remove all personal data and keep an archived basic record for statistical reporting.
+ Remove all personal data and keep an archived basic record for statistical reporting.
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 78
+
+ entity context menu tooltip
+
+
+ Delete
+ Elimina
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 85
+
+ entity context menu
+
+
+ Remove the record completely from the database.
+ Remove the record completely from the database.
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 86
+
+ entity context menu tooltip
+
+
+ Archived
+ Archived
+
+ src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
+ 6
+
+
+
+ Anonymized & Archived
+ Anonymized & Archived
+
+ src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
+ 8
+
+
+
+ This record has been anonymized. Details containing personal information have been deleted and cannot be restored. For statistical reporting, this basic record has been kept.
+ This record has been anonymized. Details containing personal information have been deleted and cannot be restored. For statistical reporting, this basic record has been kept.
+
+ src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
+ 13,17
+
+
+
+ This record is archived and will be be hidden from lists and select options by default.
+ This record is archived and will be be hidden from lists and select options by default.
+
+ src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
+ 19,22
+
+
Adding new
Nuovo
@@ -3834,26 +3886,13 @@
27
-
- Delete
- Elimina
- Generic delete button
-
- src/app/core/entity-details/entity-details/entity-details.component.html
- 58
-
-
- src/app/core/form-dialog/dialog-buttons/dialog-buttons.component.html
- 61
-
-
Save the new record to create it before accessing other details
Save the new record to create it before accessing other details
Tooltip explaining disabled sections when creating new entity
src/app/core/entity-details/entity-details/entity-details.component.html
- 74
+ 51
@@ -3981,7 +4020,7 @@
Examples of things to filter
src/app/core/entity-list/entity-list/entity-list.component.html
- 104
+ 106
@@ -3990,7 +4029,7 @@
Add a new entity to a list of multiple entities
src/app/core/entity-list/entity-list/entity-list.component.html
- 154
+ 158
@@ -3999,8 +4038,26 @@
Show filter options popup for list
src/app/core/entity-list/entity-list/entity-list.component.html
- 166
+ 170
+
+
+
+ Download all data (.csv)
+ Download all data (.csv)
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 189
+ Download list contents as CSV
+
+
+ Download current (.csv)
+ Download current (.csv)
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 207
+
+ Download list contents as CSV
Filter
@@ -4009,24 +4066,56 @@
Filter placeholder
src/app/core/entity-list/entity-list/entity-list.component.html
- 98
+ 100
-
- Download CSV
- Scarica CSV
- Download list contents as CSV
+
+ Import from file
+ Import from file
src/app/core/entity-list/entity-list/entity-list.component.html
- 185
+ 223
-
- Import from file
- Import from file
+
+ Select multiple records for bulk actions like duplicating or deleting
+ Select multiple records for bulk actions like duplicating or deleting
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 229
+
+
+
+ Bulk Actions
+ Bulk Actions
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 237
+
+
+
+ Select rows to clone
+ Select rows to clone
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 252
+
+
+
+ Duplicate
+ Duplicate
src/app/core/entity-list/entity-list/entity-list.component.html
- 201
+ 256,258
+
+ bulk action button
+
+
+ Cancel
+ Cancella
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 260,262
@@ -4092,7 +4181,7 @@
Tooltip for the disabled age field
src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.component.html
- 28
+ 34
@@ -4101,7 +4190,7 @@
Placeholder for the input that displays the age
src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.component.html
- 21
+ 27
@@ -4173,6 +4262,16 @@
51
+
+ Include archived records
+ Include archived records
+ also show entries that are archived
+ slider
+
+ src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.html
+ 160
+
+
in total
@@ -4205,53 +4304,184 @@
59
+
+ " "
+ " "
+ Entity action confirmation message
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 35
+
+
Delete?
Elimina?
Delete confirmation title
- src/app/core/entity/entity-remove.service.ts
- 78
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 76
-
- Are you sure you want to delete this record?
- Are you sure you want to delete this record?
+
+
+ This will remove the data permanently as if it never existed. This cannot be undone. Statistical reports (also for past time periods) will change and not include this record anymore.
+
+ If you have not just created this record accidentally, deleting this is probably not what you want to do. If the record represents something that actually happened in your work, consider to use "anonymize" or just "archive" instead, so that you will not lose your documentation for reports.
+
+ Are you sure you want to delete this record?
+
+ This will remove the data permanently as if it never existed. This cannot be undone. Statistical reports (also for past time periods) will change and not include this record anymore.
+
+ If you have not just created this record accidentally, deleting this is probably not what you want to do. If the record represents something that actually happened in your work, consider to use "anonymize" or just "archive" instead, so that you will not lose your documentation for reports.
+
+ Are you sure you want to delete this record?
+ Delete confirmation dialog
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 77
+
+
+
+ Processing ...
+ Processing ...
- src/app/core/entity/entity-remove.service.ts
- 81
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 89
- Delete confirmation text
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 145
+
+ Entity action progress dialog
-
- Deleted Entity
- Entità eliminata
- Deleted Entity information
+
+ Related records may still contain personal data
+ Related records may still contain personal data
- src/app/core/entity/entity-remove.service.ts
- 93
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 96
+
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 152
+
+ post-delete related PII warning title
+
+
+ Some related records (e.g. notes) may still contain personal data in their text. We have automatically deleted all records that are linked to ONLY this .
+ However, there are some records that are linked to multiple records. We have not deleted these, so that you will not lose relevant data. Please review them manually to ensure all sensitive information is removed, if required (e.g. by looking through the linked notes and editing a note's text).
+ Some related records (e.g. notes) may still contain personal data in their text. We have automatically deleted all records that are linked to ONLY this .
+ However, there are some records that are linked to multiple records. We have not deleted these, so that you will not lose relevant data. Please review them manually to ensure all sensitive information is removed, if required (e.g. by looking through the linked notes and editing a note's text).
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 97,100
+
+ post-delete related PII warning dialog
+
+
+ Deleted
+ Deleted
+ Entity action confirmation message verb
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 114
+
+
+
+ Anonymize?
+ Anonymize?
+ Anonymize confirmation dialog
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 132
+
+
+
+
+ This will remove all personal information (PII) permanently and keep only a basic record for statistical reports. Details that are removed during anonymization cannot be recovered.
+
+ If this has only become inactive and you want to keep all details about the record, consider to use "archive" instead.
+
+ Are you sure you want to anonymize this record?
+
+ This will remove all personal information (PII) permanently and keep only a basic record for statistical reports. Details that are removed during anonymization cannot be recovered.
+
+ If this has only become inactive and you want to keep all details about the record, consider to use "archive" instead.
+
+ Are you sure you want to anonymize this record?
+ Anonymize confirmation dialog
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 133
+
+
+
+ Some related records (e.g. notes) may still contain personal data in their text. We have automatically anonymized all records that are linked to ONLY this .
+ However, there are some records that are linked to multiple records. We have not anonymized these, so that you will not lose relevant data. Please review them manually to ensure all sensitive information is removed (e.g. by looking through the linked notes and editing a note's text).
+ Some related records (e.g. notes) may still contain personal data in their text. We have automatically anonymized all records that are linked to ONLY this .
+ However, there are some records that are linked to multiple records. We have not anonymized these, so that you will not lose relevant data. Please review them manually to ensure all sensitive information is removed (e.g. by looking through the linked notes and editing a note's text).
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 153,156
+
+ post-anonymize related PII warning dialog
+
+
+ Anonymized
+ Anonymized
+ Entity action confirmation message verb
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 163
+
+
+
+ Archived
+ Archived
+ Entity action confirmation message verb
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 180
+
+
+
+ Reactivated
+ Reactivated
+ Entity action confirmation message verb
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 196
Undo
Annullare
- Undo deleting an entity
+ Undo an entity action
- src/app/core/entity/entity-remove.service.ts
- 97
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 41
src/app/core/import/import-confirm-summary/import-confirm-summary.component.ts
61
-
- Ticking this box will archive the record. No data will be lost but the record will be hidden.
- Ticking this box will archive the record. No data will be lost but the record will be hidden.
- Description of checkbox
+
+ Reverting changes ...
+ Reverting changes ...
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 50
+
+ Undo entity action progress dialog
+
+
+ [anonymized ]
+ [anonymized ]
+ Entity.toString fallback for anonymized record
src/app/core/entity/model/entity.ts
- 195
+ 316
@@ -4412,7 +4642,7 @@
Are you sure that you want to delete the option " "?
src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.ts
- 71
+ 73
@@ -4424,7 +4654,7 @@
)"/> records. If deleted, the records will not be lost but specially marked.
src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.ts
- 73
+ 75
@@ -4432,7 +4662,7 @@
Delete option
src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.ts
- 78
+ 80
@@ -4441,7 +4671,7 @@
Discard changes header
src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
- 62
+ 63
@@ -4450,7 +4680,7 @@
Discard changes message
src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
- 63
+ 64
@@ -5137,7 +5367,7 @@ Please try again. If the problem persists contact Aam Digital support.
Load changes?
src/app/core/common-components/entity-form/entity-form/entity-form.component.ts
- 110
+ 111
@@ -5145,7 +5375,7 @@ Please try again. If the problem persists contact Aam Digital support.
Local changes are in conflict with updated values synced from the server. Do you want the local changes to be overwritten with the latest values?
src/app/core/common-components/entity-form/entity-form/entity-form.component.ts
- 111
+ 112
@@ -5244,7 +5474,7 @@ Please try again. If the problem persists contact Aam Digital support.
Label of username
src/app/core/user/user.ts
- 38
+ 39
@@ -5254,7 +5484,7 @@ Please try again. If the problem persists contact Aam Digital support.
Error message when trying to change the username
src/app/core/user/user.ts
- 46
+ 47
@@ -5676,7 +5906,7 @@ Please try again. If the problem persists contact Aam Digital support.
src/app/features/file/edit-photo/edit-photo.component.html
- 17
+ 22
@@ -5685,7 +5915,7 @@ Please try again. If the problem persists contact Aam Digital support.
Message for user
src/app/features/file/edit-file/edit-file.component.ts
- 132
+ 134
@@ -5768,6 +5998,10 @@ Please try again. If the problem persists contact Aam Digital support.
src/app/core/basic-datatypes/discrete/discrete-import-config/discrete-import-config.component.html
32
+
+ src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
+ 21
+
not at all
@@ -5907,7 +6141,7 @@ Please try again. If the problem persists contact Aam Digital support.
help text in map popup
src/app/features/location/edit-location/edit-location.component.ts
- 118
+ 119
@@ -6173,7 +6407,7 @@ Please try again. If the problem persists contact Aam Digital support.
src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
- 18
+ 24
src/app/features/dashboard-widgets/progress-dashboard-widget/edit-progress-dashboard/edit-progress-dashboard.component.html
@@ -6204,27 +6438,10 @@ Please try again. If the problem persists contact Aam Digital support.
86
-
- Select matching property
- Select matching property
- Label for property selection
-
- src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
- 2
-
-
Select which property of the target entity is matching with the values of this column. E.g. if your column contains names of children then select 'Name'.
Select which property of the target entity is matching with the values of this column. E.g. if your column contains names of children then select 'Name'.
import - value mapping (entity) - help text
-
- src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
- 9
-
-
-
- Save & Close
- Save & Close
src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
15
@@ -6533,6 +6750,14 @@ Please try again. If the problem persists contact Aam Digital support.
15
+
+ Please select a report and a date range
+ Please select a report and a date range
+
+ src/app/features/reporting/reporting/select-report/select-report.component.html
+ 66
+
+
Enter a date range
Inserire un intervallo di date
@@ -6572,23 +6797,39 @@ Please try again. If the problem persists contact Aam Digital support.
36
+
+ This data has been partially anonymized.
+ This data has been partially anonymized.
+
+ src/app/core/basic-datatypes/date/display-date/display-date.component.html
+ 11
+
+
+ src/app/core/basic-datatypes/date/edit-date/edit-date.component.html
+ 13
+
+
+ src/app/core/basic-datatypes/month/edit-month/edit-month.component.html
+ 13
+
+
Calculate
Calcolare
Calculate the results for a report
src/app/features/reporting/reporting/select-report/select-report.component.html
- 65
+ 70
Download
Scaricare
+ Button to download data
src/app/features/reporting/reporting/select-report/select-report.component.html
- 87
+ 93
- Button to download data
get signed agreement
@@ -6677,7 +6918,7 @@ Please try again. If the problem persists contact Aam Digital support.
Label
src/app/features/todos/model/todo.ts
- 47
+ 48
@@ -6686,7 +6927,7 @@ Please try again. If the problem persists contact Aam Digital support.
Description
src/app/features/todos/model/todo.ts
- 55
+ 57
@@ -6695,7 +6936,7 @@ Please try again. If the problem persists contact Aam Digital support.
Label
src/app/features/todos/model/todo.ts
- 68
+ 71
@@ -6704,7 +6945,7 @@ Please try again. If the problem persists contact Aam Digital support.
label for Todo entity property
src/app/features/todos/model/todo.ts
- 94
+ 100
@@ -6713,7 +6954,7 @@ Please try again. If the problem persists contact Aam Digital support.
repetition interval option
src/app/features/todos/model/todo.ts
- 97
+ 103
@@ -6722,7 +6963,7 @@ Please try again. If the problem persists contact Aam Digital support.
repetition interval option
src/app/features/todos/model/todo.ts
- 101
+ 107
@@ -6731,7 +6972,7 @@ Please try again. If the problem persists contact Aam Digital support.
label for Todo entity property
src/app/features/todos/model/todo.ts
- 110
+ 117
@@ -6914,7 +7155,7 @@ Please try again. If the problem persists contact Aam Digital support.
Filter-option for todos
src/app/features/todos/todo-list/todo-list.component.ts
- 129
+ 131
@@ -6923,7 +7164,7 @@ Please try again. If the problem persists contact Aam Digital support.
Filter-option for todos
src/app/features/todos/todo-list/todo-list.component.ts
- 99
+ 101
@@ -6932,7 +7173,7 @@ Please try again. If the problem persists contact Aam Digital support.
Filter-option for todos
src/app/features/todos/todo-list/todo-list.component.ts
- 104
+ 106
@@ -6941,7 +7182,7 @@ Please try again. If the problem persists contact Aam Digital support.
Filter-option for todos
src/app/features/todos/todo-list/todo-list.component.ts
- 109
+ 111
@@ -6949,7 +7190,7 @@ Please try again. If the problem persists contact Aam Digital support.
Any
src/app/features/todos/todo-list/todo-list.component.ts
- 112
+ 114
@@ -6957,7 +7198,7 @@ Please try again. If the problem persists contact Aam Digital support.
Tasks due
src/app/features/todos/todo-list/todo-list.component.ts
- 114
+ 116
@@ -6979,16 +7220,6 @@ Please try again. If the problem persists contact Aam Digital support.
dashboard showing open todos
subtitle
-
- Also show completed
- Also show completed
- also show entries that are inactive
- slider
-
- src/app/features/todos/todos-related-to-entity/todos-related-to-entity.component.html
- 17
-
-
-
-
-
-
Aam Digital
-
... is loading for the first time.
-
- This may take a few seconds or even minutes depending on your internet
- connection.
-
-
- Browser Details:
-
-
-
-
-
-
+
+
+
Aam Digital
+
... is loading for the first time.
+
+ This may take a few seconds or even minutes depending on your internet
+ connection.
+
+
+ Browser Details:
+
+
+
+
+
diff --git a/src/assets/locale/messages.xlf b/src/assets/locale/messages.xlf
index 6af5b1aef6..c90fd19047 100644
--- a/src/assets/locale/messages.xlf
+++ b/src/assets/locale/messages.xlf
@@ -56,7 +56,7 @@
src/app/core/config/config-fix.ts
- 886
+ 859
Events of an attendance
@@ -105,14 +105,14 @@
Save
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 54
+ 45
Discard
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 63
+ 54
Discard changes made to a form
@@ -120,7 +120,7 @@
Select Event
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 72
+ 63
One of the stages while recording child-attendances
@@ -128,7 +128,7 @@
Record Attendance
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 73
+ 64
One of the stages while recording child-attendances
@@ -136,7 +136,7 @@
Exit
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 94
+ 80
Exit from the current screen
@@ -144,7 +144,7 @@
Do you want to save your progress before going back?
src/app/child-dev-project/attendance/add-day-attendance/add-day-attendance.component.ts
- 95
+ 81
@@ -190,11 +190,18 @@
Alert when selected date is invalid
+
+ Excluded some archived participants. Click to include.
+
+ src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
+ 58
+
+
Attendance completed.
src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
- 107,109
+ 120,122
shows when the user has registered the attendance
of all children
@@ -204,7 +211,7 @@
Review Details
src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
- 117,119
+ 130,132
Open details of recorded event for review
@@ -212,10 +219,24 @@
Back to Overview
src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.html
- 127,129
+ 140,142
Back to overview button after finishing a roll call
+
+ Also include archived participants?
+
+ src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.ts
+ 271
+
+
+
+ This event has some participants who are "archived". We automatically remove them from the attendance list for you. Do you want to also include archived participants for this event?
+
+ src/app/child-dev-project/attendance/add-day-attendance/roll-call/roll-call.component.ts
+ 272
+
+
attended events
@@ -623,11 +644,11 @@
src/app/core/config/config-fix.ts
- 813
+ 786
src/app/core/config/config-fix.ts
- 891
+ 864
Label for the participants of a recurring activity
@@ -639,7 +660,7 @@
src/app/child-dev-project/notes/model/note.ts
- 144
+ 167
Label for the linked schools of a recurring activity
@@ -663,7 +684,7 @@
Date
src/app/child-dev-project/children/aser/model/aser.ts
- 30
+ 39
src/app/child-dev-project/children/educational-material/model/educational-material.ts
@@ -671,15 +692,15 @@
src/app/child-dev-project/children/health-checkup/model/health-check.ts
- 34
+ 45
src/app/child-dev-project/notes/model/note.ts
- 92
+ 99
src/app/features/historical-data/model/historical-entity-data.ts
- 13
+ 16
Label for date of the ASER results
@@ -687,7 +708,7 @@
Hindi
src/app/child-dev-project/children/aser/model/aser.ts
- 35
+ 46
src/app/child-dev-project/schools/demo-school-generator.service.ts
@@ -699,7 +720,7 @@
Bengali
src/app/child-dev-project/children/aser/model/aser.ts
- 41
+ 52
src/app/child-dev-project/schools/demo-school-generator.service.ts
@@ -711,7 +732,7 @@
English
src/app/child-dev-project/children/aser/model/aser.ts
- 47
+ 58
src/app/child-dev-project/schools/demo-school-generator.service.ts
@@ -723,7 +744,7 @@
Math
src/app/child-dev-project/children/aser/model/aser.ts
- 53
+ 64
Label of the Math ASER result
@@ -731,11 +752,11 @@
Remarks
src/app/child-dev-project/children/aser/model/aser.ts
- 59
+ 71
src/app/core/config/config-fix.ts
- 1055
+ 1041
Label for the remarks of a ASER result
@@ -836,7 +857,7 @@
src/app/core/config/config-fix.ts
- 747
+ 731
Child status
@@ -956,7 +977,7 @@
src/app/features/todos/model/todo.ts
- 61
+ 64
An additional description for the borrowed material
@@ -1149,7 +1170,7 @@
src/app/core/config/config-fix.ts
- 488
+ 474
Table header, Short for Body Mass Index
@@ -1165,7 +1186,7 @@
Height [cm]
src/app/child-dev-project/children/health-checkup/model/health-check.ts
- 39
+ 52
Label for height in cm of a health check
@@ -1173,7 +1194,7 @@
Weight [kg]
src/app/child-dev-project/children/health-checkup/model/health-check.ts
- 47
+ 60
Label for weight in kg of a health check
@@ -1189,7 +1210,7 @@
Name
src/app/child-dev-project/children/model/child.ts
- 46
+ 47
src/app/child-dev-project/schools/model/school.ts
@@ -1197,15 +1218,15 @@
src/app/core/config/config-fix.ts
- 447
+ 433
src/app/core/config/config-fix.ts
- 909
+ 882
src/app/core/config/config-fix.ts
- 1013
+ 999
Label for the name of a child
@@ -1213,7 +1234,7 @@
Project Number
src/app/child-dev-project/children/model/child.ts
- 54
+ 55
Label for the project number of a child
@@ -1221,7 +1242,7 @@
PN
src/app/child-dev-project/children/model/child.ts
- 55
+ 56
Short label for the project number
@@ -1229,7 +1250,7 @@
Date of birth
src/app/child-dev-project/children/model/child.ts
- 61
+ 63
Label for the date of birth of a child
@@ -1237,7 +1258,7 @@
DoB
src/app/child-dev-project/children/model/child.ts
- 62
+ 64
Short label for the date of birth
@@ -1245,7 +1266,7 @@
Gender
src/app/child-dev-project/children/model/child.ts
- 68
+ 71
Label for the gender of a child
@@ -1253,7 +1274,7 @@
Center
src/app/child-dev-project/children/model/child.ts
- 76
+ 80
Label for the center of a child
@@ -1261,7 +1282,7 @@
Admission
src/app/child-dev-project/children/model/child.ts
- 81
+ 86
Label for the admission date of a child
@@ -1269,11 +1290,11 @@
Status
src/app/child-dev-project/children/model/child.ts
- 86
+ 92
src/app/child-dev-project/notes/model/note.ts
- 151
+ 176
src/app/core/config/config-fix.ts
@@ -1281,11 +1302,7 @@
src/app/core/config/config-fix.ts
- 524
-
-
- src/app/core/config/config-fix.ts
- 779
+ 510
Label for the status of a child
@@ -1293,7 +1310,7 @@
Dropout Date
src/app/child-dev-project/children/model/child.ts
- 91
+ 97
Label for the dropout date of a child
@@ -1301,7 +1318,7 @@
Dropout Type
src/app/child-dev-project/children/model/child.ts
- 96
+ 103
Label for the type of dropout of a child
@@ -1309,7 +1326,7 @@
Dropout remarks
src/app/child-dev-project/children/model/child.ts
- 101
+ 109
Label for the remarks about a dropout of a child
@@ -1317,7 +1334,7 @@
Photo
src/app/child-dev-project/children/model/child.ts
- 112
+ 120
Label for the file field of a photo of a child
@@ -1325,11 +1342,11 @@
Phone Number
src/app/child-dev-project/children/model/child.ts
- 118
+ 126
src/app/core/config/config-fix.ts
- 1041
+ 1027
Label for the phone number of a child
@@ -1337,11 +1354,11 @@
Child
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 13
+ 15
src/app/core/config/config-fix.ts
- 959
+ 945
Label for the child of a relation
@@ -1349,7 +1366,7 @@
School
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 23
+ 27
src/app/child-dev-project/schools/demo-school-generator.service.ts
@@ -1361,11 +1378,11 @@
src/app/core/config/config-fix.ts
- 463
+ 449
src/app/core/config/config-fix.ts
- 574
+ 551
Label for the school of a relation
@@ -1373,11 +1390,11 @@
Class
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 32
+ 38
src/app/core/config/config-fix.ts
- 458
+ 444
Label for the class of a relation
@@ -1385,7 +1402,7 @@
Start date
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 37
+ 43
src/app/core/entity-details/related-time-period-entities/time-period.ts
@@ -1393,7 +1410,7 @@
src/app/features/todos/model/todo.ts
- 54
+ 56
Label for the start date of a relation
@@ -1401,7 +1418,7 @@
The date a child joins a school
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 38
+ 44
Description of the start date of a relation
@@ -1409,7 +1426,7 @@
End date
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 44
+ 51
src/app/core/entity-details/related-time-period-entities/time-period.ts
@@ -1421,7 +1438,7 @@
The date of a child leaving the school
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 45
+ 52
Description of the end date of a relation
@@ -1429,7 +1446,7 @@
Result
src/app/child-dev-project/children/model/childSchoolRelation.ts
- 51
+ 59
Label for the percentage result of a relation
@@ -1877,7 +1894,7 @@
src/app/child-dev-project/notes/model/note.ts
- 100
+ 110
src/app/core/config/config-fix.ts
@@ -1889,7 +1906,7 @@
Children
src/app/child-dev-project/notes/model/note.ts
- 76
+ 77
src/app/core/config/config-fix.ts
@@ -1897,11 +1914,7 @@
src/app/core/config/config-fix.ts
- 563
-
-
- src/app/core/config/config-fix.ts
- 960
+ 946
Label for the children of a note
@@ -1909,11 +1922,11 @@
Subject
src/app/child-dev-project/notes/model/note.ts
- 97
+ 106
src/app/features/todos/model/todo.ts
- 42
+ 43
Label for the subject of a note
@@ -1921,7 +1934,7 @@
SW
src/app/child-dev-project/notes/model/note.ts
- 106
+ 117
Label for the social worker(s) who created the note
@@ -1929,19 +1942,26 @@
Category
src/app/child-dev-project/notes/model/note.ts
- 114
+ 126
Label for the category of a note
+
+ Attachment
+
+ src/app/child-dev-project/notes/model/note.ts
+ 134
+
+
Related Records
src/app/child-dev-project/notes/model/note.ts
- 132
+ 154
src/app/features/todos/model/todo.ts
- 83
+ 87
label for the related Entities
@@ -1949,7 +1969,7 @@
Download details
src/app/child-dev-project/notes/note-details/note-details.component.html
- 90
+ 94
Download note details as CSV
@@ -1970,7 +1990,7 @@
Urgent
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 66
+ 65
Filter-option for notes
@@ -1978,7 +1998,7 @@
Needs Follow-Up
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 71
+ 70
src/app/child-dev-project/warning-level.ts
@@ -1990,19 +2010,11 @@
All
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 76
+ 75
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 90
-
-
- src/app/core/config/config-fix.ts
- 566
-
-
- src/app/core/config/config-fix.ts
- 782
+ 89
src/app/core/filter/filters/filters.ts
@@ -2025,7 +2037,7 @@
This Week
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 82
+ 81
Filter-option for notes
@@ -2033,7 +2045,7 @@
Since Last Week
src/app/child-dev-project/notes/notes-manager/notes-manager.component.ts
- 87
+ 86
Filter-option for notes
@@ -2140,11 +2152,18 @@
title of dropdown options popup dialog
+
+ Add new option
+
+ src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.html
+ 32
+
+
Close
src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.html
- 29
+ 46
src/app/core/filter/filter-overlay/filter-overlay.component.html
@@ -2156,7 +2175,7 @@
Are you sure that you want to delete the option " "?
src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.ts
- 71
+ 73
@@ -2165,21 +2184,21 @@
)"/> records. If deleted, the records will not be lost but specially marked.
src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.ts
- 73,75
+ 75,77
Delete option
src/app/core/basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component.ts
- 78
+ 80
Age
src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.component.html
- 21
+ 27
Placeholder for the input that displays the age
@@ -2187,7 +2206,7 @@
This field is read-only. Edit Date of Birth to change age. Select Jan 1st if you only know the year of birth.
src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.component.html
- 28
+ 34
Tooltip for the disabled age field
@@ -2235,6 +2254,10 @@
src/app/core/basic-datatypes/discrete/discrete-import-config/discrete-import-config.component.html
32,34
+
+ src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
+ 21,23
+
Cancel
@@ -2248,7 +2271,7 @@
src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
- 18
+ 24
src/app/features/dashboard-widgets/progress-dashboard-widget/edit-progress-dashboard/edit-progress-dashboard.component.html
@@ -2361,6 +2384,21 @@
Date selection
+
+ This data has been partially anonymized.
+
+ src/app/core/basic-datatypes/date/display-date/display-date.component.html
+ 11
+
+
+ src/app/core/basic-datatypes/date/edit-date/edit-date.component.html
+ 13
+
+
+ src/app/core/basic-datatypes/month/edit-month/edit-month.component.html
+ 13
+
+
Imported values
@@ -2404,11 +2442,11 @@
context Add User(s)
Placeholder for input to add entities
-
- Select matching property
+
+ Select matching property
src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
- 2
+ 2,4
Label for property selection
@@ -2416,17 +2454,10 @@
Select which property of the target entity is matching with the values of this column. E.g. if your column contains names of children then select 'Name'.
src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
- 9
+ 15
import - value mapping (entity) - help text
-
- Save & Close
-
- src/app/core/basic-datatypes/entity/entity-import-config/entity-import-config.component.html
- 15,17
-
-
Ignore for import?
@@ -2468,7 +2499,7 @@
Discard Changes?
src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
- 62
+ 63
Discard changes header
@@ -2476,7 +2507,7 @@
You have unsaved changes. Do you really want to leave this page? All unsaved changes will be lost.
src/app/core/common-components/confirmation-dialog/confirmation-dialog.service.ts
- 63
+ 64
Discard changes message
@@ -2647,14 +2678,14 @@
Load changes?
src/app/core/common-components/entity-form/entity-form/entity-form.component.ts
- 110
+ 111
Local changes are in conflict with updated values synced from the server. Do you want the local changes to be overwritten with the latest values?
src/app/core/common-components/entity-form/entity-form/entity-form.component.ts
- 111
+ 112
@@ -2673,6 +2704,15 @@
A placeholder for the input element when select options are not loaded yet
+
+ Include archived records
+
+ src/app/core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component.html
+ 160,162
+
+ also show entries that are archived
+ slider
+
Select file
@@ -2709,7 +2749,7 @@
src/app/core/config/config-fix.ts
- 661
+ 645
Menu item
@@ -2872,33 +2912,26 @@
src/app/core/config/config-fix.ts
- 495
+ 481
src/app/core/config/config-fix.ts
- 549
+ 535
Translated name of mobile column group
-
- Attachment
-
- src/app/core/config/config-fix.ts
- 269
-
-
Site Settings
src/app/core/config/config-fix.ts
- 281
+ 267
User Information
src/app/core/config/config-fix.ts
- 328
+ 314
Panel title
@@ -2906,7 +2939,7 @@
Security
src/app/core/config/config-fix.ts
- 347
+ 333
Panel title
@@ -2914,7 +2947,7 @@
assets/help/help.en.md
src/app/core/config/config-fix.ts
- 361
+ 347
Filename of markdown help page (make sure the filename you enter as a translation actually exists on the server!)
@@ -2922,26 +2955,26 @@
Private School
src/app/core/config/config-fix.ts
- 382
+ 368
src/app/core/config/config-fix.ts
- 1020
+ 1006
Basic Information
src/app/core/config/config-fix.ts
- 393
+ 379
src/app/core/config/config-fix.ts
- 585
+ 569
src/app/core/config/config-fix.ts
- 798
+ 771
Panel title
@@ -2949,7 +2982,7 @@
Students
src/app/core/config/config-fix.ts
- 421
+ 407
Panel title
@@ -2957,7 +2990,7 @@
Activities
src/app/core/config/config-fix.ts
- 430
+ 416
Panel title
@@ -2965,7 +2998,7 @@
Age
src/app/core/config/config-fix.ts
- 452
+ 438
Column label for age of child
@@ -2973,7 +3006,7 @@
Attendance (School)
src/app/core/config/config-fix.ts
- 470
+ 456
Column label for school attendance of child
@@ -2981,7 +3014,7 @@
Attendance (Coaching)
src/app/core/config/config-fix.ts
- 479
+ 465
Column label for coaching attendance of child
@@ -2989,11 +3022,11 @@
Basic Info
src/app/core/config/config-fix.ts
- 494
+ 480
src/app/core/config/config-fix.ts
- 498
+ 484
Translated name of default column group
@@ -3001,7 +3034,7 @@
School Info
src/app/core/config/config-fix.ts
- 511
+ 497
Column group name
@@ -3009,47 +3042,19 @@
Health
src/app/core/config/config-fix.ts
- 534
+ 520
src/app/core/config/config-fix.ts
- 683
+ 667
Column group name
-
- Active
-
- src/app/core/config/config-fix.ts
- 564
-
-
- src/app/core/config/config-fix.ts
- 780
-
- Active children filter label - true case
-
-
- Inactive
-
- src/app/core/config/config-fix.ts
- 565
-
-
- src/app/core/config/config-fix.ts
- 781
-
-
- src/app/core/entity/model/entity.ts
- 194
-
- Active children filter label - false case
-
Personal Information
src/app/core/config/config-fix.ts
- 613
+ 597
Header for form section
@@ -3057,7 +3062,7 @@
Additional
src/app/core/config/config-fix.ts
- 614
+ 598
Header for form section
@@ -3065,7 +3070,7 @@
Scholar activities
src/app/core/config/config-fix.ts
- 615
+ 599
Header for form section
@@ -3073,7 +3078,7 @@
Education
src/app/core/config/config-fix.ts
- 622
+ 606
Panel title
@@ -3081,7 +3086,7 @@
School History
src/app/core/config/config-fix.ts
- 625
+ 609
Title inside a panel
@@ -3089,7 +3094,7 @@
ASER Results
src/app/core/config/config-fix.ts
- 645
+ 629
Title inside a panel
@@ -3097,7 +3102,7 @@
Find a suitable new school
src/app/core/config/config-fix.ts
- 649
+ 633
Child details section title
@@ -3105,7 +3110,7 @@
Notes & Tasks
src/app/core/config/config-fix.ts
- 670
+ 654
Panel title
@@ -3113,7 +3118,7 @@
Health checkups are to be done regularly, at least every 6 months according to the program guidelines.
src/app/core/config/config-fix.ts
- 692
+ 676
description section
@@ -3121,7 +3126,7 @@
Height & Weight Tracking
src/app/core/config/config-fix.ts
- 699
+ 683
Title inside a panel
@@ -3129,7 +3134,7 @@
Educational Materials
src/app/core/config/config-fix.ts
- 705
+ 689
Panel title
@@ -3137,7 +3142,7 @@
Observations
src/app/core/config/config-fix.ts
- 730
+ 714
Panel title
@@ -3145,7 +3150,7 @@
Events & Attendance
src/app/core/config/config-fix.ts
- 828
+ 801
Panel title
@@ -3153,7 +3158,7 @@
Basic Report
src/app/core/config/config-fix.ts
- 843
+ 816
Name of a report
@@ -3161,7 +3166,7 @@
All children
src/app/core/config/config-fix.ts
- 847
+ 820
Label of report query
@@ -3169,7 +3174,7 @@
All schools
src/app/core/config/config-fix.ts
- 852
+ 825
Label for report query
@@ -3177,7 +3182,7 @@
Children attending a school
src/app/core/config/config-fix.ts
- 855
+ 828
Label for report query
@@ -3185,7 +3190,7 @@
Governmental schools
src/app/core/config/config-fix.ts
- 859
+ 832
Label for report query
@@ -3193,7 +3198,7 @@
Children attending a governmental school
src/app/core/config/config-fix.ts
- 864
+ 837
Label for report query
@@ -3201,7 +3206,7 @@
Private schools
src/app/core/config/config-fix.ts
- 868
+ 841
Label for report query
@@ -3209,7 +3214,7 @@
Children attending a private school
src/app/core/config/config-fix.ts
- 873
+ 846
Label for report query
@@ -3217,7 +3222,7 @@
Event Report
src/app/core/config/config-fix.ts
- 881
+ 854
Name of a report
@@ -3225,7 +3230,7 @@
Attendance Report
src/app/core/config/config-fix.ts
- 898
+ 871
Name of a report
@@ -3233,7 +3238,7 @@
Total
src/app/core/config/config-fix.ts
- 913
+ 899
Name of a column of a report
@@ -3241,7 +3246,7 @@
Present
src/app/core/config/config-fix.ts
- 917
+ 903
Name of a column of a report
@@ -3249,7 +3254,7 @@
Rate
src/app/core/config/config-fix.ts
- 921
+ 907
Name of a column of a report
@@ -3257,7 +3262,7 @@
Late
src/app/core/config/config-fix.ts
- 925
+ 911
Name of a column of a report
@@ -3265,7 +3270,7 @@
Materials Distributed
src/app/core/config/config-fix.ts
- 935
+ 921
Name of a report
@@ -3273,11 +3278,11 @@
Address
src/app/core/config/config-fix.ts
- 966
+ 952
src/app/core/config/config-fix.ts
- 1034
+ 1020
Label for the address of a child
@@ -3285,7 +3290,7 @@
Blood Group
src/app/core/config/config-fix.ts
- 973
+ 959
Label for a child attribute
@@ -3293,7 +3298,7 @@
Religion
src/app/core/config/config-fix.ts
- 980
+ 966
Label for the religion of a child
@@ -3301,7 +3306,7 @@
Mother Tongue
src/app/core/config/config-fix.ts
- 987
+ 973
Label for the mother tongue of a child
@@ -3309,7 +3314,7 @@
The primary language spoken at home
src/app/core/config/config-fix.ts
- 988
+ 974
Tooltip description for the mother tongue of a child
@@ -3317,7 +3322,7 @@
Last Dental Check-Up
src/app/core/config/config-fix.ts
- 995
+ 981
Label for a child attribute
@@ -3325,7 +3330,7 @@
Birth certificate
src/app/core/config/config-fix.ts
- 1002
+ 988
Label for a child attribute
@@ -3333,7 +3338,7 @@
Language
src/app/core/config/config-fix.ts
- 1027
+ 1013
Label for the language of a school
@@ -3341,7 +3346,7 @@
School Timing
src/app/core/config/config-fix.ts
- 1048
+ 1034
Label for the timing of a school
@@ -3349,7 +3354,7 @@
Motivated
src/app/core/config/config-fix.ts
- 1067
+ 1053
Label for a child attribute
@@ -3357,7 +3362,7 @@
The child is motivated during the class.
src/app/core/config/config-fix.ts
- 1068
+ 1054
Description for a child attribute
@@ -3365,7 +3370,7 @@
Participating
src/app/core/config/config-fix.ts
- 1076
+ 1062
Label for a child attribute
@@ -3373,7 +3378,7 @@
The child is actively participating in the class.
src/app/core/config/config-fix.ts
- 1077
+ 1063
Description for a child attribute
@@ -3381,7 +3386,7 @@
Interacting
src/app/core/config/config-fix.ts
- 1085
+ 1071
Label for a child attribute
@@ -3389,7 +3394,7 @@
The child interacts with other students during the class.
src/app/core/config/config-fix.ts
- 1086
+ 1072
Description for a child attribute
@@ -3397,7 +3402,7 @@
Homework
src/app/core/config/config-fix.ts
- 1094
+ 1080
Label for a child attribute
@@ -3405,7 +3410,7 @@
The child does its homework.
src/app/core/config/config-fix.ts
- 1095
+ 1081
Description for a child attribute
@@ -3413,7 +3418,7 @@
Asking Questions
src/app/core/config/config-fix.ts
- 1103
+ 1089
Label for a child attribute
@@ -3421,7 +3426,7 @@
The child is asking questions during the class.
src/app/core/config/config-fix.ts
- 1104
+ 1090
Description for a child attribute
@@ -3429,7 +3434,7 @@
Contact
src/app/core/config/config-fix.ts
- 1115
+ 1101
Label of user phone
@@ -3584,6 +3589,82 @@
28
+
+ Archive
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 69
+
+ entity context menu
+
+
+ Mark the record as inactive, hiding it from lists by default while keeping the data.
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 70
+
+ entity context menu tooltip
+
+
+ Anonymize
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 77
+
+ entity context menu
+
+
+ Remove all personal data and keep an archived basic record for statistical reporting.
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 78
+
+ entity context menu tooltip
+
+
+ Delete
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 85
+
+ entity context menu
+
+
+ Remove the record completely from the database.
+
+ src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
+ 86
+
+ entity context menu tooltip
+
+
+ Archived
+
+ src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
+ 6
+
+
+
+ Anonymized & Archived
+
+ src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
+ 8
+
+
+
+ This record has been anonymized. Details containing personal information have been deleted and cannot be restored. For statistical reporting, this basic record has been kept.
+
+ src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
+ 13,17
+
+
+
+ This record is archived and will be be hidden from lists and select options by default.
+
+ src/app/core/entity-details/entity-archived-info/entity-archived-info.component.html
+ 19,22
+
+
Adding new
@@ -3593,23 +3674,11 @@
An entity is a child, note, school, etc.
Title when adding a new entity
-
- Delete
-
- src/app/core/entity-details/entity-details/entity-details.component.html
- 58
-
-
- src/app/core/form-dialog/dialog-buttons/dialog-buttons.component.html
- 61
-
- Generic delete button
-
Save the new record to create it before accessing other details
src/app/core/entity-details/entity-details/entity-details.component.html
- 74
+ 51
Tooltip explaining disabled sections when creating new entity
@@ -3663,38 +3732,11 @@
14
-
- Show entries where the end date is in the past
-
- src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
- 32
-
-
- src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
- 32
-
- Tooltip that will appear when hovered over the
- show-ended button
- Show ended tooltip
-
-
- Include inactive past records
-
- src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
- 34,36
-
-
- src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.html
- 34,36
-
- also show entries that are inactive
- slider
-
Currently
src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
- 105
+ 97
e.g. Currently active
Label for the currently active status
@@ -3703,7 +3745,7 @@
Only added to linked record if active. Change the start or end date to modify this status.
src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
- 108
+ 100
Tooltip for the status of currently active or not
@@ -3711,7 +3753,7 @@
active
src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
- 111
+ 103
Indication for the currently active status of an entry
@@ -3719,7 +3761,7 @@
not active
src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.ts
- 112
+ 104
Indication for the currently inactive status of an entry
@@ -3743,7 +3785,7 @@
No " " date is set
src/app/core/entity-details/related-time-period-entities/time-period.ts
- 63
+ 68
Error assertValid failed
@@ -3751,7 +3793,7 @@
The " " date is after the " " date
src/app/core/entity-details/related-time-period-entities/time-period.ts
- 67
+ 72
Error assertValid failed
@@ -3768,7 +3810,7 @@
Filter
src/app/core/entity-list/entity-list/entity-list.component.html
- 98,99
+ 100,101
Allows the user to filter through entities
Filter placeholder
@@ -3777,7 +3819,7 @@
e.g. name, age
src/app/core/entity-list/entity-list/entity-list.component.html
- 104
+ 106
Examples of things to filter
@@ -3785,7 +3827,7 @@
Add New
src/app/core/entity-list/entity-list/entity-list.component.html
- 154,156
+ 158,160
Add a new entity to a list of multiple entities
@@ -3793,15 +3835,23 @@
Filter options
src/app/core/entity-list/entity-list/entity-list.component.html
- 166
+ 170
Show filter options popup for list
-
- Download CSV
+
+ Download all data (.csv)
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 189
+
+ Download list contents as CSV
+
+
+ Download current (.csv)
src/app/core/entity-list/entity-list/entity-list.component.html
- 185
+ 207
Download list contents as CSV
@@ -3809,7 +3859,43 @@
Import from file
src/app/core/entity-list/entity-list/entity-list.component.html
- 201
+ 223
+
+
+
+ Select multiple records for bulk actions like duplicating or deleting
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 229
+
+
+
+ Bulk Actions
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 237
+
+
+
+ Select rows to clone
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 252
+
+
+
+ Duplicate
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 256,258
+
+ bulk action button
+
+
+ Cancel
+
+ src/app/core/entity-list/entity-list/entity-list.component.html
+ 260,262
@@ -3819,49 +3905,157 @@
59
+
+ " "
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 35,37
+
+ Entity action confirmation message
+
+
+ Undo
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 41
+
+
+ src/app/core/import/import-confirm-summary/import-confirm-summary.component.ts
+ 61
+
+ Undo an entity action
+
+
+ Reverting changes ...
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 50
+
+ Undo entity action progress dialog
+
Delete?
- src/app/core/entity/entity-remove.service.ts
- 78
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 76
Delete confirmation title
-
- Are you sure you want to delete this record?
+
+
+ This will remove the data permanently as if it never existed. This cannot be undone. Statistical reports (also for past time periods) will change and not include this record anymore.
+
+ If you have not just created this record accidentally, deleting this is probably not what you want to do. If the record represents something that actually happened in your work, consider to use "anonymize" or just "archive" instead, so that you will not lose your documentation for reports.
+
+ Are you sure you want to delete this record?
- src/app/core/entity/entity-remove.service.ts
- 81
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 77,82
- Delete confirmation text
+ Delete confirmation dialog
-
- Deleted Entity
+
+ Processing ...
- src/app/core/entity/entity-remove.service.ts
- 93
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 89
- Deleted Entity information
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 145
+
+ Entity action progress dialog
-
- Undo
+
+ Related records may still contain personal data
- src/app/core/entity/entity-remove.service.ts
- 97
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 96
- src/app/core/import/import-confirm-summary/import-confirm-summary.component.ts
- 61
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 152
+
+ post-delete related PII warning title
+
+
+ Some related records (e.g. notes) may still contain personal data in their text. We have automatically deleted all records that are linked to ONLY this .
+ However, there are some records that are linked to multiple records. We have not deleted these, so that you will not lose relevant data. Please review them manually to ensure all sensitive information is removed, if required (e.g. by looking through the linked notes and editing a note's text).
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 97,100
+
+ post-delete related PII warning dialog
+
+
+ Deleted
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 114
+
+ Entity action confirmation message verb
+
+
+ Anonymize?
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 132
+
+ Anonymize confirmation dialog
+
+
+
+ This will remove all personal information (PII) permanently and keep only a basic record for statistical reports. Details that are removed during anonymization cannot be recovered.
+
+ If this has only become inactive and you want to keep all details about the record, consider to use "archive" instead.
+
+ Are you sure you want to anonymize this record?
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 133,138
+
+ Anonymize confirmation dialog
+
+
+ Some related records (e.g. notes) may still contain personal data in their text. We have automatically anonymized all records that are linked to ONLY this .
+ However, there are some records that are linked to multiple records. We have not anonymized these, so that you will not lose relevant data. Please review them manually to ensure all sensitive information is removed (e.g. by looking through the linked notes and editing a note's text).
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 153,156
+
+ post-anonymize related PII warning dialog
+
+
+ Anonymized
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 163
+
+ Entity action confirmation message verb
+
+
+ Archived
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 180
- Undo deleting an entity
+ Entity action confirmation message verb
-
- Ticking this box will archive the record. No data will be lost but the record will be hidden.
+
+ Reactivated
+
+ src/app/core/entity/entity-actions/entity-actions.service.ts
+ 196
+
+ Entity action confirmation message verb
+
+
+ [anonymized ]
src/app/core/entity/model/entity.ts
- 195
+ 316,318
- Description of checkbox
+ Entity.toString fallback for anonymized record
Filter Options
@@ -5042,7 +5236,7 @@ Please try again. If the problem persists contact Aam Digital support.
Username
src/app/core/user/user.ts
- 38
+ 39
Label of username
@@ -5050,7 +5244,7 @@ Please try again. If the problem persists contact Aam Digital support.
cannot be changed after initialization
src/app/core/user/user.ts
- 46
+ 47
e.g. username cannot be changed after initialization
Error message when trying to change the username
@@ -5525,7 +5719,7 @@ Please try again. If the problem persists contact Aam Digital support.
src/app/features/file/edit-photo/edit-photo.component.html
- 17
+ 22
Tooltip upload file button
@@ -5533,7 +5727,7 @@ Please try again. If the problem persists contact Aam Digital support.
File " " deleted
src/app/features/file/edit-file/edit-file.component.ts
- 132
+ 134
Message for user
@@ -5630,7 +5824,7 @@ Please try again. If the problem persists contact Aam Digital support.
Click on the map to select a different location
src/app/features/location/edit-location/edit-location.component.ts
- 118
+ 119
help text in map popup
@@ -5803,11 +5997,18 @@ Please try again. If the problem persists contact Aam Digital support.
15
+
+ Please select a report and a date range
+
+ src/app/features/reporting/reporting/select-report/select-report.component.html
+ 66
+
+
Calculate
src/app/features/reporting/reporting/select-report/select-report.component.html
- 65,67
+ 70,72
Calculate the results for a report
@@ -5815,7 +6016,7 @@ Please try again. If the problem persists contact Aam Digital support.
Download
src/app/features/reporting/reporting/select-report/select-report.component.html
- 87
+ 93
Button to download data
@@ -5895,7 +6096,7 @@ Please try again. If the problem persists contact Aam Digital support.
Deadline
src/app/features/todos/model/todo.ts
- 47
+ 48
Label
@@ -5903,7 +6104,7 @@ Please try again. If the problem persists contact Aam Digital support.
When you are planning to start work so that you keep enough time before the actual hard deadline.
src/app/features/todos/model/todo.ts
- 55
+ 57
Description
@@ -5911,7 +6112,7 @@ Please try again. If the problem persists contact Aam Digital support.
Assigned to
src/app/features/todos/model/todo.ts
- 68
+ 71
Label
@@ -5919,7 +6120,7 @@ Please try again. If the problem persists contact Aam Digital support.
repeats
src/app/features/todos/model/todo.ts
- 94
+ 100
label for Todo entity property
@@ -5927,7 +6128,7 @@ Please try again. If the problem persists contact Aam Digital support.
every week
src/app/features/todos/model/todo.ts
- 97
+ 103
repetition interval option
@@ -5935,7 +6136,7 @@ Please try again. If the problem persists contact Aam Digital support.
every month
src/app/features/todos/model/todo.ts
- 101
+ 107
repetition interval option
@@ -5943,7 +6144,7 @@ Please try again. If the problem persists contact Aam Digital support.
completed
src/app/features/todos/model/todo.ts
- 110
+ 117
label for Todo entity property
@@ -6109,7 +6310,7 @@ Please try again. If the problem persists contact Aam Digital support.
Overdue
src/app/features/todos/todo-list/todo-list.component.ts
- 99
+ 101
Filter-option for todos
@@ -6117,7 +6318,7 @@ Please try again. If the problem persists contact Aam Digital support.
Completed
src/app/features/todos/todo-list/todo-list.component.ts
- 104
+ 106
Filter-option for todos
@@ -6125,7 +6326,7 @@ Please try again. If the problem persists contact Aam Digital support.
All Open
src/app/features/todos/todo-list/todo-list.component.ts
- 109
+ 111
Filter-option for todos
@@ -6133,21 +6334,21 @@ Please try again. If the problem persists contact Aam Digital support.
Any
src/app/features/todos/todo-list/todo-list.component.ts
- 112
+ 114
Tasks due
src/app/features/todos/todo-list/todo-list.component.ts
- 114
+ 116
Currently Active
src/app/features/todos/todo-list/todo-list.component.ts
- 129
+ 131
Filter-option for todos
@@ -6168,15 +6369,6 @@ Please try again. If the problem persists contact Aam Digital support.
dashboard showing open todos
subtitle
-
- Also show completed
-
- src/app/features/todos/todos-related-to-entity/todos-related-to-entity.component.html
- 17,19
-
- also show entries that are inactive
- slider
-
diff --git a/src/index.html b/src/index.html
index 702f4b74d9..ac4754347a 100644
--- a/src/index.html
+++ b/src/index.html
@@ -1,4 +1,5 @@
-
-