1
0

Merge remote-tracking branch 'github/main' into DURACOM-191-20240311-main-merge

# Conflicts:
#	src/app/access-control/access-control-routing.module.ts
#	src/app/access-control/access-control.module.ts
#	src/app/access-control/bulk-access/browse/bulk-access-browse.component.spec.ts
#	src/app/access-control/bulk-access/browse/bulk-access-browse.component.ts
#	src/app/access-control/bulk-access/bulk-access.component.spec.ts
#	src/app/access-control/bulk-access/bulk-access.component.ts
#	src/app/access-control/bulk-access/settings/bulk-access-settings.component.spec.ts
#	src/app/access-control/bulk-access/settings/bulk-access-settings.component.ts
#	src/app/access-control/epeople-registry/epeople-registry.component.spec.ts
#	src/app/access-control/epeople-registry/epeople-registry.component.ts
#	src/app/access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts
#	src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts
#	src/app/access-control/group-registry/group-form/group-form.component.spec.ts
#	src/app/access-control/group-registry/group-form/group-form.component.ts
#	src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts
#	src/app/access-control/group-registry/group-form/members-list/members-list.component.ts
#	src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts
#	src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts
#	src/app/access-control/group-registry/groups-registry.component.spec.ts
#	src/app/access-control/group-registry/groups-registry.component.ts
#	src/app/admin/admin-curation-tasks/admin-curation-tasks.component.spec.ts
#	src/app/admin/admin-import-batch-page/batch-import-page.component.spec.ts
#	src/app/admin/admin-import-batch-page/batch-import-page.component.ts
#	src/app/admin/admin-import-metadata-page/metadata-import-page.component.spec.ts
#	src/app/admin/admin-import-metadata-page/metadata-import-page.component.ts
#	src/app/admin/admin-ldn-services/admin-ldn-services-routes.ts
#	src/app/admin/admin-ldn-services/admin-ldn-services.module.ts
#	src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.spec.ts
#	src/app/admin/admin-ldn-services/ldn-service-form/ldn-service-form.component.ts
#	src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.spec.ts
#	src/app/admin/admin-ldn-services/ldn-services-directory/ldn-services-directory.component.ts
#	src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts
#	src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.ts
#	src/app/admin/admin-notifications/admin-notifications-routing.module.ts
#	src/app/admin/admin-notifications/admin-notifications.module.ts
#	src/app/admin/admin-registries/admin-registries-routing.module.ts
#	src/app/admin/admin-registries/admin-registries.module.ts
#	src/app/admin/admin-registries/bitstream-formats/add-bitstream-format/add-bitstream-format.component.spec.ts
#	src/app/admin/admin-registries/bitstream-formats/add-bitstream-format/add-bitstream-format.component.ts
#	src/app/admin/admin-registries/bitstream-formats/bitstream-formats-routing.module.ts
#	src/app/admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts
#	src/app/admin/admin-registries/bitstream-formats/bitstream-formats.component.ts
#	src/app/admin/admin-registries/bitstream-formats/bitstream-formats.module.ts
#	src/app/admin/admin-registries/bitstream-formats/edit-bitstream-format/edit-bitstream-format.component.spec.ts
#	src/app/admin/admin-registries/bitstream-formats/edit-bitstream-format/edit-bitstream-format.component.ts
#	src/app/admin/admin-registries/bitstream-formats/format-form/format-form.component.spec.ts
#	src/app/admin/admin-registries/bitstream-formats/format-form/format-form.component.ts
#	src/app/admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts
#	src/app/admin/admin-registries/metadata-registry/metadata-registry.component.ts
#	src/app/admin/admin-registries/metadata-registry/metadata-schema-form/metadata-schema-form.component.spec.ts
#	src/app/admin/admin-registries/metadata-registry/metadata-schema-form/metadata-schema-form.component.ts
#	src/app/admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.spec.ts
#	src/app/admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.ts
#	src/app/admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts
#	src/app/admin/admin-registries/metadata-schema/metadata-schema.component.ts
#	src/app/admin/admin-reports/admin-reports-routing.module.ts
#	src/app/admin/admin-reports/admin-reports.module.ts
#	src/app/admin/admin-reports/filtered-collections/filtered-collections.component.spec.ts
#	src/app/admin/admin-reports/filtered-collections/filtered-collections.component.ts
#	src/app/admin/admin-reports/filtered-items/filtered-items.component.ts
#	src/app/admin/admin-reports/filters-section/filters-section.component.spec.ts
#	src/app/admin/admin-reports/filters-section/filters-section.component.ts
#	src/app/admin/admin-routing.module.ts
#	src/app/admin/admin-search-page/admin-search-page.component.spec.ts
#	src/app/admin/admin-search-page/admin-search-page.component.ts
#	src/app/admin/admin-search-page/admin-search-results/admin-search-result-grid-element/collection-search-result/collection-admin-search-result-grid-element.component.spec.ts
#	src/app/admin/admin-search-page/admin-search-results/admin-search-result-grid-element/collection-search-result/collection-admin-search-result-grid-element.component.ts
#	src/app/admin/admin-search-page/admin-search-results/admin-search-result-grid-element/community-search-result/community-admin-search-result-grid-element.component.spec.ts
#	src/app/admin/admin-search-page/admin-search-results/admin-search-result-grid-element/community-search-result/community-admin-search-result-grid-element.component.ts
#	src/app/admin/admin-search-page/admin-search-results/admin-search-result-grid-element/item-search-result/item-admin-search-result-grid-element.component.spec.ts
#	src/app/admin/admin-search-page/admin-search-results/admin-search-result-grid-element/item-search-result/item-admin-search-result-grid-element.component.ts
#	src/app/admin/admin-search-page/admin-search-results/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.spec.ts
#	src/app/admin/admin-search-page/admin-search-results/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.ts
#	src/app/admin/admin-search-page/admin-search-results/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.spec.ts
#	src/app/admin/admin-search-page/admin-search-results/admin-search-result-list-element/community-search-result/community-admin-search-result-list-element.component.ts
#	src/app/admin/admin-search-page/admin-search-results/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.spec.ts
#	src/app/admin/admin-search-page/admin-search-results/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.ts
#	src/app/admin/admin-search-page/admin-search-results/item-admin-search-result-actions.component.spec.ts
#	src/app/admin/admin-search-page/admin-search-results/item-admin-search-result-actions.component.ts
#	src/app/admin/admin-search-page/admin-search.module.ts
#	src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.spec.ts
#	src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.ts
#	src/app/admin/admin-sidebar/admin-sidebar.component.spec.ts
#	src/app/admin/admin-sidebar/admin-sidebar.component.ts
#	src/app/admin/admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component.spec.ts
#	src/app/admin/admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component.ts
#	src/app/admin/admin-workflow-page/admin-workflow-page.component.spec.ts
#	src/app/admin/admin-workflow-page/admin-workflow-page.component.ts
#	src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workflow-item/workflow-item-admin-workflow-actions.component.spec.ts
#	src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workflow-item/workflow-item-admin-workflow-actions.component.ts
#	src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component.spec.ts
#	src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-group-selector/supervision-order-group-selector.component.ts
#	src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component.spec.ts
#	src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/supervision-order-status/supervision-order-status.component.ts
#	src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.spec.ts
#	src/app/admin/admin-workflow-page/admin-workflow-search-results/actions/workspace-item/workspace-item-admin-workflow-actions.component.ts
#	src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workflow-item/workflow-item-search-result-admin-workflow-grid-element.component.spec.ts
#	src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workflow-item/workflow-item-search-result-admin-workflow-grid-element.component.ts
#	src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component.spec.ts
#	src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-grid-element/workspace-item/workspace-item-search-result-admin-workflow-grid-element.component.ts
#	src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component.spec.ts
#	src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workflow-item/workflow-item-search-result-admin-workflow-list-element.component.ts
#	src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workspace-item/workspace-item-search-result-admin-workflow-list-element.component.spec.ts
#	src/app/admin/admin-workflow-page/admin-workflow-search-results/admin-workflow-search-result-list-element/workspace-item/workspace-item-search-result-admin-workflow-list-element.component.ts
#	src/app/admin/admin-workflow-page/admin-workflow.module.ts
#	src/app/admin/admin.module.ts
#	src/app/app-routing.module.ts
#	src/app/app.component.ts
#	src/app/app.module.ts
#	src/app/bitstream-page/bitstream-authorizations/bitstream-authorizations.component.spec.ts
#	src/app/bitstream-page/bitstream-authorizations/bitstream-authorizations.component.ts
#	src/app/bitstream-page/bitstream-download-page/bitstream-download-page.component.spec.ts
#	src/app/bitstream-page/bitstream-download-page/bitstream-download-page.component.ts
#	src/app/bitstream-page/bitstream-page-routing.module.ts
#	src/app/bitstream-page/bitstream-page.module.ts
#	src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts
#	src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts
#	src/app/breadcrumbs/breadcrumbs.component.spec.ts
#	src/app/breadcrumbs/breadcrumbs.component.ts
#	src/app/browse-by/browse-by-date/browse-by-date.component.spec.ts
#	src/app/browse-by/browse-by-date/browse-by-date.component.ts
#	src/app/browse-by/browse-by-guard.spec.ts
#	src/app/browse-by/browse-by-metadata/browse-by-metadata.component.spec.ts
#	src/app/browse-by/browse-by-metadata/browse-by-metadata.component.ts
#	src/app/browse-by/browse-by-page.module.ts
#	src/app/browse-by/browse-by-routing.module.ts
#	src/app/browse-by/browse-by-switcher/browse-by-decorator.ts
#	src/app/browse-by/browse-by-switcher/browse-by-switcher.component.spec.ts
#	src/app/browse-by/browse-by-switcher/browse-by-switcher.component.ts
#	src/app/browse-by/browse-by-switcher/dynamic-component-loader.directive.ts
#	src/app/browse-by/browse-by-taxonomy/browse-by-taxonomy.component.spec.ts
#	src/app/browse-by/browse-by-taxonomy/browse-by-taxonomy.component.ts
#	src/app/browse-by/browse-by-title/browse-by-title.component.spec.ts
#	src/app/browse-by/browse-by-title/browse-by-title.component.ts
#	src/app/browse-by/browse-by.module.ts
#	src/app/collection-page/collection-form/collection-form.component.ts
#	src/app/collection-page/collection-form/collection-form.module.ts
#	src/app/collection-page/collection-item-mapper/collection-item-mapper.component.spec.ts
#	src/app/collection-page/collection-item-mapper/collection-item-mapper.component.ts
#	src/app/collection-page/collection-page-routing.module.ts
#	src/app/collection-page/collection-page.component.ts
#	src/app/collection-page/collection-page.module.ts
#	src/app/collection-page/create-collection-page/create-collection-page.component.spec.ts
#	src/app/collection-page/create-collection-page/create-collection-page.component.ts
#	src/app/collection-page/delete-collection-page/delete-collection-page.component.spec.ts
#	src/app/collection-page/delete-collection-page/delete-collection-page.component.ts
#	src/app/collection-page/edit-collection-page/collection-access-control/collection-access-control.component.spec.ts
#	src/app/collection-page/edit-collection-page/collection-authorizations/collection-authorizations.component.spec.ts
#	src/app/collection-page/edit-collection-page/collection-curate/collection-curate.component.spec.ts
#	src/app/collection-page/edit-collection-page/collection-metadata/collection-metadata.component.spec.ts
#	src/app/collection-page/edit-collection-page/collection-metadata/collection-metadata.component.ts
#	src/app/collection-page/edit-collection-page/collection-roles/collection-roles.component.spec.ts
#	src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts
#	src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts
#	src/app/collection-page/edit-collection-page/collection-source/collection-source.component.spec.ts
#	src/app/collection-page/edit-collection-page/collection-source/collection-source.component.ts
#	src/app/collection-page/edit-collection-page/edit-collection-page.component.spec.ts
#	src/app/collection-page/edit-collection-page/edit-collection-page.component.ts
#	src/app/collection-page/edit-collection-page/edit-collection-page.module.ts
#	src/app/collection-page/edit-collection-page/edit-collection-page.routing.module.ts
#	src/app/collection-page/edit-item-template-page/edit-item-template-page.component.spec.ts
#	src/app/collection-page/edit-item-template-page/edit-item-template-page.component.ts
#	src/app/community-list-page/community-list-page.component.spec.ts
#	src/app/community-list-page/community-list-page.module.ts
#	src/app/community-list-page/community-list-page.routing.module.ts
#	src/app/community-list-page/community-list/community-list.component.spec.ts
#	src/app/community-list-page/community-list/community-list.component.ts
#	src/app/community-page/community-form/community-form.component.ts
#	src/app/community-page/community-form/community-form.module.ts
#	src/app/community-page/community-page-routing.module.ts
#	src/app/community-page/community-page.component.ts
#	src/app/community-page/community-page.module.ts
#	src/app/community-page/create-community-page/create-community-page.component.spec.ts
#	src/app/community-page/create-community-page/create-community-page.component.ts
#	src/app/community-page/delete-community-page/delete-community-page.component.spec.ts
#	src/app/community-page/delete-community-page/delete-community-page.component.ts
#	src/app/community-page/edit-community-page/community-access-control/community-access-control.component.spec.ts
#	src/app/community-page/edit-community-page/community-access-control/community-access-control.component.ts
#	src/app/community-page/edit-community-page/community-authorizations/community-authorizations.component.spec.ts
#	src/app/community-page/edit-community-page/community-curate/community-curate.component.spec.ts
#	src/app/community-page/edit-community-page/community-metadata/community-metadata.component.spec.ts
#	src/app/community-page/edit-community-page/community-roles/community-roles.component.spec.ts
#	src/app/community-page/edit-community-page/community-roles/community-roles.component.ts
#	src/app/community-page/edit-community-page/edit-community-page.component.spec.ts
#	src/app/community-page/edit-community-page/edit-community-page.component.ts
#	src/app/community-page/edit-community-page/edit-community-page.module.ts
#	src/app/community-page/edit-community-page/edit-community-page.routing.module.ts
#	src/app/community-page/sections/sub-com-col-section/sub-collection-list/community-page-sub-collection-list.component.spec.ts
#	src/app/community-page/sections/sub-com-col-section/sub-collection-list/community-page-sub-collection-list.component.ts
#	src/app/community-page/sections/sub-com-col-section/sub-com-col-section.component.ts
#	src/app/community-page/sections/sub-com-col-section/sub-community-list/community-page-sub-community-list.component.spec.ts
#	src/app/community-page/sections/sub-com-col-section/sub-community-list/community-page-sub-community-list.component.ts
#	src/app/core/auth/auth.service.spec.ts
#	src/app/core/browse/browse-definition-data.service.ts
#	src/app/core/cache/builders/link.service.spec.ts
#	src/app/core/cache/builders/link.service.ts
#	src/app/core/coar-notify/notify-info/notify-info.component.spec.ts
#	src/app/core/coar-notify/notify-info/notify-info.component.ts
#	src/app/core/coar-notify/notify-info/notify-info.service.ts
#	src/app/core/config/bulk-access-config-data.service.ts
#	src/app/core/config/submission-accesses-config-data.service.ts
#	src/app/core/config/submission-uploads-config-data.service.ts
#	src/app/core/core.module.ts
#	src/app/core/data/access-status-data.service.ts
#	src/app/core/data/bitstream-data.service.ts
#	src/app/core/data/bitstream-format-data.service.ts
#	src/app/core/data/bundle-data.service.ts
#	src/app/core/data/collection-data.service.ts
#	src/app/core/data/community-data.service.ts
#	src/app/core/data/configuration-data.service.ts
#	src/app/core/data/dspace-object-data.service.ts
#	src/app/core/data/feature-authorization/authorization-data.service.ts
#	src/app/core/data/feature-authorization/feature-authorization-guard/site-administrator.guard.ts
#	src/app/core/data/feature-authorization/feature-authorization-guard/site-register.guard.ts
#	src/app/core/data/feature-authorization/feature-data.service.ts
#	src/app/core/data/href-only-data.service.ts
#	src/app/core/data/identifier-data.service.ts
#	src/app/core/data/item-data.service.spec.ts
#	src/app/core/data/item-data.service.ts
#	src/app/core/data/metadata-field-data.service.ts
#	src/app/core/data/metadata-schema-data.service.ts
#	src/app/core/data/processes/process-data.service.ts
#	src/app/core/data/processes/script-data.service.ts
#	src/app/core/data/relationship-data.service.ts
#	src/app/core/data/relationship-type-data.service.ts
#	src/app/core/data/root-data.service.ts
#	src/app/core/data/site-data.service.ts
#	src/app/core/data/system-wide-alert-data.service.ts
#	src/app/core/data/version-data.service.ts
#	src/app/core/data/version-history-data.service.ts
#	src/app/core/data/workflow-action-data.service.ts
#	src/app/core/eperson/eperson-data.service.spec.ts
#	src/app/core/eperson/eperson-data.service.ts
#	src/app/core/eperson/group-data.service.spec.ts
#	src/app/core/eperson/group-data.service.ts
#	src/app/core/feedback/feedback-data.service.ts
#	src/app/core/google-recaptcha/google-recaptcha.module.ts
#	src/app/core/orcid/orcid-history-data.service.ts
#	src/app/core/orcid/orcid-queue-data.service.ts
#	src/app/core/profile/researcher-profile-data.service.ts
#	src/app/core/registry/registry.service.spec.ts
#	src/app/core/resource-policy/resource-policy-data.service.ts
#	src/app/core/shared/non-hierarchical-browse-definition.ts
#	src/app/core/shared/search/search.service.spec.ts
#	src/app/core/statistics/usage-report-data.service.ts
#	src/app/core/submission/submission-cc-license-data.service.ts
#	src/app/core/submission/submission-cc-license-url-data.service.ts
#	src/app/core/submission/vocabularies/vocabulary-entry-details.data.service.ts
#	src/app/core/submission/workflowitem-data.service.ts
#	src/app/core/submission/workspaceitem-data.service.ts
#	src/app/core/supervision-order/supervision-order-data.service.ts
#	src/app/core/tasks/claimed-task-data.service.ts
#	src/app/core/tasks/pool-task-data.service.ts
#	src/app/curation-form/curation-form.component.spec.ts
#	src/app/curation-form/curation-form.component.ts
#	src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-field-values/dso-edit-metadata-field-values.component.spec.ts
#	src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-field-values/dso-edit-metadata-field-values.component.ts
#	src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-headers/dso-edit-metadata-headers.component.spec.ts
#	src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-headers/dso-edit-metadata-headers.component.ts
#	src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value-headers/dso-edit-metadata-value-headers.component.ts
#	src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.spec.ts
#	src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.ts
#	src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.spec.ts
#	src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts
#	src/app/dso-shared/dso-edit-metadata/metadata-field-selector/metadata-field-selector.component.spec.ts
#	src/app/dso-shared/dso-edit-metadata/metadata-field-selector/metadata-field-selector.component.ts
#	src/app/dso-shared/dso-shared.module.ts
#	src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.spec.ts
#	src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.ts
#	src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.spec.ts
#	src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.ts
#	src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.spec.ts
#	src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.ts
#	src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.ts
#	src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.ts
#	src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.ts
#	src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.spec.ts
#	src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.ts
#	src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.spec.ts
#	src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.ts
#	src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.spec.ts
#	src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.ts
#	src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.spec.ts
#	src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.ts
#	src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.spec.ts
#	src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.ts
#	src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.spec.ts
#	src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.ts
#	src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-issue/journal-issue-sidebar-search-list-element.component.ts
#	src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-volume/journal-volume-sidebar-search-list-element.component.ts
#	src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal/journal-sidebar-search-list-element.component.ts
#	src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.ts
#	src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.ts
#	src/app/entity-groups/journal-entities/item-pages/journal/journal.component.spec.ts
#	src/app/entity-groups/journal-entities/item-pages/journal/journal.component.ts
#	src/app/entity-groups/journal-entities/journal-entities.module.ts
#	src/app/entity-groups/research-entities/item-grid-elements/org-unit/org-unit-grid-element.component.spec.ts
#	src/app/entity-groups/research-entities/item-grid-elements/org-unit/org-unit-grid-element.component.ts
#	src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.spec.ts
#	src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.ts
#	src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.spec.ts
#	src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.ts
#	src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.ts
#	src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.ts
#	src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.ts
#	src/app/entity-groups/research-entities/item-list-elements/org-unit/org-unit-list-element.component.spec.ts
#	src/app/entity-groups/research-entities/item-list-elements/org-unit/org-unit-list-element.component.ts
#	src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.spec.ts
#	src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.ts
#	src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.spec.ts
#	src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.ts
#	src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.spec.ts
#	src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.ts
#	src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.spec.ts
#	src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.ts
#	src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.spec.ts
#	src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.ts
#	src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/org-unit/org-unit-sidebar-search-list-element.component.ts
#	src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/person/person-sidebar-search-list-element.component.ts
#	src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/project/project-sidebar-search-list-element.component.ts
#	src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.ts
#	src/app/entity-groups/research-entities/item-pages/person/person.component.ts
#	src/app/entity-groups/research-entities/item-pages/project/project.component.ts
#	src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts
#	src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.ts
#	src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.spec.ts
#	src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts
#	src/app/entity-groups/research-entities/metadata-representations/project/project-item-metadata-list-element.component.spec.ts
#	src/app/entity-groups/research-entities/metadata-representations/project/project-item-metadata-list-element.component.ts
#	src/app/entity-groups/research-entities/research-entities.module.ts
#	src/app/entity-groups/research-entities/submission/item-list-elements/external-source-entry/external-source-entry-list-submission-element.component.spec.ts
#	src/app/entity-groups/research-entities/submission/item-list-elements/external-source-entry/external-source-entry-list-submission-element.component.ts
#	src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.spec.ts
#	src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.ts
#	src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-suggestions/org-unit-input-suggestions.component.spec.ts
#	src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-suggestions/org-unit-input-suggestions.component.ts
#	src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.spec.ts
#	src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.ts
#	src/app/entity-groups/research-entities/submission/item-list-elements/person/person-suggestions/person-input-suggestions.component.ts
#	src/app/entity-groups/research-entities/submission/name-variant-modal/name-variant-modal.component.spec.ts
#	src/app/entity-groups/research-entities/submission/name-variant-modal/name-variant-modal.component.ts
#	src/app/footer/footer.component.spec.ts
#	src/app/footer/footer.component.ts
#	src/app/forbidden/forbidden.component.ts
#	src/app/forgot-password/forgot-password-email/forgot-email.component.spec.ts
#	src/app/forgot-password/forgot-password-email/forgot-email.component.ts
#	src/app/forgot-password/forgot-password-email/themed-forgot-email.component.ts
#	src/app/forgot-password/forgot-password-form/forgot-password-form.component.spec.ts
#	src/app/forgot-password/forgot-password-form/forgot-password-form.component.ts
#	src/app/forgot-password/forgot-password-form/themed-forgot-password-form.component.ts
#	src/app/forgot-password/forgot-password-routing.module.ts
#	src/app/forgot-password/forgot-password.module.ts
#	src/app/header-nav-wrapper/header-navbar-wrapper.component.ts
#	src/app/header/context-help-toggle/context-help-toggle.component.spec.ts
#	src/app/header/context-help-toggle/context-help-toggle.component.ts
#	src/app/header/header.component.spec.ts
#	src/app/header/header.component.ts
#	src/app/health-page/health-info/health-info-component/health-info-component.component.spec.ts
#	src/app/health-page/health-info/health-info-component/health-info-component.component.ts
#	src/app/health-page/health-info/health-info.component.spec.ts
#	src/app/health-page/health-info/health-info.component.ts
#	src/app/health-page/health-page.component.spec.ts
#	src/app/health-page/health-page.component.ts
#	src/app/health-page/health-page.module.ts
#	src/app/health-page/health-page.routing.module.ts
#	src/app/health-page/health-panel/health-component/health-component.component.spec.ts
#	src/app/health-page/health-panel/health-component/health-component.component.ts
#	src/app/health-page/health-panel/health-panel.component.spec.ts
#	src/app/health-page/health-panel/health-panel.component.ts
#	src/app/health-page/health-panel/health-status/health-status.component.spec.ts
#	src/app/health-page/health-panel/health-status/health-status.component.ts
#	src/app/home-page/home-news/home-news.component.ts
#	src/app/home-page/home-page-routing.module.ts
#	src/app/home-page/home-page.component.ts
#	src/app/home-page/home-page.module.ts
#	src/app/home-page/recent-item-list/recent-item-list.component.spec.ts
#	src/app/home-page/recent-item-list/recent-item-list.component.ts
#	src/app/home-page/top-level-community-list/top-level-community-list.component.spec.ts
#	src/app/home-page/top-level-community-list/top-level-community-list.component.ts
#	src/app/import-external-page/import-external-page.component.spec.ts
#	src/app/import-external-page/import-external-page.component.ts
#	src/app/import-external-page/import-external-page.module.ts
#	src/app/import-external-page/import-external-routing.module.ts
#	src/app/info/end-user-agreement/end-user-agreement-content/end-user-agreement-content.component.spec.ts
#	src/app/info/end-user-agreement/end-user-agreement-content/end-user-agreement-content.component.ts
#	src/app/info/end-user-agreement/end-user-agreement.component.spec.ts
#	src/app/info/end-user-agreement/end-user-agreement.component.ts
#	src/app/info/feedback/feedback-form/feedback-form.component.spec.ts
#	src/app/info/feedback/feedback-form/feedback-form.component.ts
#	src/app/info/feedback/feedback.component.spec.ts
#	src/app/info/feedback/feedback.component.ts
#	src/app/info/info-routing.module.ts
#	src/app/info/info.module.ts
#	src/app/info/privacy/privacy-content/privacy-content.component.spec.ts
#	src/app/info/privacy/privacy-content/privacy-content.component.ts
#	src/app/info/privacy/privacy.component.spec.ts
#	src/app/info/privacy/privacy.component.ts
#	src/app/init.service.ts
#	src/app/item-page/alerts/item-alerts.component.spec.ts
#	src/app/item-page/alerts/item-alerts.component.ts
#	src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.spec.ts
#	src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.ts
#	src/app/item-page/bitstreams/upload/upload-bitstream.component.spec.ts
#	src/app/item-page/bitstreams/upload/upload-bitstream.component.ts
#	src/app/item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts
#	src/app/item-page/edit-item-page/edit-item-page.component.spec.ts
#	src/app/item-page/edit-item-page/edit-item-page.component.ts
#	src/app/item-page/edit-item-page/edit-item-page.module.ts
#	src/app/item-page/edit-item-page/edit-item-page.routing.module.ts
#	src/app/item-page/edit-item-page/item-access-control/item-access-control.component.spec.ts
#	src/app/item-page/edit-item-page/item-access-control/item-access-control.component.ts
#	src/app/item-page/edit-item-page/item-authorizations/item-authorizations.component.spec.ts
#	src/app/item-page/edit-item-page/item-authorizations/item-authorizations.component.ts
#	src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.spec.ts
#	src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts
#	src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts
#	src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.ts
#	src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.spec.ts
#	src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.ts
#	src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-drag-handle/item-edit-bitstream-drag-handle.component.ts
#	src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.spec.ts
#	src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.ts
#	src/app/item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.spec.ts
#	src/app/item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.ts
#	src/app/item-page/edit-item-page/item-curate/item-curate.component.spec.ts
#	src/app/item-page/edit-item-page/item-curate/item-curate.component.ts
#	src/app/item-page/edit-item-page/item-delete/item-delete.component.spec.ts
#	src/app/item-page/edit-item-page/item-delete/item-delete.component.ts
#	src/app/item-page/edit-item-page/item-move/item-move.component.spec.ts
#	src/app/item-page/edit-item-page/item-move/item-move.component.ts
#	src/app/item-page/edit-item-page/item-operation/item-operation.component.spec.ts
#	src/app/item-page/edit-item-page/item-operation/item-operation.component.ts
#	src/app/item-page/edit-item-page/item-private/item-private.component.spec.ts
#	src/app/item-page/edit-item-page/item-private/item-private.component.ts
#	src/app/item-page/edit-item-page/item-public/item-public.component.spec.ts
#	src/app/item-page/edit-item-page/item-public/item-public.component.ts
#	src/app/item-page/edit-item-page/item-register-doi/item-register-doi.component.spec.ts
#	src/app/item-page/edit-item-page/item-register-doi/item-register-doi.component.ts
#	src/app/item-page/edit-item-page/item-reinstate/item-reinstate.component.spec.ts
#	src/app/item-page/edit-item-page/item-reinstate/item-reinstate.component.ts
#	src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.spec.ts
#	src/app/item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts
#	src/app/item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.spec.ts
#	src/app/item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.ts
#	src/app/item-page/edit-item-page/item-relationships/item-relationships.component.spec.ts
#	src/app/item-page/edit-item-page/item-relationships/item-relationships.component.ts
#	src/app/item-page/edit-item-page/item-status/item-status.component.ts
#	src/app/item-page/edit-item-page/item-version-history/item-version-history.component.spec.ts
#	src/app/item-page/edit-item-page/item-version-history/item-version-history.component.ts
#	src/app/item-page/edit-item-page/item-withdraw/item-withdraw.component.spec.ts
#	src/app/item-page/edit-item-page/item-withdraw/item-withdraw.component.ts
#	src/app/item-page/edit-item-page/modify-item-overview/modify-item-overview.component.ts
#	src/app/item-page/edit-item-page/simple-item-action/abstract-simple-item-action.component.spec.ts
#	src/app/item-page/edit-item-page/simple-item-action/abstract-simple-item-action.component.ts
#	src/app/item-page/edit-item-page/virtual-metadata/virtual-metadata.component.spec.ts
#	src/app/item-page/edit-item-page/virtual-metadata/virtual-metadata.component.ts
#	src/app/item-page/field-components/collections/collections.component.spec.ts
#	src/app/item-page/field-components/collections/collections.component.ts
#	src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.spec.ts
#	src/app/item-page/field-components/metadata-uri-values/metadata-uri-values.component.ts
#	src/app/item-page/field-components/metadata-values/metadata-values.component.spec.ts
#	src/app/item-page/field-components/metadata-values/metadata-values.component.ts
#	src/app/item-page/full/field-components/file-section/full-file-section.component.spec.ts
#	src/app/item-page/full/field-components/file-section/full-file-section.component.ts
#	src/app/item-page/full/full-item-page.component.spec.ts
#	src/app/item-page/full/full-item-page.component.ts
#	src/app/item-page/item-page-routing.module.ts
#	src/app/item-page/item-page.module.ts
#	src/app/item-page/item-shared.module.ts
#	src/app/item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts
#	src/app/item-page/media-viewer/media-viewer.component.spec.ts
#	src/app/item-page/media-viewer/media-viewer.component.ts
#	src/app/item-page/mirador-viewer/mirador-viewer.component.spec.ts
#	src/app/item-page/mirador-viewer/mirador-viewer.component.ts
#	src/app/item-page/orcid-page/orcid-auth/orcid-auth.component.spec.ts
#	src/app/item-page/orcid-page/orcid-auth/orcid-auth.component.ts
#	src/app/item-page/orcid-page/orcid-page.component.html
#	src/app/item-page/orcid-page/orcid-page.component.spec.ts
#	src/app/item-page/orcid-page/orcid-page.component.ts
#	src/app/item-page/orcid-page/orcid-queue/orcid-queue.component.spec.ts
#	src/app/item-page/orcid-page/orcid-queue/orcid-queue.component.ts
#	src/app/item-page/orcid-page/orcid-sync-settings/orcid-sync-settings.component.spec.ts
#	src/app/item-page/orcid-page/orcid-sync-settings/orcid-sync-settings.component.ts
#	src/app/item-page/simple/field-components/file-section/file-section.component.spec.ts
#	src/app/item-page/simple/field-components/file-section/file-section.component.ts
#	src/app/item-page/simple/field-components/file-section/themed-file-section.component.ts
#	src/app/item-page/simple/field-components/specific-field/abstract/item-page-abstract-field.component.spec.ts
#	src/app/item-page/simple/field-components/specific-field/abstract/item-page-abstract-field.component.ts
#	src/app/item-page/simple/field-components/specific-field/author/item-page-author-field.component.spec.ts
#	src/app/item-page/simple/field-components/specific-field/author/item-page-author-field.component.ts
#	src/app/item-page/simple/field-components/specific-field/date/item-page-date-field.component.spec.ts
#	src/app/item-page/simple/field-components/specific-field/date/item-page-date-field.component.ts
#	src/app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component.spec.ts
#	src/app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component.ts
#	src/app/item-page/simple/field-components/specific-field/img/item-page-img-field.component.spec.ts
#	src/app/item-page/simple/field-components/specific-field/img/item-page-img-field.component.ts
#	src/app/item-page/simple/field-components/specific-field/item-page-field.component.spec.ts
#	src/app/item-page/simple/field-components/specific-field/item-page-field.component.ts
#	src/app/item-page/simple/field-components/specific-field/title/item-page-title-field.component.spec.ts
#	src/app/item-page/simple/field-components/specific-field/title/item-page-title-field.component.ts
#	src/app/item-page/simple/field-components/specific-field/uri/item-page-uri-field.component.spec.ts
#	src/app/item-page/simple/field-components/specific-field/uri/item-page-uri-field.component.ts
#	src/app/item-page/simple/item-page.component.spec.ts
#	src/app/item-page/simple/item-page.component.ts
#	src/app/item-page/simple/item-types/publication/publication.component.spec.ts
#	src/app/item-page/simple/item-types/shared/item.component.spec.ts
#	src/app/item-page/simple/item-types/shared/item.component.ts
#	src/app/item-page/simple/item-types/untyped-item/untyped-item.component.spec.ts
#	src/app/item-page/simple/metadata-representation-list/metadata-representation-list.component.spec.ts
#	src/app/item-page/simple/metadata-representation-list/metadata-representation-list.component.ts
#	src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.spec.ts
#	src/app/item-page/simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component.ts
#	src/app/item-page/simple/qa-event-notification/qa-event-notification.component.spec.ts
#	src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts
#	src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.spec.ts
#	src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.ts
#	src/app/item-page/simple/related-entities/tabbed-related-entities-search/tabbed-related-entities-search.component.spec.ts
#	src/app/item-page/simple/related-entities/tabbed-related-entities-search/tabbed-related-entities-search.component.ts
#	src/app/item-page/simple/related-items/related-items-component.ts
#	src/app/item-page/simple/related-items/related-items.component.spec.ts
#	src/app/item-page/version-page/version-page/version-page.component.ts
#	src/app/item-page/versions/item-versions-delete-modal/item-versions-delete-modal.component.spec.ts
#	src/app/item-page/versions/item-versions-delete-modal/item-versions-delete-modal.component.ts
#	src/app/item-page/versions/item-versions-summary-modal/item-versions-summary-modal.component.spec.ts
#	src/app/item-page/versions/item-versions-summary-modal/item-versions-summary-modal.component.ts
#	src/app/item-page/versions/item-versions.component.spec.ts
#	src/app/item-page/versions/item-versions.component.ts
#	src/app/item-page/versions/item-versions.module.ts
#	src/app/item-page/versions/notice/item-versions-notice.component.spec.ts
#	src/app/item-page/versions/notice/item-versions-notice.component.ts
#	src/app/login-page/login-page-routing.module.ts
#	src/app/login-page/login-page.component.spec.ts
#	src/app/login-page/login-page.component.ts
#	src/app/login-page/login-page.module.ts
#	src/app/login-page/themed-login-page.component.ts
#	src/app/logout-page/logout-page-routing.module.ts
#	src/app/logout-page/logout-page.component.spec.ts
#	src/app/logout-page/logout-page.component.ts
#	src/app/logout-page/logout-page.module.ts
#	src/app/logout-page/themed-logout-page.component.ts
#	src/app/lookup-by-id/lookup-by-id-routes.ts
#	src/app/lookup-by-id/lookup-by-id.module.ts
#	src/app/lookup-by-id/objectnotfound/objectnotfound.component.spec.ts
#	src/app/lookup-by-id/objectnotfound/objectnotfound.component.ts
#	src/app/menu.resolver.spec.ts
#	src/app/menu.resolver.ts
#	src/app/my-dspace-page/collection-selector/collection-selector.component.spec.ts
#	src/app/my-dspace-page/collection-selector/collection-selector.component.ts
#	src/app/my-dspace-page/my-dspace-configuration.service.ts
#	src/app/my-dspace-page/my-dspace-new-submission/my-dspace-new-external-dropdown/my-dspace-new-external-dropdown.component.spec.ts
#	src/app/my-dspace-page/my-dspace-new-submission/my-dspace-new-external-dropdown/my-dspace-new-external-dropdown.component.ts
#	src/app/my-dspace-page/my-dspace-new-submission/my-dspace-new-submission-dropdown/my-dspace-new-submission-dropdown.component.spec.ts
#	src/app/my-dspace-page/my-dspace-new-submission/my-dspace-new-submission-dropdown/my-dspace-new-submission-dropdown.component.ts
#	src/app/my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.spec.ts
#	src/app/my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts
#	src/app/my-dspace-page/my-dspace-page-routing.module.ts
#	src/app/my-dspace-page/my-dspace-page.component.spec.ts
#	src/app/my-dspace-page/my-dspace-page.component.ts
#	src/app/my-dspace-page/my-dspace-page.module.ts
#	src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.spec.ts
#	src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.ts
#	src/app/my-dspace-page/my-dspace-search.module.ts
#	src/app/my-dspace-page/themed-my-dspace-page.component.ts
#	src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.spec.ts
#	src/app/navbar/expandable-navbar-section/expandable-navbar-section.component.ts
#	src/app/navbar/navbar-section/navbar-section.component.spec.ts
#	src/app/navbar/navbar-section/navbar-section.component.ts
#	src/app/navbar/navbar.component.spec.ts
#	src/app/navbar/navbar.component.ts
#	src/app/navbar/navbar.module.ts
#	src/app/notifications/notifications.module.ts
#	src/app/notifications/qa/events/ePerson-data/ePerson-data.component.spec.ts
#	src/app/notifications/qa/events/ePerson-data/ePerson-data.component.ts
#	src/app/notifications/qa/events/quality-assurance-events.component.spec.ts
#	src/app/notifications/qa/events/quality-assurance-events.component.ts
#	src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.spec.ts
#	src/app/notifications/qa/project-entry-import-modal/project-entry-import-modal.component.ts
#	src/app/notifications/qa/source/quality-assurance-source.component.spec.ts
#	src/app/notifications/qa/source/quality-assurance-source.component.ts
#	src/app/notifications/qa/topics/quality-assurance-topics.component.spec.ts
#	src/app/notifications/qa/topics/quality-assurance-topics.component.ts
#	src/app/notifications/suggestion-actions/suggestion-actions.component.ts
#	src/app/notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component.ts
#	src/app/notifications/suggestion-list-element/suggestion-list-element.component.spec.ts
#	src/app/notifications/suggestion-list-element/suggestion-list-element.component.ts
#	src/app/notifications/suggestion-targets/publication-claim/publication-claim.component.ts
#	src/app/notifications/suggestions-notification/suggestions-notification.component.ts
#	src/app/notifications/suggestions-popup/suggestions-popup.component.spec.ts
#	src/app/notifications/suggestions-popup/suggestions-popup.component.ts
#	src/app/page-error/page-error.component.spec.ts
#	src/app/page-error/page-error.component.ts
#	src/app/page-internal-server-error/page-internal-server-error.component.ts
#	src/app/pagenotfound/pagenotfound.component.ts
#	src/app/process-page/detail/process-detail-field/process-detail-field.component.spec.ts
#	src/app/process-page/detail/process-detail-field/process-detail-field.component.ts
#	src/app/process-page/detail/process-detail.component.spec.ts
#	src/app/process-page/detail/process-detail.component.ts
#	src/app/process-page/form/process-form.component.spec.ts
#	src/app/process-page/form/process-form.component.ts
#	src/app/process-page/form/process-parameters/parameter-select/parameter-select.component.spec.ts
#	src/app/process-page/form/process-parameters/parameter-select/parameter-select.component.ts
#	src/app/process-page/form/process-parameters/parameter-value-input/boolean-value-input/boolean-value-input.component.spec.ts
#	src/app/process-page/form/process-parameters/parameter-value-input/boolean-value-input/boolean-value-input.component.ts
#	src/app/process-page/form/process-parameters/parameter-value-input/date-value-input/date-value-input.component.spec.ts
#	src/app/process-page/form/process-parameters/parameter-value-input/date-value-input/date-value-input.component.ts
#	src/app/process-page/form/process-parameters/parameter-value-input/file-value-input/file-value-input.component.spec.ts
#	src/app/process-page/form/process-parameters/parameter-value-input/file-value-input/file-value-input.component.ts
#	src/app/process-page/form/process-parameters/parameter-value-input/parameter-value-input.component.spec.ts
#	src/app/process-page/form/process-parameters/parameter-value-input/parameter-value-input.component.ts
#	src/app/process-page/form/process-parameters/parameter-value-input/string-value-input/string-value-input.component.spec.ts
#	src/app/process-page/form/process-parameters/parameter-value-input/string-value-input/string-value-input.component.ts
#	src/app/process-page/form/process-parameters/process-parameters.component.spec.ts
#	src/app/process-page/form/process-parameters/process-parameters.component.ts
#	src/app/process-page/form/script-help/script-help.component.spec.ts
#	src/app/process-page/form/script-help/script-help.component.ts
#	src/app/process-page/form/scripts-select/scripts-select.component.spec.ts
#	src/app/process-page/form/scripts-select/scripts-select.component.ts
#	src/app/process-page/new/new-process.component.spec.ts
#	src/app/process-page/overview/process-overview.component.spec.ts
#	src/app/process-page/overview/process-overview.component.ts
#	src/app/process-page/overview/table/process-overview-table.component.ts
#	src/app/process-page/process-page-routing.module.ts
#	src/app/process-page/process-page-shared.module.ts
#	src/app/process-page/process-page.module.ts
#	src/app/profile-page/profile-claim-item-modal/profile-claim-item-modal.component.spec.ts
#	src/app/profile-page/profile-claim-item-modal/profile-claim-item-modal.component.ts
#	src/app/profile-page/profile-page-metadata-form/profile-page-metadata-form.component.spec.ts
#	src/app/profile-page/profile-page-metadata-form/profile-page-metadata-form.component.ts
#	src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.spec.ts
#	src/app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component.ts
#	src/app/profile-page/profile-page-routing.module.ts
#	src/app/profile-page/profile-page-security-form/profile-page-security-form.component.spec.ts
#	src/app/profile-page/profile-page-security-form/profile-page-security-form.component.ts
#	src/app/profile-page/profile-page.component.spec.ts
#	src/app/profile-page/profile-page.component.ts
#	src/app/profile-page/profile-page.module.ts
#	src/app/profile-page/themed-profile-page.component.ts
#	src/app/quality-assurance-notifications-pages/notifications-pages-routing.module.ts
#	src/app/quality-assurance-notifications-pages/notifications-pages.module.ts
#	src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.spec.ts
#	src/app/quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component.ts
#	src/app/quality-assurance-notifications-pages/quality-assurance-events-page/quality-assurance-events-page.component.spec.ts
#	src/app/quality-assurance-notifications-pages/quality-assurance-events-page/quality-assurance-events-page.component.ts
#	src/app/quality-assurance-notifications-pages/quality-assurance-source-page-component/quality-assurance-source-page.component.spec.ts
#	src/app/quality-assurance-notifications-pages/quality-assurance-topics-page/quality-assurance-topics-page.component.spec.ts
#	src/app/quality-assurance-notifications-pages/quality-assurance-topics-page/quality-assurance-topics-page.component.ts
#	src/app/register-email-form/register-email-form.component.spec.ts
#	src/app/register-email-form/register-email-form.component.ts
#	src/app/register-email-form/register-email-form.module.ts
#	src/app/register-page/create-profile/create-profile.component.spec.ts
#	src/app/register-page/create-profile/create-profile.component.ts
#	src/app/register-page/create-profile/themed-create-profile.component.ts
#	src/app/register-page/register-email/register-email.component.spec.ts
#	src/app/register-page/register-email/register-email.component.ts
#	src/app/register-page/register-page-routing.module.ts
#	src/app/register-page/register-page.module.ts
#	src/app/request-copy/deny-request-copy/deny-request-copy.component.spec.ts
#	src/app/request-copy/deny-request-copy/deny-request-copy.component.ts
#	src/app/request-copy/email-request-copy/email-request-copy.component.spec.ts
#	src/app/request-copy/email-request-copy/email-request-copy.component.ts
#	src/app/request-copy/grant-deny-request-copy/grant-deny-request-copy.component.spec.ts
#	src/app/request-copy/grant-deny-request-copy/grant-deny-request-copy.component.ts
#	src/app/request-copy/grant-request-copy/grant-request-copy.component.spec.ts
#	src/app/request-copy/grant-request-copy/grant-request-copy.component.ts
#	src/app/request-copy/request-copy-routing.module.ts
#	src/app/request-copy/request-copy.module.ts
#	src/app/root.module.ts
#	src/app/root/root.component.spec.ts
#	src/app/root/root.component.ts
#	src/app/search-navbar/search-navbar.component.spec.ts
#	src/app/search-navbar/search-navbar.component.ts
#	src/app/search-page/configuration-search-page.component.ts
#	src/app/search-page/search-page-routing.module.ts
#	src/app/search-page/search-page.component.ts
#	src/app/search-page/search-page.module.ts
#	src/app/shared/abstract-component-loader/dynamic-component-loader.directive.ts
#	src/app/shared/access-control-form-container/access-control-array-form/access-control-array-form.component.spec.ts
#	src/app/shared/access-control-form-container/access-control-array-form/access-control-array-form.component.ts
#	src/app/shared/access-control-form-container/access-control-array-form/to-date.pipe.ts
#	src/app/shared/access-control-form-container/access-control-form-container.component.spec.ts
#	src/app/shared/access-control-form-container/access-control-form-container.component.ts
#	src/app/shared/access-control-form-container/access-control-form.module.ts
#	src/app/shared/access-control-form-container/item-access-control-select-bitstreams-modal/item-access-control-select-bitstreams-modal.component.spec.ts
#	src/app/shared/access-control-form-container/item-access-control-select-bitstreams-modal/item-access-control-select-bitstreams-modal.component.ts
#	src/app/shared/alert/alert.component.spec.ts
#	src/app/shared/alert/alert.component.ts
#	src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts
#	src/app/shared/auth-nav-menu/auth-nav-menu.component.ts
#	src/app/shared/auth-nav-menu/user-menu/themed-user-menu.component.ts
#	src/app/shared/auth-nav-menu/user-menu/user-menu.component.spec.ts
#	src/app/shared/auth-nav-menu/user-menu/user-menu.component.ts
#	src/app/shared/browse-by/browse-by.component.spec.ts
#	src/app/shared/browse-by/browse-by.component.ts
#	src/app/shared/browse-by/shared-browse-by.module.ts
#	src/app/shared/browse-by/themed-browse-by.component.ts
#	src/app/shared/collection-dropdown/collection-dropdown.component.spec.ts
#	src/app/shared/collection-dropdown/collection-dropdown.component.ts
#	src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.spec.ts
#	src/app/shared/comcol/comcol-forms/comcol-form/comcol-form.component.ts
#	src/app/shared/comcol/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts
#	src/app/shared/comcol/comcol-forms/create-comcol-page/create-comcol-page.component.ts
#	src/app/shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts
#	src/app/shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts
#	src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.spec.ts
#	src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.ts
#	src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.spec.ts
#	src/app/shared/comcol/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts
#	src/app/shared/comcol/comcol-forms/edit-comcol-page/edit-comcol-page.component.spec.ts
#	src/app/shared/comcol/comcol-forms/edit-comcol-page/edit-comcol-page.component.ts
#	src/app/shared/comcol/comcol-page-browse-by/comcol-page-browse-by.component.ts
#	src/app/shared/comcol/comcol-page-content/comcol-page-content.component.ts
#	src/app/shared/comcol/comcol-page-handle/comcol-page-handle.component.spec.ts
#	src/app/shared/comcol/comcol-page-handle/comcol-page-handle.component.ts
#	src/app/shared/comcol/comcol-page-header/comcol-page-header.component.ts
#	src/app/shared/comcol/comcol.module.ts
#	src/app/shared/comcol/sections/comcol-search-section/comcol-search-section.component.ts
#	src/app/shared/confirmation-modal/confirmation-modal.component.spec.ts
#	src/app/shared/context-help-wrapper/context-help-wrapper.component.spec.ts
#	src/app/shared/context-help-wrapper/context-help-wrapper.component.ts
#	src/app/shared/context-help.directive.spec.ts
#	src/app/shared/correction-suggestion/withdrawn-reinstate-modal.component.ts
#	src/app/shared/ds-select/ds-select.component.ts
#	src/app/shared/dso-page/dso-edit-menu.resolver.spec.ts
#	src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.spec.ts
#	src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.ts
#	src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.spec.ts
#	src/app/shared/dso-page/dso-edit-menu/dso-edit-menu-section/dso-edit-menu-section.component.ts
#	src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.spec.ts
#	src/app/shared/dso-page/dso-edit-menu/dso-edit-menu.component.ts
#	src/app/shared/dso-page/dso-page.module.ts
#	src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.spec.ts
#	src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.ts
#	src/app/shared/dso-selector/dso-selector/dso-selector.component.spec.ts
#	src/app/shared/dso-selector/dso-selector/dso-selector.component.ts
#	src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.spec.ts
#	src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts
#	src/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/themed-create-collection-parent-selector.component.ts
#	src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.spec.ts
#	src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts
#	src/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/themed-create-community-parent-selector.component.ts
#	src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.spec.ts
#	src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts
#	src/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/themed-create-item-parent-selector.component.ts
#	src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.spec.ts
#	src/app/shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component.spec.ts
#	src/app/shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component.ts
#	src/app/shared/dso-selector/modal-wrappers/edit-collection-selector/themed-edit-collection-selector.component.ts
#	src/app/shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component.spec.ts
#	src/app/shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component.ts
#	src/app/shared/dso-selector/modal-wrappers/edit-community-selector/themed-edit-community-selector.component.ts
#	src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.spec.ts
#	src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts
#	src/app/shared/dso-selector/modal-wrappers/edit-item-selector/themed-edit-item-selector.component.ts
#	src/app/shared/dso-selector/modal-wrappers/export-batch-selector/export-batch-selector.component.spec.ts
#	src/app/shared/dso-selector/modal-wrappers/export-batch-selector/export-batch-selector.component.ts
#	src/app/shared/dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component.spec.ts
#	src/app/shared/dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component.ts
#	src/app/shared/dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component.spec.ts
#	src/app/shared/dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component.ts
#	src/app/shared/entity-dropdown/entity-dropdown.component.spec.ts
#	src/app/shared/entity-dropdown/entity-dropdown.component.ts
#	src/app/shared/eperson-group-list/eperson-group-list.component.spec.ts
#	src/app/shared/eperson-group-list/eperson-group-list.component.ts
#	src/app/shared/eperson-group-list/eperson-search-box/eperson-search-box.component.spec.ts
#	src/app/shared/eperson-group-list/eperson-search-box/eperson-search-box.component.ts
#	src/app/shared/eperson-group-list/group-search-box/group-search-box.component.spec.ts
#	src/app/shared/eperson-group-list/group-search-box/group-search-box.component.ts
#	src/app/shared/error/error.component.spec.ts
#	src/app/shared/error/error.component.ts
#	src/app/shared/file-download-link/file-download-link.component.spec.ts
#	src/app/shared/file-download-link/file-download-link.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker-inline/dynamic-date-picker-inline.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker-inline/dynamic-date-picker-inline.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/form-group/dynamic-form-group.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.components.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/models/tag/dynamic-tag.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.spec.ts
#	src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.ts
#	src/app/shared/form/chips/chips.component.spec.ts
#	src/app/shared/form/chips/chips.component.ts
#	src/app/shared/form/directives/authority-confidence-state.directive.ts
#	src/app/shared/form/form.component.spec.ts
#	src/app/shared/form/form.component.ts
#	src/app/shared/form/form.module.ts
#	src/app/shared/form/number-picker/number-picker.component.spec.ts
#	src/app/shared/form/number-picker/number-picker.component.ts
#	src/app/shared/form/vocabulary-treeview-modal/vocabulary-treeview-modal.component.spec.ts
#	src/app/shared/form/vocabulary-treeview-modal/vocabulary-treeview-modal.component.ts
#	src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.spec.ts
#	src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts
#	src/app/shared/google-recaptcha/google-recaptcha.component.spec.ts
#	src/app/shared/hover-class.directive.spec.ts
#	src/app/shared/hover-class.directive.ts
#	src/app/shared/idle-modal/idle-modal.component.spec.ts
#	src/app/shared/idle-modal/idle-modal.component.ts
#	src/app/shared/impersonate-navbar/impersonate-navbar.component.spec.ts
#	src/app/shared/impersonate-navbar/impersonate-navbar.component.ts
#	src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.spec.ts
#	src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.ts
#	src/app/shared/input-suggestions/filter-suggestions/filter-input-suggestions.component.spec.ts
#	src/app/shared/input-suggestions/filter-suggestions/filter-input-suggestions.component.ts
#	src/app/shared/input-suggestions/input-suggestions.component.spec.ts
#	src/app/shared/input-suggestions/input-suggestions.component.ts
#	src/app/shared/input-suggestions/validation-suggestions/validation-suggestions.component.spec.ts
#	src/app/shared/input-suggestions/validation-suggestions/validation-suggestions.component.ts
#	src/app/shared/lang-switch/lang-switch.component.spec.ts
#	src/app/shared/lang-switch/lang-switch.component.ts
#	src/app/shared/loading/loading.component.spec.ts
#	src/app/shared/loading/loading.component.ts
#	src/app/shared/log-in/container/log-in-container.component.spec.ts
#	src/app/shared/log-in/container/log-in-container.component.ts
#	src/app/shared/log-in/log-in.component.spec.ts
#	src/app/shared/log-in/log-in.component.ts
#	src/app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.spec.ts
#	src/app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.ts
#	src/app/shared/log-in/methods/log-in.methods-decorator.ts
#	src/app/shared/log-in/methods/password/log-in-password.component.spec.ts
#	src/app/shared/log-in/methods/password/log-in-password.component.ts
#	src/app/shared/log-in/themed-log-in.component.ts
#	src/app/shared/log-out/log-out.component.spec.ts
#	src/app/shared/log-out/log-out.component.ts
#	src/app/shared/menu/menu-item/external-link-menu-item.component.spec.ts
#	src/app/shared/menu/menu-item/external-link-menu-item.component.ts
#	src/app/shared/menu/menu-item/link-menu-item.component.spec.ts
#	src/app/shared/menu/menu-item/link-menu-item.component.ts
#	src/app/shared/menu/menu-item/onclick-menu-item.component.spec.ts
#	src/app/shared/menu/menu-item/onclick-menu-item.component.ts
#	src/app/shared/menu/menu-item/text-menu-item.component.spec.ts
#	src/app/shared/menu/menu-item/text-menu-item.component.ts
#	src/app/shared/menu/menu-section.decorator.ts
#	src/app/shared/menu/menu-section/menu-section.component.spec.ts
#	src/app/shared/menu/menu-section/menu-section.component.ts
#	src/app/shared/menu/menu.component.ts
#	src/app/shared/menu/menu.module.ts
#	src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts
#	src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.ts
#	src/app/shared/metadata-representation/metadata-representation-loader.component.spec.ts
#	src/app/shared/metadata-representation/metadata-representation-loader.component.ts
#	src/app/shared/mydspace-actions/claimed-task/approve/claimed-task-actions-approve.component.spec.ts
#	src/app/shared/mydspace-actions/claimed-task/approve/claimed-task-actions-approve.component.ts
#	src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.spec.ts
#	src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.ts
#	src/app/shared/mydspace-actions/claimed-task/decline-task/claimed-task-actions-decline-task.component.spec.ts
#	src/app/shared/mydspace-actions/claimed-task/decline-task/claimed-task-actions-decline-task.component.ts
#	src/app/shared/mydspace-actions/claimed-task/edit-metadata/claimed-task-actions-edit-metadata.component.spec.ts
#	src/app/shared/mydspace-actions/claimed-task/edit-metadata/claimed-task-actions-edit-metadata.component.ts
#	src/app/shared/mydspace-actions/claimed-task/rating/advanced-claimed-task-action-rating.component.ts
#	src/app/shared/mydspace-actions/claimed-task/reject/claimed-task-actions-reject.component.spec.ts
#	src/app/shared/mydspace-actions/claimed-task/reject/claimed-task-actions-reject.component.ts
#	src/app/shared/mydspace-actions/claimed-task/return-to-pool/claimed-task-actions-return-to-pool.component.spec.ts
#	src/app/shared/mydspace-actions/claimed-task/return-to-pool/claimed-task-actions-return-to-pool.component.ts
#	src/app/shared/mydspace-actions/claimed-task/select-reviewer/advanced-claimed-task-action-select-reviewer.component.spec.ts
#	src/app/shared/mydspace-actions/claimed-task/select-reviewer/advanced-claimed-task-action-select-reviewer.component.ts
#	src/app/shared/mydspace-actions/claimed-task/switcher/claimed-task-actions-decorator.spec.ts
#	src/app/shared/mydspace-actions/claimed-task/switcher/claimed-task-actions-loader.component.spec.ts
#	src/app/shared/mydspace-actions/claimed-task/switcher/claimed-task-actions-loader.component.ts
#	src/app/shared/mydspace-actions/item/item-actions.component.spec.ts
#	src/app/shared/mydspace-actions/item/item-actions.component.ts
#	src/app/shared/mydspace-actions/mydspace-actions.module.ts
#	src/app/shared/mydspace-actions/mydspace-reloadable-actions.spec.ts
#	src/app/shared/mydspace-actions/pool-task/pool-task-actions.component.spec.ts
#	src/app/shared/mydspace-actions/pool-task/pool-task-actions.component.ts
#	src/app/shared/mydspace-actions/workflowitem/workflowitem-actions.component.spec.ts
#	src/app/shared/mydspace-actions/workflowitem/workflowitem-actions.component.ts
#	src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.spec.ts
#	src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts
#	src/app/shared/notifications/notification/notification.component.spec.ts
#	src/app/shared/notifications/notification/notification.component.ts
#	src/app/shared/notifications/notifications-board/notifications-board.component.spec.ts
#	src/app/shared/notifications/notifications-board/notifications-board.component.ts
#	src/app/shared/notifications/notifications.reducers.spec.ts
#	src/app/shared/notifications/notifications.service.spec.ts
#	src/app/shared/object-collection/object-collection.component.spec.ts
#	src/app/shared/object-collection/object-collection.component.ts
#	src/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.spec.ts
#	src/app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component.ts
#	src/app/shared/object-collection/shared/badges/badges.component.spec.ts
#	src/app/shared/object-collection/shared/badges/badges.component.ts
#	src/app/shared/object-collection/shared/badges/my-dspace-status-badge/my-dspace-status-badge.component.spec.ts
#	src/app/shared/object-collection/shared/badges/my-dspace-status-badge/my-dspace-status-badge.component.ts
#	src/app/shared/object-collection/shared/badges/status-badge/status-badge.component.spec.ts
#	src/app/shared/object-collection/shared/badges/status-badge/status-badge.component.ts
#	src/app/shared/object-collection/shared/badges/type-badge/type-badge.component.spec.ts
#	src/app/shared/object-collection/shared/badges/type-badge/type-badge.component.ts
#	src/app/shared/object-collection/shared/importable-list-item-control/importable-list-item-control.component.ts
#	src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.spec.ts
#	src/app/shared/object-collection/shared/mydspace-item-collection/item-collection.component.ts
#	src/app/shared/object-collection/shared/mydspace-item-submitter/item-submitter.component.spec.ts
#	src/app/shared/object-collection/shared/mydspace-item-submitter/item-submitter.component.ts
#	src/app/shared/object-collection/shared/selectable-list-item-control/selectable-list-item-control.component.spec.ts
#	src/app/shared/object-collection/shared/selectable-list-item-control/selectable-list-item-control.component.ts
#	src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.spec.ts
#	src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.ts
#	src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component.spec.ts
#	src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component.ts
#	src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.spec.ts
#	src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.ts
#	src/app/shared/object-detail/my-dspace-result-detail-element/item-search-result/item-search-result-detail-element.component.spec.ts
#	src/app/shared/object-detail/my-dspace-result-detail-element/item-search-result/item-search-result-detail-element.component.ts
#	src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.spec.ts
#	src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.ts
#	src/app/shared/object-detail/my-dspace-result-detail-element/search-result-detail-element.component.ts
#	src/app/shared/object-detail/my-dspace-result-detail-element/workflow-item-search-result/workflow-item-search-result-detail-element.component.spec.ts
#	src/app/shared/object-detail/my-dspace-result-detail-element/workflow-item-search-result/workflow-item-search-result-detail-element.component.ts
#	src/app/shared/object-detail/my-dspace-result-detail-element/workspace-item-search-result/workspace-item-search-result-detail-element.component.spec.ts
#	src/app/shared/object-detail/my-dspace-result-detail-element/workspace-item-search-result/workspace-item-search-result-detail-element.component.ts
#	src/app/shared/object-detail/object-detail.component.spec.ts
#	src/app/shared/object-detail/object-detail.component.ts
#	src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.spec.ts
#	src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts
#	src/app/shared/object-grid/community-grid-element/community-grid-element.component.spec.ts
#	src/app/shared/object-grid/community-grid-element/community-grid-element.component.ts
#	src/app/shared/object-grid/item-grid-element/item-types/item/item-grid-element.component.spec.ts
#	src/app/shared/object-grid/item-grid-element/item-types/item/item-grid-element.component.ts
#	src/app/shared/object-grid/object-grid.component.ts
#	src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts
#	src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts
#	src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts
#	src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.ts
#	src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.spec.ts
#	src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.ts
#	src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts
#	src/app/shared/object-list/bitstream-list-item/bitstream-list-item.component.spec.ts
#	src/app/shared/object-list/bitstream-list-item/bitstream-list-item.component.ts
#	src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.spec.ts
#	src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.ts
#	src/app/shared/object-list/bundle-list-element/bundle-list-element.component.ts
#	src/app/shared/object-list/collection-list-element/collection-list-element.component.spec.ts
#	src/app/shared/object-list/collection-list-element/collection-list-element.component.ts
#	src/app/shared/object-list/community-list-element/community-list-element.component.spec.ts
#	src/app/shared/object-list/community-list-element/community-list-element.component.ts
#	src/app/shared/object-list/identifier-data/identifier-data.component.ts
#	src/app/shared/object-list/item-list-element/item-types/item/item-list-element.component.spec.ts
#	src/app/shared/object-list/item-list-element/item-types/item/item-list-element.component.ts
#	src/app/shared/object-list/metadata-representation-list-element/browse-link/browse-link-metadata-list-element.component.spec.ts
#	src/app/shared/object-list/metadata-representation-list-element/browse-link/browse-link-metadata-list-element.component.ts
#	src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-list-element.component.spec.ts
#	src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-list-element.component.ts
#	src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component.ts
#	src/app/shared/object-list/metadata-representation-list-element/metadata-representation-list-element.component.spec.ts
#	src/app/shared/object-list/metadata-representation-list-element/metadata-representation-list-element.component.ts
#	src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.spec.ts
#	src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.ts
#	src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-approved-search-result/claimed-approved-search-result-list-element.component.spec.ts
#	src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-approved-search-result/claimed-approved-search-result-list-element.component.ts
#	src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-search-result/claimed-declined-search-result-list-element.component.spec.ts
#	src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-search-result/claimed-declined-search-result-list-element.component.ts
#	src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-task-search-result/claimed-declined-task-search-result-list-element.component.spec.ts
#	src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-task-search-result/claimed-declined-task-search-result-list-element.component.ts
#	src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.spec.ts
#	src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.ts
#	src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.spec.ts
#	src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.ts
#	src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/themed-item-list-preview.component.ts
#	src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.spec.ts
#	src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.ts
#	src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.spec.ts
#	src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.ts
#	src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts
#	src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.ts
#	src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts
#	src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.ts
#	src/app/shared/object-list/object-list.component.spec.ts
#	src/app/shared/object-list/object-list.component.ts
#	src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts
#	src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.ts
#	src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts
#	src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.ts
#	src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts
#	src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.ts
#	src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts
#	src/app/shared/object-list/sidebar-search-list-element/collection/collection-sidebar-search-list-element.component.ts
#	src/app/shared/object-list/sidebar-search-list-element/community/community-sidebar-search-list-element.component.ts
#	src/app/shared/object-list/sidebar-search-list-element/item-types/publication/publication-sidebar-search-list-element.component.ts
#	src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.spec.ts
#	src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.ts
#	src/app/shared/object-select/collection-select/collection-select.component.spec.ts
#	src/app/shared/object-select/collection-select/collection-select.component.ts
#	src/app/shared/object-select/item-select/item-select.component.spec.ts
#	src/app/shared/object-select/item-select/item-select.component.ts
#	src/app/shared/page-size-selector/page-size-selector.component.spec.ts
#	src/app/shared/page-size-selector/page-size-selector.component.ts
#	src/app/shared/pagination/pagination.component.spec.ts
#	src/app/shared/pagination/pagination.component.ts
#	src/app/shared/resource-policies/create/resource-policy-create.component.spec.ts
#	src/app/shared/resource-policies/create/resource-policy-create.component.ts
#	src/app/shared/resource-policies/edit/resource-policy-edit.component.spec.ts
#	src/app/shared/resource-policies/edit/resource-policy-edit.component.ts
#	src/app/shared/resource-policies/entry/resource-policy-entry.component.spec.ts
#	src/app/shared/resource-policies/entry/resource-policy-entry.component.ts
#	src/app/shared/resource-policies/form/resource-policy-form.component.spec.ts
#	src/app/shared/resource-policies/form/resource-policy-form.component.ts
#	src/app/shared/resource-policies/resource-policies.component.spec.ts
#	src/app/shared/resource-policies/resource-policies.component.ts
#	src/app/shared/resource-policies/resource-policies.module.ts
#	src/app/shared/results-back-button/results-back-button.component.spec.ts
#	src/app/shared/results-back-button/results-back-button.component.ts
#	src/app/shared/results-back-button/results-back-button.module.ts
#	src/app/shared/roles/role.directive.ts
#	src/app/shared/rss-feed/rss.component.spec.ts
#	src/app/shared/rss-feed/rss.component.ts
#	src/app/shared/search-form/scope-selector-modal/scope-selector-modal.component.spec.ts
#	src/app/shared/search-form/scope-selector-modal/scope-selector-modal.component.ts
#	src/app/shared/search-form/search-form.component.spec.ts
#	src/app/shared/search-form/search-form.component.ts
#	src/app/shared/search/advanced-search/advanced-search.component.spec.ts
#	src/app/shared/search/advanced-search/advanced-search.component.ts
#	src/app/shared/search/search-export-csv/search-export-csv.component.spec.ts
#	src/app/shared/search/search-export-csv/search-export-csv.component.ts
#	src/app/shared/search/search-filters/search-filter/search-authority-filter/search-authority-filter.component.ts
#	src/app/shared/search/search-filters/search-filter/search-boolean-filter/search-boolean-filter.component.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts
#	src/app/shared/search/search-filters/search-filter/search-filter.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-filter.component.ts
#	src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts
#	src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts
#	src/app/shared/search/search-filters/search-filter/search-range-filter/search-range-filter.component.ts
#	src/app/shared/search/search-filters/search-filter/search-text-filter/search-text-filter.component.ts
#	src/app/shared/search/search-filters/search-filters.component.spec.ts
#	src/app/shared/search/search-filters/search-filters.component.ts
#	src/app/shared/search/search-labels/search-label/search-label.component.spec.ts
#	src/app/shared/search/search-labels/search-label/search-label.component.ts
#	src/app/shared/search/search-labels/search-labels.component.spec.ts
#	src/app/shared/search/search-labels/search-labels.component.ts
#	src/app/shared/search/search-results/search-results.component.spec.ts
#	src/app/shared/search/search-results/search-results.component.ts
#	src/app/shared/search/search-settings/search-settings.component.spec.ts
#	src/app/shared/search/search-settings/search-settings.component.ts
#	src/app/shared/search/search-sidebar/search-sidebar.component.spec.ts
#	src/app/shared/search/search-sidebar/search-sidebar.component.ts
#	src/app/shared/search/search-switch-configuration/search-switch-configuration.component.spec.ts
#	src/app/shared/search/search-switch-configuration/search-switch-configuration.component.ts
#	src/app/shared/search/search.component.spec.ts
#	src/app/shared/search/search.component.ts
#	src/app/shared/search/search.module.ts
#	src/app/shared/shared.module.ts
#	src/app/shared/sidebar/page-with-sidebar.component.spec.ts
#	src/app/shared/sidebar/sidebar-dropdown.component.ts
#	src/app/shared/starts-with/date/starts-with-date.component.spec.ts
#	src/app/shared/starts-with/date/starts-with-date.component.ts
#	src/app/shared/starts-with/starts-with-abstract.component.ts
#	src/app/shared/starts-with/starts-with-decorator.spec.ts
#	src/app/shared/starts-with/starts-with-loader.component.spec.ts
#	src/app/shared/starts-with/starts-with-loader.component.ts
#	src/app/shared/starts-with/text/starts-with-text.component.spec.ts
#	src/app/shared/starts-with/text/starts-with-text.component.ts
#	src/app/shared/subscriptions/subscription-modal/subscription-modal.component.spec.ts
#	src/app/shared/subscriptions/subscription-modal/subscription-modal.component.ts
#	src/app/shared/subscriptions/subscription-view/subscription-view.component.spec.ts
#	src/app/shared/subscriptions/subscription-view/subscription-view.component.ts
#	src/app/shared/subscriptions/subscriptions-data.service.ts
#	src/app/shared/subscriptions/subscriptions.module.ts
#	src/app/shared/testing/browser-only-mock.pipe.ts
#	src/app/shared/testing/dynamic-form-mock-services.ts
#	src/app/shared/testing/route-service.stub.ts
#	src/app/shared/testing/test-module.ts
#	src/app/shared/testing/utils.test.ts
#	src/app/shared/theme-support/themed.component.spec.ts
#	src/app/shared/trackable/abstract-trackable.component.spec.ts
#	src/app/shared/trackable/abstract-trackable.component.ts
#	src/app/shared/truncatable/truncatable-part/truncatable-part.component.spec.ts
#	src/app/shared/truncatable/truncatable-part/truncatable-part.component.ts
#	src/app/shared/truncatable/truncatable.component.spec.ts
#	src/app/shared/upload/file-dropzone-no-uploader/file-dropzone-no-uploader.component.ts
#	src/app/shared/upload/upload.module.ts
#	src/app/shared/upload/uploader/uploader.component.spec.ts
#	src/app/shared/upload/uploader/uploader.component.ts
#	src/app/shared/utils/auto-focus.directive.ts
#	src/app/shared/utils/browser-only.pipe.ts
#	src/app/shared/utils/capitalize.pipe.ts
#	src/app/shared/utils/click-outside.directive.ts
#	src/app/shared/utils/console.pipe.ts
#	src/app/shared/utils/drag-click.directive.ts
#	src/app/shared/utils/file-value-accessor.directive.ts
#	src/app/shared/utils/in-list-validator.directive.ts
#	src/app/shared/utils/markdown.pipe.ts
#	src/app/shared/utils/metadatafield-validator.directive.ts
#	src/app/shared/utils/object-keys-pipe.ts
#	src/app/shared/utils/object-ngfor.pipe.ts
#	src/app/shared/utils/object-values-pipe.ts
#	src/app/shared/utils/require-file.validator.ts
#	src/app/shared/utils/short-number.pipe.ts
#	src/app/shared/utils/split.pipe.ts
#	src/app/shared/utils/truncate.pipe.ts
#	src/app/shared/view-mode-switch/view-mode-switch.component.spec.ts
#	src/app/shared/view-mode-switch/view-mode-switch.component.ts
#	src/app/statistics-page/collection-statistics-page/collection-statistics-page.component.spec.ts
#	src/app/statistics-page/collection-statistics-page/collection-statistics-page.component.ts
#	src/app/statistics-page/community-statistics-page/community-statistics-page.component.spec.ts
#	src/app/statistics-page/community-statistics-page/community-statistics-page.component.ts
#	src/app/statistics-page/item-statistics-page/item-statistics-page.component.spec.ts
#	src/app/statistics-page/item-statistics-page/item-statistics-page.component.ts
#	src/app/statistics-page/site-statistics-page/site-statistics-page.component.spec.ts
#	src/app/statistics-page/site-statistics-page/site-statistics-page.component.ts
#	src/app/statistics-page/statistics-page-routing.module.ts
#	src/app/statistics-page/statistics-page.module.ts
#	src/app/statistics-page/statistics-page/statistics-page.directive.ts
#	src/app/statistics-page/statistics-table/statistics-table.component.spec.ts
#	src/app/statistics-page/statistics-table/statistics-table.component.ts
#	src/app/statistics/statistics.module.ts
#	src/app/submission/edit/submission-edit.component.spec.ts
#	src/app/submission/edit/submission-edit.component.ts
#	src/app/submission/edit/themed-submission-edit.component.ts
#	src/app/submission/form/collection/submission-form-collection.component.spec.ts
#	src/app/submission/form/collection/submission-form-collection.component.ts
#	src/app/submission/form/footer/submission-form-footer.component.spec.ts
#	src/app/submission/form/footer/submission-form-footer.component.ts
#	src/app/submission/form/section-add/submission-form-section-add.component.spec.ts
#	src/app/submission/form/section-add/submission-form-section-add.component.ts
#	src/app/submission/form/submission-form.component.spec.ts
#	src/app/submission/form/submission-form.component.ts
#	src/app/submission/form/submission-upload-files/submission-upload-files.component.spec.ts
#	src/app/submission/form/submission-upload-files/submission-upload-files.component.ts
#	src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.spec.ts
#	src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.ts
#	src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.spec.ts
#	src/app/submission/import-external/import-external-preview/submission-import-external-preview.component.ts
#	src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts
#	src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts
#	src/app/submission/import-external/submission-import-external.component.spec.ts
#	src/app/submission/import-external/submission-import-external.component.ts
#	src/app/submission/import-external/themed-submission-import-external.component.ts
#	src/app/submission/sections/accesses/section-accesses.component.spec.ts
#	src/app/submission/sections/accesses/section-accesses.component.ts
#	src/app/submission/sections/cc-license/submission-section-cc-licenses.component.spec.ts
#	src/app/submission/sections/cc-license/submission-section-cc-licenses.component.ts
#	src/app/submission/sections/container/section-container.component.spec.ts
#	src/app/submission/sections/container/section-container.component.ts
#	src/app/submission/sections/form/section-form-operations.service.spec.ts
#	src/app/submission/sections/form/section-form.component.spec.ts
#	src/app/submission/sections/form/section-form.component.ts
#	src/app/submission/sections/identifiers/section-identifiers.component.spec.ts
#	src/app/submission/sections/identifiers/section-identifiers.component.ts
#	src/app/submission/sections/license/section-license.component.spec.ts
#	src/app/submission/sections/license/section-license.component.ts
#	src/app/submission/sections/section-coar-notify/section-coar-notify.component.ts
#	src/app/submission/sections/sections.directive.ts
#	src/app/submission/sections/sherpa-policies/content-accordion/content-accordion.component.spec.ts
#	src/app/submission/sections/sherpa-policies/content-accordion/content-accordion.component.ts
#	src/app/submission/sections/sherpa-policies/metadata-information/metadata-information.component.spec.ts
#	src/app/submission/sections/sherpa-policies/metadata-information/metadata-information.component.ts
#	src/app/submission/sections/sherpa-policies/publication-information/publication-information.component.spec.ts
#	src/app/submission/sections/sherpa-policies/publication-information/publication-information.component.ts
#	src/app/submission/sections/sherpa-policies/publisher-policy/publisher-policy.component.spec.ts
#	src/app/submission/sections/sherpa-policies/publisher-policy/publisher-policy.component.ts
#	src/app/submission/sections/sherpa-policies/section-sherpa-policies.component.spec.ts
#	src/app/submission/sections/sherpa-policies/section-sherpa-policies.component.ts
#	src/app/submission/sections/upload/accessConditions/submission-section-upload-access-conditions.component.ts
#	src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.spec.ts
#	src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts
#	src/app/submission/sections/upload/file/section-upload-file.component.spec.ts
#	src/app/submission/sections/upload/file/section-upload-file.component.ts
#	src/app/submission/sections/upload/file/themed-section-upload-file.component.ts
#	src/app/submission/sections/upload/file/view/section-upload-file-view.component.spec.ts
#	src/app/submission/sections/upload/file/view/section-upload-file-view.component.ts
#	src/app/submission/sections/upload/section-upload.component.spec.ts
#	src/app/submission/sections/upload/section-upload.component.ts
#	src/app/submission/submission.module.ts
#	src/app/submission/submit/submission-submit.component.spec.ts
#	src/app/submission/submit/submission-submit.component.ts
#	src/app/submission/submit/themed-submission-submit.component.ts
#	src/app/submit-page/submit-page-routing.module.ts
#	src/app/submit-page/submit-page.module.ts
#	src/app/subscriptions-page/subscriptions-page-routing.module.ts
#	src/app/subscriptions-page/subscriptions-page.component.spec.ts
#	src/app/subscriptions-page/subscriptions-page.component.ts
#	src/app/subscriptions-page/subscriptions-page.module.ts
#	src/app/suggestions-page/suggestions-page-routing.module.ts
#	src/app/suggestions-page/suggestions-page.component.spec.ts
#	src/app/suggestions-page/suggestions-page.component.ts
#	src/app/suggestions-page/suggestions-page.module.ts
#	src/app/system-wide-alert/alert-banner/system-wide-alert-banner.component.spec.ts
#	src/app/system-wide-alert/alert-banner/system-wide-alert-banner.component.ts
#	src/app/system-wide-alert/alert-form/system-wide-alert-form.component.spec.ts
#	src/app/system-wide-alert/alert-form/system-wide-alert-form.component.ts
#	src/app/system-wide-alert/system-wide-alert-routing.module.ts
#	src/app/system-wide-alert/system-wide-alert.module.ts
#	src/app/thumbnail/thumbnail.component.spec.ts
#	src/app/thumbnail/thumbnail.component.ts
#	src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-page/advanced-workflow-action-page.component.ts
#	src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-rating/advanced-workflow-action-rating.component.ts
#	src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/advanced-workflow-action-select-reviewer.component.ts
#	src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.spec.ts
#	src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action-select-reviewer/reviewers-list/reviewers-list.component.ts
#	src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action/advanced-workflow-action.component.spec.ts
#	src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-action/advanced-workflow-action.component.ts
#	src/app/workflowitems-edit-page/advanced-workflow-action/advanced-workflow-actions-loader/advanced-workflow-actions-loader.component.spec.ts
#	src/app/workflowitems-edit-page/workflow-item-action-page.component.spec.ts
#	src/app/workflowitems-edit-page/workflow-item-action-page.component.ts
#	src/app/workflowitems-edit-page/workflow-item-delete/themed-workflow-item-delete.component.ts
#	src/app/workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component.spec.ts
#	src/app/workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component.ts
#	src/app/workflowitems-edit-page/workflow-item-send-back/themed-workflow-item-send-back.component.ts
#	src/app/workflowitems-edit-page/workflow-item-send-back/workflow-item-send-back.component.spec.ts
#	src/app/workflowitems-edit-page/workflow-item-send-back/workflow-item-send-back.component.ts
#	src/app/workflowitems-edit-page/workflowitems-edit-page-routing.module.ts
#	src/app/workflowitems-edit-page/workflowitems-edit-page.module.ts
#	src/app/workspaceitems-edit-page/workspaceitems-delete-page/themed-workspaceitems-delete-page.component.ts
#	src/app/workspaceitems-edit-page/workspaceitems-delete-page/workspaceitems-delete-page.component.spec.ts
#	src/app/workspaceitems-edit-page/workspaceitems-delete-page/workspaceitems-delete-page.component.ts
#	src/app/workspaceitems-edit-page/workspaceitems-edit-page-routing.module.ts
#	src/app/workspaceitems-edit-page/workspaceitems-edit-page.module.ts
#	src/config/app-config.interface.ts
#	src/modules/app/browser-app.module.ts
#	src/modules/app/server-app.module.ts
#	src/test.ts
#	src/themes/custom/app/admin/admin-sidebar/admin-sidebar.component.ts
#	src/themes/custom/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts
#	src/themes/custom/app/breadcrumbs/breadcrumbs.component.ts
#	src/themes/custom/app/browse-by/browse-by-title/browse-by-title.component.ts
#	src/themes/custom/app/collection-page/collection-page.component.ts
#	src/themes/custom/app/collection-page/edit-item-template-page/edit-item-template-page.component.ts
#	src/themes/custom/app/community-list-page/community-list-page.component.ts
#	src/themes/custom/app/community-list-page/community-list/community-list.component.ts
#	src/themes/custom/app/community-page/community-page.component.ts
#	src/themes/custom/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts
#	src/themes/custom/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.ts
#	src/themes/custom/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.ts
#	src/themes/custom/app/entity-groups/journal-entities/item-pages/journal/journal.component.ts
#	src/themes/custom/app/entity-groups/research-entities/item-pages/person/person.component.ts
#	src/themes/custom/app/footer/footer.component.ts
#	src/themes/custom/app/forbidden/forbidden.component.ts
#	src/themes/custom/app/forgot-password/forgot-password-email/forgot-email.component.ts
#	src/themes/custom/app/forgot-password/forgot-password-form/forgot-password-form.component.ts
#	src/themes/custom/app/header-nav-wrapper/header-navbar-wrapper.component.ts
#	src/themes/custom/app/home-page/home-news/home-news.component.ts
#	src/themes/custom/app/home-page/home-page.component.ts
#	src/themes/custom/app/home-page/top-level-community-list/top-level-community-list.component.ts
#	src/themes/custom/app/info/end-user-agreement/end-user-agreement.component.ts
#	src/themes/custom/app/info/feedback/feedback-form/feedback-form.component.ts
#	src/themes/custom/app/info/feedback/feedback.component.ts
#	src/themes/custom/app/info/privacy/privacy.component.ts
#	src/themes/custom/app/item-page/edit-item-page/item-status/item-status.component.ts
#	src/themes/custom/app/item-page/full/field-components/file-section/full-file-section.component.ts
#	src/themes/custom/app/item-page/full/full-item-page.component.ts
#	src/themes/custom/app/item-page/media-viewer/media-viewer-image/media-viewer-image.component.ts
#	src/themes/custom/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts
#	src/themes/custom/app/item-page/media-viewer/media-viewer.component.ts
#	src/themes/custom/app/item-page/simple/field-components/file-section/file-section.component.ts
#	src/themes/custom/app/item-page/simple/field-components/specific-field/title/item-page-title-field.component.ts
#	src/themes/custom/app/item-page/simple/item-page.component.ts
#	src/themes/custom/app/item-page/simple/item-types/publication/publication.component.ts
#	src/themes/custom/app/item-page/simple/item-types/untyped-item/untyped-item.component.ts
#	src/themes/custom/app/item-page/simple/metadata-representation-list/metadata-representation-list.component.ts
#	src/themes/custom/app/login-page/login-page.component.ts
#	src/themes/custom/app/logout-page/logout-page.component.ts
#	src/themes/custom/app/lookup-by-id/objectnotfound/objectnotfound.component.ts
#	src/themes/custom/app/my-dspace-page/my-dspace-page.component.ts
#	src/themes/custom/app/navbar/expandable-navbar-section/expandable-navbar-section.component.ts
#	src/themes/custom/app/navbar/navbar.component.ts
#	src/themes/custom/app/pagenotfound/pagenotfound.component.ts
#	src/themes/custom/app/profile-page/profile-page.component.ts
#	src/themes/custom/app/register-email-form/register-email-form.component.ts
#	src/themes/custom/app/register-page/create-profile/create-profile.component.ts
#	src/themes/custom/app/register-page/register-email/register-email.component.ts
#	src/themes/custom/app/request-copy/deny-request-copy/deny-request-copy.component.ts
#	src/themes/custom/app/request-copy/email-request-copy/email-request-copy.component.ts
#	src/themes/custom/app/request-copy/grant-request-copy/grant-request-copy.component.ts
#	src/themes/custom/app/root/root.component.ts
#	src/themes/custom/app/search-navbar/search-navbar.component.ts
#	src/themes/custom/app/search-page/configuration-search-page.component.ts
#	src/themes/custom/app/search-page/search-page.component.ts
#	src/themes/custom/app/shared/auth-nav-menu/auth-nav-menu.component.ts
#	src/themes/custom/app/shared/comcol-page-browse-by/comcol-page-browse-by.component.ts
#	src/themes/custom/app/shared/comcol-page-handle/comcol-page-handle.component.ts
#	src/themes/custom/app/shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component.ts
#	src/themes/custom/app/shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component.ts
#	src/themes/custom/app/shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component.ts
#	src/themes/custom/app/shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component.ts
#	src/themes/custom/app/shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component.ts
#	src/themes/custom/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts
#	src/themes/custom/app/shared/file-download-link/file-download-link.component.ts
#	src/themes/custom/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts
#	src/themes/custom/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.ts
#	src/themes/custom/app/shared/loading/loading.component.ts
#	src/themes/custom/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.ts
#	src/themes/custom/app/shared/object-list/collection-list-element/collection-list-element.component.ts
#	src/themes/custom/app/shared/object-list/community-list-element/community-list-element.component.ts
#	src/themes/custom/app/shared/object-list/object-list.component.ts
#	src/themes/custom/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.ts
#	src/themes/custom/app/shared/object-list/sidebar-search-list-element/item-types/publication-sidebar-search-list-element.component.ts
#	src/themes/custom/app/shared/results-back-button/results-back-button.component.ts
#	src/themes/custom/app/shared/search-form/search-form.component.ts
#	src/themes/custom/app/shared/search/search-filters/search-filters.component.ts
#	src/themes/custom/app/shared/search/search-results/search-results.component.ts
#	src/themes/custom/app/shared/search/search-settings/search-settings.component.ts
#	src/themes/custom/app/shared/search/search-sidebar/search-sidebar.component.ts
#	src/themes/custom/app/shared/starts-with/date/starts-with-date.component.ts
#	src/themes/custom/app/shared/starts-with/text/starts-with-text.component.ts
#	src/themes/custom/app/statistics-page/collection-statistics-page/collection-statistics-page.component.ts
#	src/themes/custom/app/statistics-page/community-statistics-page/community-statistics-page.component.ts
#	src/themes/custom/app/statistics-page/item-statistics-page/item-statistics-page.component.ts
#	src/themes/custom/app/statistics-page/site-statistics-page/site-statistics-page.component.ts
#	src/themes/custom/app/submission/edit/submission-edit.component.ts
#	src/themes/custom/app/submission/import-external/submission-import-external.component.ts
#	src/themes/custom/app/submission/sections/upload/file/section-upload-file.component.ts
#	src/themes/custom/app/submission/submit/submission-submit.component.ts
#	src/themes/custom/app/workflowitems-edit-page/workflow-item-delete/workflow-item-delete.component.ts
#	src/themes/custom/app/workflowitems-edit-page/workflow-item-send-back/workflow-item-send-back.component.ts
#	src/themes/custom/app/workspace-items-delete-page/workspace-items-delete/workspace-items-delete.component.ts
#	src/themes/custom/eager-theme.module.ts
#	src/themes/custom/lazy-theme.module.ts
#	src/themes/dspace/app/header-nav-wrapper/header-navbar-wrapper.component.ts
#	src/themes/dspace/app/header/header.component.ts
#	src/themes/dspace/app/home-page/home-news/home-news.component.ts
#	src/themes/dspace/app/navbar/navbar.component.ts
#	src/themes/dspace/eager-theme.module.ts
#	src/themes/dspace/lazy-theme.module.ts
This commit is contained in:
Andrea Barbasso
2024-03-12 17:47:51 +01:00
2625 changed files with 49907 additions and 32129 deletions

View File

@@ -1,13 +1,3 @@
import { FormService } from '../../../shared/form/form.service';
import { ComponentFixture, inject, TestBed } from '@angular/core/testing';
import { SubmissionSectionAccessesComponent } from './section-accesses.component';
import { SectionsService } from '../sections.service';
import { SectionsServiceStub } from '../../../shared/testing/sections-service.stub';
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
import { getMockFormBuilderService } from '../../../shared/mocks/form-builder-service.mock';
import { SubmissionAccessesConfigDataService } from '../../../core/config/submission-accesses-config-data.service';
import {
getSubmissionAccessesConfigNotChangeDiscoverableService,
getSubmissionAccessesConfigService
@@ -32,9 +22,14 @@ import {
DynamicCheckboxModel,
DynamicDatePickerModel,
DynamicFormArrayModel,
DynamicSelectModel
DynamicSelectModel,
} from '@ng-dynamic-forms/core';
import { AppState } from '../../../app.reducer';
import { SubmissionAccessesConfigDataService } from '../../../core/config/submission-accesses-config-data.service';
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
import { FormService } from '../../../shared/form/form.service';
import { getMockFormBuilderService } from '../../../shared/mocks/form-builder-service.mock';
import { getMockFormService } from '../../../shared/mocks/form-service.mock';
import { mockAccessesFormData } from '../../../shared/mocks/submission.mock';
import { accessConditionChangeEvent, checkboxChangeEvent } from '../../../shared/testing/form-event.stub';
@@ -50,6 +45,15 @@ import { CommonModule } from '@angular/common';
import {
dsDynamicFormControlMapFn
} from '../../../shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-map-fn';
import { SectionsServiceStub } from '../../../shared/testing/sections-service.stub';
import { SectionsService } from '../sections.service';
import { SubmissionSectionAccessesComponent } from './section-accesses.component';
import { TestBed } from '@angular/core/testing';
ComponentFixture,
inject,
TestBed,
} from '@angular/core/testing';
function getMockDsDynamicTypeBindRelationService(): DsDynamicTypeBindRelationService {
return jasmine.createSpyObj('DsDynamicTypeBindRelationService', {
@@ -88,12 +92,12 @@ describe('SubmissionSectionAccessesComponent', () => {
enabled: true,
data: {
discoverable: true,
accessConditions: []
accessConditions: [],
},
errorsToShow: [],
serverValidationErrors: [],
isLoading: false,
isValid: true
isValid: true,
};
describe('First with canChangeDiscoverable true', () => {
@@ -125,7 +129,7 @@ describe('SubmissionSectionAccessesComponent', () => {
{ provide: APP_DYNAMIC_FORM_CONTROL_FN, useValue: dsDynamicFormControlMapFn },
FormBuilderService,
provideMockStore({})
]
],
})
.compileComponents();
});
@@ -168,8 +172,8 @@ describe('SubmissionSectionAccessesComponent', () => {
});
it('should have set maxStartDate and maxEndDate properly', () => {
const maxStartDate = {year: 2024, month: 12, day: 20};
const maxEndDate = {year: 2022, month: 6, day: 20};
const maxStartDate = { year: 2024, month: 12, day: 20 };
const maxEndDate = { year: 2022, month: 6, day: 20 };
const startDateModel = formbuilderService.findById('startDate', component.formModel);
expect(startDateModel.max).toEqual(maxStartDate);
@@ -222,7 +226,7 @@ describe('SubmissionSectionAccessesComponent', () => {
FormBuilderService,
provideMockStore({})
]
],
})
.compileComponents();
});

View File

@@ -1,5 +1,4 @@
import { SectionAccessesService } from './section-accesses.service';
import { Component, Inject, ViewChild } from '@angular/core';
import { Component, Inject, ViewChild, } from '@angular/core';
import { UntypedFormControl } from '@angular/forms';
import { filter, map, mergeMap, take } from 'rxjs/operators';
@@ -19,10 +18,28 @@ import {
DynamicFormGroupModel,
DynamicSelectModel,
MATCH_ENABLED,
OR_OPERATOR
OR_OPERATOR,
} from '@ng-dynamic-forms/core';
import { DynamicDateControlValue } from '@ng-dynamic-forms/core/lib/model/dynamic-date-control.model';
import { DynamicFormControlCondition } from '@ng-dynamic-forms/core/lib/model/misc/dynamic-form-control-relation.model';
import { AccessesConditionOption } from '../../../core/config/models/config-accesses-conditions-options.model';
import { SubmissionAccessesConfigDataService } from '../../../core/config/submission-accesses-config-data.service';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { getFirstSucceededRemoteData } from '../../../core/shared/operators';
import {
WorkspaceitemSectionAccessesObject
} from '../../../core/submission/models/workspaceitem-section-accesses.model';
import {
SubmissionJsonPatchOperationsService
} from '../../../core/submission/submission-json-patch-operations.service';
import { dateToISOFormat } from '../../../shared/date.util';
import { hasValue, isNotEmpty, isNotNull, } from '../../../shared/empty.util';
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
import { FormComponent } from '../../../shared/form/form.component';
import { FormService } from '../../../shared/form/form.service';
import { SectionFormOperationsService } from '../form/section-form-operations.service';
import {
ACCESS_CONDITION_GROUP_CONFIG,
ACCESS_CONDITION_GROUP_LAYOUT,
@@ -35,27 +52,10 @@ import {
FORM_ACCESS_CONDITION_START_DATE_CONFIG,
FORM_ACCESS_CONDITION_START_DATE_LAYOUT,
FORM_ACCESS_CONDITION_TYPE_CONFIG,
FORM_ACCESS_CONDITION_TYPE_LAYOUT
FORM_ACCESS_CONDITION_TYPE_LAYOUT,
} from './section-accesses.model';
import { hasValue, isNotEmpty, isNotNull } from '../../../shared/empty.util';
import {
WorkspaceitemSectionAccessesObject
} from '../../../core/submission/models/workspaceitem-section-accesses.model';
import { SubmissionAccessesConfigDataService } from '../../../core/config/submission-accesses-config-data.service';
import { getFirstSucceededRemoteData } from '../../../core/shared/operators';
import { FormComponent } from '../../../shared/form/form.component';
import { FormService } from '../../../shared/form/form.service';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { SectionFormOperationsService } from '../form/section-form-operations.service';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { AccessesConditionOption } from '../../../core/config/models/config-accesses-conditions-options.model';
import {
SubmissionJsonPatchOperationsService
} from '../../../core/submission/submission-json-patch-operations.service';
import { dateToISOFormat } from '../../../shared/date.util';
import { DynamicFormControlCondition } from '@ng-dynamic-forms/core/lib/model/misc/dynamic-form-control-relation.model';
import { DynamicDateControlValue } from '@ng-dynamic-forms/core/lib/model/dynamic-date-control.model';
import { NgIf } from '@angular/common';
import { SectionAccessesService } from './section-accesses.service';
/**
* This component represents a section for managing item's access conditions.
@@ -165,7 +165,7 @@ export class SubmissionSectionAccessesComponent extends SectionModelComponent {
metadataModel.value = {
year: date.getUTCFullYear(),
month: date.getUTCMonth() + 1,
day: date.getUTCDate()
day: date.getUTCDate(),
};
} else {
metadataModel.value = accessCondition[key];
@@ -205,7 +205,7 @@ export class SubmissionSectionAccessesComponent extends SectionModelComponent {
take(1),
filter((isValid) => isValid),
mergeMap(() => this.formService.getFormData(this.formId)),
take(1)
take(1),
).subscribe((formData: any) => {
const accessConditionsToSave = [];
formData.accessCondition
@@ -309,10 +309,10 @@ export class SubmissionSectionAccessesComponent extends SectionModelComponent {
const discoverableCheckboxConfig = Object.assign({}, ACCESS_FORM_CHECKBOX_CONFIG, {
label: this.translate.instant('submission.sections.accesses.form.discoverable-label'),
hint: this.translate.instant('submission.sections.accesses.form.discoverable-description'),
value: this.accessesData.discoverable
value: this.accessesData.discoverable,
});
formModel.push(
new DynamicCheckboxModel(discoverableCheckboxConfig, ACCESS_FORM_CHECKBOX_LAYOUT)
new DynamicCheckboxModel(discoverableCheckboxConfig, ACCESS_FORM_CHECKBOX_LAYOUT),
);
}
@@ -324,8 +324,8 @@ export class SubmissionSectionAccessesComponent extends SectionModelComponent {
accessConditionTypeOptions.push(
{
label: accessCondition.name,
value: accessCondition.name
}
value: accessCondition.name,
},
);
}
accessConditionTypeModelConfig.options = accessConditionTypeOptions;
@@ -344,7 +344,7 @@ export class SubmissionSectionAccessesComponent extends SectionModelComponent {
maxStartDate = {
year: min.getUTCFullYear(),
month: min.getUTCMonth() + 1,
day: min.getUTCDate()
day: min.getUTCDate(),
};
}
}
@@ -355,7 +355,7 @@ export class SubmissionSectionAccessesComponent extends SectionModelComponent {
maxEndDate = {
year: max.getUTCFullYear(),
month: max.getUTCMonth() + 1,
day: max.getUTCDate()
day: max.getUTCDate(),
};
}
}
@@ -393,7 +393,7 @@ export class SubmissionSectionAccessesComponent extends SectionModelComponent {
// Number of access conditions blocks in form
accessConditionsArrayConfig.initialCount = isNotEmpty(this.accessesData.accessConditions) ? this.accessesData.accessConditions.length : 1;
formModel.push(
new DynamicFormArrayModel(accessConditionsArrayConfig, ACCESS_CONDITIONS_FORM_ARRAY_LAYOUT)
new DynamicFormArrayModel(accessConditionsArrayConfig, ACCESS_CONDITIONS_FORM_ARRAY_LAYOUT),
);
this.initModelData(formModel);

View File

@@ -12,7 +12,7 @@ import { DynamicCheckboxModelConfig } from '@ng-dynamic-forms/core/lib/model/che
export const ACCESS_FORM_CHECKBOX_CONFIG: DynamicCheckboxModelConfig = {
id: 'discoverable',
name: 'discoverable'
name: 'discoverable',
};
export const ACCESS_FORM_CHECKBOX_LAYOUT = {
@@ -20,21 +20,21 @@ export const ACCESS_FORM_CHECKBOX_LAYOUT = {
element: {
container: 'custom-control custom-checkbox pl-1',
control: 'custom-control-input',
label: 'custom-control-label pt-1'
}
label: 'custom-control-label pt-1',
},
};
export const ACCESS_CONDITION_GROUP_CONFIG: DynamicFormGroupModelConfig = {
id: 'accessConditionGroup',
group: []
group: [],
};
export const ACCESS_CONDITION_GROUP_LAYOUT: DynamicFormControlLayout = {
element: {
host: 'form-group access-condition-group col',
container: 'pl-1 pr-1',
control: 'form-row '
}
control: 'form-row ',
},
};
export const ACCESS_CONDITIONS_FORM_ARRAY_CONFIG: DynamicFormArrayModelConfig = {
@@ -44,20 +44,20 @@ export const ACCESS_CONDITIONS_FORM_ARRAY_CONFIG: DynamicFormArrayModelConfig =
export const ACCESS_CONDITIONS_FORM_ARRAY_LAYOUT: DynamicFormControlLayout = {
grid: {
group: 'form-row pt-4',
}
},
};
export const FORM_ACCESS_CONDITION_TYPE_CONFIG: DynamicSelectModelConfig<any> = {
id: 'name',
label: 'submission.sections.accesses.form.access-condition-label',
hint: 'submission.sections.accesses.form.access-condition-hint',
options: []
options: [],
};
export const FORM_ACCESS_CONDITION_TYPE_LAYOUT: DynamicFormControlLayout = {
element: {
host: 'col-12',
label: 'col-form-label name-label'
}
label: 'col-form-label name-label',
},
};
export const FORM_ACCESS_CONDITION_START_DATE_CONFIG: DynamicDatePickerModelConfig = {
@@ -71,24 +71,24 @@ export const FORM_ACCESS_CONDITION_START_DATE_CONFIG: DynamicDatePickerModelConf
{
match: MATCH_ENABLED,
operator: OR_OPERATOR,
when: []
}
when: [],
},
],
required: true,
validators: {
required: null
required: null,
},
errorMessages: {
required: 'submission.sections.accesses.form.date-required-from'
}
required: 'submission.sections.accesses.form.date-required-from',
},
};
export const FORM_ACCESS_CONDITION_START_DATE_LAYOUT: DynamicFormControlLayout = {
element: {
label: 'col-form-label'
label: 'col-form-label',
},
grid: {
host: 'col-6'
}
host: 'col-6',
},
};
export const FORM_ACCESS_CONDITION_END_DATE_CONFIG: DynamicDatePickerModelConfig = {
@@ -102,22 +102,22 @@ export const FORM_ACCESS_CONDITION_END_DATE_CONFIG: DynamicDatePickerModelConfig
{
match: MATCH_ENABLED,
operator: OR_OPERATOR,
when: []
}
when: [],
},
],
required: true,
validators: {
required: null
required: null,
},
errorMessages: {
required: 'submission.sections.accesses.form.date-required-until'
}
required: 'submission.sections.accesses.form.date-required-until',
},
};
export const FORM_ACCESS_CONDITION_END_DATE_LAYOUT: DynamicFormControlLayout = {
element: {
label: 'col-form-label'
label: 'col-form-label',
},
grid: {
host: 'col-6'
}
host: 'col-6',
},
};

View File

@@ -1,13 +1,15 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { distinctUntilChanged, filter } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import {
distinctUntilChanged,
filter,
} from 'rxjs/operators';
import { SubmissionState } from '../../submission.reducers';
import { WorkspaceitemSectionAccessesObject } from '../../../core/submission/models/workspaceitem-section-accesses.model';
import { isNotUndefined } from '../../../shared/empty.util';
import { submissionSectionDataFromIdSelector } from '../../selectors';
import { WorkspaceitemSectionAccessesObject } from '../../../core/submission/models/workspaceitem-section-accesses.model';
import { SubmissionState } from '../../submission.reducers';
/**
* A service that provides methods to handle submission item's accesses condition state.

View File

@@ -20,7 +20,7 @@
</ng-container>
<ng-container class="menu">
<button *ngIf="submissionCcLicenses?.length == 0"
<button *ngIf="submissionCcLicenses?.length === 0"
class="dropdown-item disabled">
{{ 'submission.sections.ccLicense.none' | translate }}
</button>

View File

@@ -1,22 +1,23 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { SubmissionSectionCcLicensesComponent } from './submission-section-cc-licenses.component';
import { SUBMISSION_CC_LICENSE } from '../../../core/submission/models/submission-cc-licence.resource-type';
import { of as observableOf } from 'rxjs';
import { SubmissionCcLicenseDataService } from '../../../core/submission/submission-cc-license-data.service';
import { DebugElement } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync, } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { SectionsService } from '../sections.service';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsType } from '../sections-type';
import { TranslateModule } from '@ngx-translate/core';
import { SubmissionCcLicence } from '../../../core/submission/models/submission-cc-license.model';
import { cold } from 'jasmine-marbles';
import { of as observableOf } from 'rxjs';
import { ConfigurationDataService } from '../../../core/data/configuration-data.service';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { ConfigurationProperty } from '../../../core/shared/configuration-property.model';
import { SUBMISSION_CC_LICENSE } from '../../../core/submission/models/submission-cc-licence.resource-type';
import { SubmissionCcLicence } from '../../../core/submission/models/submission-cc-license.model';
import { SubmissionCcLicenseDataService } from '../../../core/submission/submission-cc-license-data.service';
import { SubmissionCcLicenseUrlDataService } from '../../../core/submission/submission-cc-license-url-data.service';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
import { createPaginatedList } from '../../../shared/testing/utils.test';
import {ConfigurationDataService} from '../../../core/data/configuration-data.service';
import {ConfigurationProperty} from '../../../core/shared/configuration-property.model';
import { SubmissionSectionCcLicensesComponent } from './submission-section-cc-licenses.component';
import { ThemedLoadingComponent } from '../../../shared/loading/themed-loading.component';
import { FormBuilderService } from 'src/app/shared/form/builder/form-builder.service';
@@ -34,7 +35,7 @@ describe('SubmissionSectionCcLicensesComponent', () => {
serverValidationErrors: [],
header: 'test header',
id: 'test section id',
sectionType: SectionsType.SubmissionForm
sectionType: SectionsType.SubmissionForm,
};
const submissionCcLicenses: SubmissionCcLicence[] = [
@@ -97,12 +98,12 @@ describe('SubmissionSectionCcLicensesComponent', () => {
{
id: 'test enum id 2a I',
label: 'test enum label 2a I',
description: 'test enum description 2a I'
description: 'test enum description 2a I',
},
{
id: 'test enum id 2a II',
label: 'test enum label 2a II',
description: 'test enum description 2a II'
description: 'test enum description 2a II',
},
],
},
@@ -114,12 +115,12 @@ describe('SubmissionSectionCcLicensesComponent', () => {
{
id: 'test enum id 2b I',
label: 'test enum label 2b I',
description: 'test enum description 2b I'
description: 'test enum description 2b I',
},
{
id: 'test enum id 2b II',
label: 'test enum label 2b II',
description: 'test enum description 2b II'
description: 'test enum description 2b II',
},
],
},
@@ -140,7 +141,7 @@ describe('SubmissionSectionCcLicensesComponent', () => {
getCcLicenseLink: createSuccessfulRemoteDataObject$(
{
url: 'test cc license link',
}
},
),
});
@@ -151,7 +152,7 @@ describe('SubmissionSectionCcLicensesComponent', () => {
setSectionStatus: () => undefined,
updateSectionData: (submissionId, sectionId, updatedData) => {
component.sectionData.data = updatedData;
}
},
};
const operationsBuilder = jasmine.createSpyObj('operationsBuilder', {
@@ -204,10 +205,10 @@ describe('SubmissionSectionCcLicensesComponent', () => {
it('should display a dropdown with the different cc licenses', () => {
expect(
de.query(By.css('.ccLicense-select ds-select .dropdown-menu button:nth-child(1)')).nativeElement.innerText
de.query(By.css('.ccLicense-select ds-select .dropdown-menu button:nth-child(1)')).nativeElement.innerText,
).toContain('test license name 1');
expect(
de.query(By.css('.ccLicense-select ds-select .dropdown-menu button:nth-child(2)')).nativeElement.innerText
de.query(By.css('.ccLicense-select ds-select .dropdown-menu button:nth-child(2)')).nativeElement.innerText,
).toContain('test license name 2');
});
@@ -222,7 +223,7 @@ describe('SubmissionSectionCcLicensesComponent', () => {
it('should display the selected cc license', () => {
expect(
de.query(By.css('.ccLicense-select ds-select button.selection')).nativeElement.innerText
de.query(By.css('.ccLicense-select ds-select button.selection')).nativeElement.innerText,
).toContain('test license name 2');
});
@@ -255,7 +256,7 @@ describe('SubmissionSectionCcLicensesComponent', () => {
new Map([
[ccLicence.fields[0], ccLicence.fields[0].enums[1]],
[ccLicence.fields[1], ccLicence.fields[1].enums[0]],
])
]),
);
});

View File

@@ -1,26 +1,27 @@
import { Component, Inject } from '@angular/core';
import { Observable, of as observableOf, Subscription } from 'rxjs';
import { Field, Option, SubmissionCcLicence } from '../../../core/submission/models/submission-cc-license.model';
import { Component, Inject, } from '@angular/core';
import { NgbModal, NgbModalRef, } from '@ng-bootstrap/ng-bootstrap';
import { Observable, of as observableOf, Subscription, } from 'rxjs';
import { distinctUntilChanged, filter, map, take, } from 'rxjs/operators';
import { ConfigurationDataService } from '../../../core/data/configuration-data.service';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import {
getFirstCompletedRemoteData,
getFirstSucceededRemoteData,
getRemoteDataPayload
getRemoteDataPayload,
} from '../../../core/shared/operators';
import { distinctUntilChanged, filter, map, take } from 'rxjs/operators';
import { SubmissionCcLicenseDataService } from '../../../core/submission/submission-cc-license-data.service';
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { SectionsType } from '../sections-type';
import { SectionModelComponent } from '../models/section.model';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsService } from '../sections.service';
import { Field, Option, SubmissionCcLicence, } from '../../../core/submission/models/submission-cc-license.model';
import {
WorkspaceitemSectionCcLicenseObject
} from '../../../core/submission/models/workspaceitem-section-cc-license.model';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { isNotEmpty } from '../../../shared/empty.util';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { SubmissionCcLicenseDataService } from '../../../core/submission/submission-cc-license-data.service';
import { SectionsType } from '../sections-type';
import { SubmissionCcLicenseUrlDataService } from '../../../core/submission/submission-cc-license-url-data.service';
import { ConfigurationDataService } from '../../../core/data/configuration-data.service';
import { isNotEmpty } from '../../../shared/empty.util';
import { SectionModelComponent } from '../models/section.model';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsService } from '../sections.service';
import { TranslateModule } from '@ngx-translate/core';
import { AsyncPipe, NgForOf, NgIf } from '@angular/common';
import { ThemedLoadingComponent } from '../../../shared/loading/themed-loading.component';
@@ -111,7 +112,7 @@ export class SubmissionSectionCcLicensesComponent extends SectionModelComponent
protected configService: ConfigurationDataService,
@Inject('collectionIdProvider') public injectedCollectionId: string,
@Inject('sectionDataProvider') public injectedSectionData: SectionDataObject,
@Inject('submissionIdProvider') public injectedSubmissionId: string
@Inject('submissionIdProvider') public injectedSubmissionId: string,
) {
super(
injectedCollectionId,
@@ -169,7 +170,7 @@ export class SubmissionSectionCcLicensesComponent extends SectionModelComponent
ccLicense: {
id: ccLicense.id,
fields: Object.assign({}, this.data.ccLicense.fields, {
[field.id]: option
[field.id]: option,
}),
},
accepted: false,
@@ -203,7 +204,7 @@ export class SubmissionSectionCcLicensesComponent extends SectionModelComponent
*/
getCcLicenseLink$(): Observable<string> {
if (!!this.storedCcLicenseLink) {
if (this.storedCcLicenseLink) {
return observableOf(this.storedCcLicenseLink);
}
if (!this.getSelectedCcLicense() || this.getSelectedCcLicense().fields.some(
@@ -214,7 +215,7 @@ export class SubmissionSectionCcLicensesComponent extends SectionModelComponent
return this.submissionCcLicenseUrlDataService.getCcLicenseLink(
selectedCcLicense,
new Map(selectedCcLicense.fields.map(
(field) => [field, this.getSelectedOption(selectedCcLicense, field)]
(field) => [field, this.getSelectedOption(selectedCcLicense, field)],
)),
);
}
@@ -272,7 +273,7 @@ export class SubmissionSectionCcLicensesComponent extends SectionModelComponent
).subscribe((link) => {
this.operationsBuilder.add(path, link.toString(), false, true);
});
} else if (!!this.data.uri) {
} else if (this.data.uri) {
this.operationsBuilder.remove(path);
}
}
@@ -283,19 +284,19 @@ export class SubmissionSectionCcLicensesComponent extends SectionModelComponent
getRemoteDataPayload(),
map((list) => list.page),
).subscribe(
(licenses) => this.submissionCcLicenses = licenses
(licenses) => this.submissionCcLicenses = licenses,
),
this.configService.findByPropertyName('cc.license.jurisdiction').pipe(
getFirstCompletedRemoteData(),
getRemoteDataPayload()
getRemoteDataPayload(),
).subscribe((remoteData) => {
if (remoteData === undefined || remoteData.values.length === 0) {
// No value configured, use blank value (International jurisdiction)
this.defaultJurisdiction = '';
} else {
this.defaultJurisdiction = remoteData.values[0];
}
})
if (remoteData === undefined || remoteData.values.length === 0) {
// No value configured, use blank value (International jurisdiction)
this.defaultJurisdiction = '';
} else {
this.defaultJurisdiction = remoteData.values[0];
}
}),
);
}
@@ -305,7 +306,7 @@ export class SubmissionSectionCcLicensesComponent extends SectionModelComponent
*/
setAccepted(accepted: boolean) {
this.updateSectionData({
accepted
accepted,
});
this.updateSectionStatus();
}

View File

@@ -9,7 +9,7 @@
'submission.sections.'+sectionData.header | translate
}}</span>
<div class="d-inline-block float-right">
<i *ngIf="!(sectionRef.isValid() | async) && !(sectionRef.hasErrors()) && !(sectionRef.isInfo())"
<i *ngIf="(sectionRef.isValid() | async) !== true && !(sectionRef.hasErrors()) && !(sectionRef.isInfo())"
class="fas fa-exclamation-circle text-warning mr-3"
title="{{'submission.sections.status.warnings.title' | translate}}" role="img"
[attr.aria-label]="'submission.sections.status.warnings.aria' | translate"></i>

View File

@@ -1,35 +1,34 @@
// Load the implementations that should be tested
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { Component, CUSTOM_ELEMENTS_SCHEMA, } from '@angular/core';
import { ComponentFixture, inject, TestBed, waitForAsync, } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { of as observableOf } from 'rxjs';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { TranslateModule } from '@ngx-translate/core';
import { of as observableOf } from 'rxjs';
import { SubmissionSectionContainerComponent } from './section-container.component';
import { createTestComponent } from '../../../shared/testing/utils.test';
import { SectionsType } from '../sections-type';
import { SectionsDirective } from '../sections.directive';
import { SubmissionService } from '../../submission.service';
import { SectionsService } from '../sections.service';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service.stub';
import { mockSubmissionCollectionId, mockSubmissionId, } from '../../../shared/mocks/submission.mock';
import { SectionsServiceStub } from '../../../shared/testing/sections-service.stub';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service.stub';
import { createTestComponent } from '../../../shared/testing/utils.test';
import { SubmissionService } from '../../submission.service';
import { SectionDataObject } from '../models/section-data.model';
import { mockSubmissionCollectionId, mockSubmissionId } from '../../../shared/mocks/submission.mock';
import { SectionsDirective } from '../sections.directive';
import { SectionsService } from '../sections.service';
import { SectionsType } from '../sections-type';
import { SubmissionSectionContainerComponent } from './section-container.component';
const sectionState = {
header: 'submit.progressbar.describe.stepone',
config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone',
mandatory: true,
sectionType: SectionsType.SubmissionForm,
collapsed: false,
enabled: true,
data: {},
errorsToShow: [],
serverValidationErrors: [],
isLoading: false,
isValid: false
config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone',
mandatory: true,
sectionType: SectionsType.SubmissionForm,
collapsed: false,
enabled: true,
data: {},
errorsToShow: [],
serverValidationErrors: [],
isLoading: false,
isValid: false,
} as any;
const sectionObject: SectionDataObject = {
@@ -40,7 +39,7 @@ const sectionObject: SectionDataObject = {
serverValidationErrors: [],
header: 'submit.progressbar.describe.stepone',
id: 'traditionalpageone',
sectionType: SectionsType.SubmissionForm
sectionType: SectionsType.SubmissionForm,
};
describe('SubmissionSectionContainerComponent test suite', () => {
@@ -76,9 +75,9 @@ describe('SubmissionSectionContainerComponent test suite', () => {
providers: [
{ provide: SectionsService, useValue: sectionsServiceStub },
{ provide: SubmissionService, useValue: submissionServiceStub },
SubmissionSectionContainerComponent
SubmissionSectionContainerComponent,
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
schemas: [CUSTOM_ELEMENTS_SCHEMA],
}).compileComponents();
}));

View File

@@ -1,9 +1,9 @@
import { Component, Injector, Input, OnInit, ViewChild } from '@angular/core';
import { Component, Injector, Input, OnInit, ViewChild, } from '@angular/core';
import { SectionsDirective } from '../sections.directive';
import { SectionDataObject } from '../models/section-data.model';
import { rendersSectionType } from '../sections-decorator';
import { AlertType } from '../../../shared/alert/alert-type';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsDirective } from '../sections.directive';
import { rendersSectionType } from '../sections-decorator';
import { AlertComponent } from '../../../shared/alert/alert.component';
import { AsyncPipe, NgClass, NgComponentOutlet, NgForOf, NgIf } from '@angular/common';
import { NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap';
@@ -84,7 +84,7 @@ export class SubmissionSectionContainerComponent implements OnInit {
{ provide: 'sectionDataProvider', useFactory: () => (this.sectionData), deps: [] },
{ provide: 'submissionIdProvider', useFactory: () => (this.submissionId), deps: [] },
],
parent: this.injector
parent: this.injector,
});
}

View File

@@ -0,0 +1,20 @@
<!--
Template for the detect duplicates submission section component
@author Kim Shepherd
-->
<div class="text-sm-left" *ngVar="(this.getDuplicateData() | async) as data">
<ng-container *ngIf="data?.potentialDuplicates.length === 0">
<div class="alert alert-success w-100">{{ 'submission.sections.duplicates.none' | translate }}</div>
</ng-container>
<ng-container *ngIf="data?.potentialDuplicates.length > 0">
<div class="alert alert-warning w-100">{{ 'submission.sections.duplicates.detected' | translate }}</div>
<div *ngFor="let dupe of data?.potentialDuplicates" class="ds-duplicate">
<a target="_blank" [href]="getItemLink(dupe.uuid)">{{dupe.title}}</a>
<div *ngFor="let metadatum of Metadata.toViewModelList(dupe.metadata)">
{{('item.preview.' + metadatum.key) | translate}} {{metadatum.value}}
</div>
<p *ngIf="dupe.workspaceItemId">{{ 'submission.sections.duplicates.in-workspace' | translate }}</p>
<p *ngIf="dupe.workflowItemId">{{ 'submission.sections.duplicates.in-workflow' | translate }}</p>
</div>
</ng-container>
</div>

View File

@@ -0,0 +1,261 @@
import { CommonModule } from '@angular/common';
import {
ChangeDetectorRef,
Component,
NO_ERRORS_SCHEMA,
} from '@angular/core';
import {
ComponentFixture,
TestBed,
waitForAsync,
} from '@angular/core/testing';
import {
FormsModule,
ReactiveFormsModule,
} from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { TranslateModule } from '@ngx-translate/core';
import { cold } from 'jasmine-marbles';
import { NgxPaginationModule } from 'ngx-pagination';
import { of as observableOf } from 'rxjs';
import { SubmissionFormsConfigDataService } from '../../../core/config/submission-forms-config-data.service';
import { CollectionDataService } from '../../../core/data/collection-data.service';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { PaginationService } from '../../../core/pagination/pagination.service';
import { Collection } from '../../../core/shared/collection.model';
import { License } from '../../../core/shared/license.model';
import { MetadataValue } from '../../../core/shared/metadata.models';
import { SubmissionScopeType } from '../../../core/submission/submission-scope-type';
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
import { FormService } from '../../../shared/form/form.service';
import { getMockFormOperationsService } from '../../../shared/mocks/form-operations-service.mock';
import { getMockFormService } from '../../../shared/mocks/form-service.mock';
import {
mockSubmissionCollectionId,
mockSubmissionId,
} from '../../../shared/mocks/submission.mock';
import { defaultUUID } from '../../../shared/mocks/uuid.service.mock';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { Duplicate } from '../../../shared/object-list/duplicate-data/duplicate.model';
import { DUPLICATE } from '../../../shared/object-list/duplicate-data/duplicate.resource-type';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub';
import { SectionsServiceStub } from '../../../shared/testing/sections-service.stub';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service.stub';
import { ObjNgFor } from '../../../shared/utils/object-ngfor.pipe';
import { VarDirective } from '../../../shared/utils/var.directive';
import { SubmissionService } from '../../submission.service';
import { SectionFormOperationsService } from '../form/section-form-operations.service';
import { SectionsService } from '../sections.service';
import { SectionsType } from '../sections-type';
import { SubmissionSectionDuplicatesComponent } from './section-duplicates.component';
function getMockSubmissionFormsConfigService(): SubmissionFormsConfigDataService {
return jasmine.createSpyObj('FormOperationsService', {
getConfigAll: jasmine.createSpy('getConfigAll'),
getConfigByHref: jasmine.createSpy('getConfigByHref'),
getConfigByName: jasmine.createSpy('getConfigByName'),
getConfigBySearch: jasmine.createSpy('getConfigBySearch'),
});
}
function getMockCollectionDataService(): CollectionDataService {
return jasmine.createSpyObj('CollectionDataService', {
findById: jasmine.createSpy('findById'),
findByHref: jasmine.createSpy('findByHref'),
});
}
const duplicates: Duplicate[] = [{
title: 'Unique title',
uuid: defaultUUID,
workflowItemId: 1,
workspaceItemId: 2,
owningCollection: 'Test Collection',
metadata: {
'dc.title': [
Object.assign(new MetadataValue(), {
'value': 'Unique title',
'language': null,
'authority': null,
'confidence': -1,
'place': 0,
})],
},
type: DUPLICATE,
_links: {
self: {
href: 'http://localhost:8080/server/api/core/submission/duplicates/search?uuid=testid',
},
},
}];
const sectionObject = {
header: 'submission.sections.submit.progressbar.duplicates',
mandatory: true,
opened: true,
data: { potentialDuplicates: duplicates },
errorsToShow: [],
serverValidationErrors: [],
id: 'duplicates',
sectionType: SectionsType.Duplicates,
sectionVisibility: null,
};
describe('SubmissionSectionDuplicatesComponent test suite', () => {
let comp: SubmissionSectionDuplicatesComponent;
let compAsAny: any;
let fixture: ComponentFixture<SubmissionSectionDuplicatesComponent>;
let submissionServiceStub: any = new SubmissionServiceStub();
const sectionsServiceStub: any = new SectionsServiceStub();
let formService: any;
let formOperationsService: any;
let formBuilderService: any;
let collectionDataService: any;
const submissionId = mockSubmissionId;
const collectionId = mockSubmissionCollectionId;
const jsonPatchOpBuilder: any = jasmine.createSpyObj('jsonPatchOpBuilder', {
add: jasmine.createSpy('add'),
replace: jasmine.createSpy('replace'),
remove: jasmine.createSpy('remove'),
});
const licenseText = 'License text';
const mockCollection = Object.assign(new Collection(), {
name: 'Community 1-Collection 1',
id: collectionId,
metadata: [
{
key: 'dc.title',
language: 'en_US',
value: 'Community 1-Collection 1',
}],
license: createSuccessfulRemoteDataObject$(Object.assign(new License(), { text: licenseText })),
});
const paginationService = new PaginationServiceStub();
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
BrowserModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
NgxPaginationModule,
NoopAnimationsModule,
TranslateModule.forRoot(),
],
declarations: [
SubmissionSectionDuplicatesComponent,
TestComponent,
ObjNgFor,
VarDirective,
],
providers: [
{ provide: CollectionDataService, useValue: getMockCollectionDataService() },
{ provide: SectionFormOperationsService, useValue: getMockFormOperationsService() },
{ provide: FormService, useValue: getMockFormService() },
{ provide: JsonPatchOperationsBuilder, useValue: jsonPatchOpBuilder },
{ provide: SubmissionFormsConfigDataService, useValue: getMockSubmissionFormsConfigService() },
{ provide: NotificationsService, useClass: NotificationsServiceStub },
{ provide: SectionsService, useClass: SectionsServiceStub },
{ provide: SubmissionService, useClass: SubmissionServiceStub },
{ provide: 'collectionIdProvider', useValue: collectionId },
{ provide: 'sectionDataProvider', useValue: sectionObject },
{ provide: 'submissionIdProvider', useValue: submissionId },
{ provide: PaginationService, useValue: paginationService },
ChangeDetectorRef,
FormBuilderService,
],
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents().then();
}));
// First test to check the correct component creation
describe('', () => {
let testComp: TestComponent;
let testFixture: ComponentFixture<TestComponent>;
// synchronous beforeEach
beforeEach(() => {
sectionsServiceStub.isSectionReadOnly.and.returnValue(observableOf(false));
sectionsServiceStub.getSectionErrors.and.returnValue(observableOf([]));
sectionsServiceStub.getSectionData.and.returnValue(observableOf(sectionObject));
testFixture = TestBed.createComponent(SubmissionSectionDuplicatesComponent);
testComp = testFixture.componentInstance;
});
afterEach(() => {
testFixture.destroy();
});
it('should create SubmissionSectionDuplicatesComponent', () => {
expect(testComp).toBeTruthy();
});
});
describe('', () => {
beforeEach(() => {
fixture = TestBed.createComponent(SubmissionSectionDuplicatesComponent);
comp = fixture.componentInstance;
compAsAny = comp;
submissionServiceStub = TestBed.inject(SubmissionService);
formService = TestBed.inject(FormService);
formBuilderService = TestBed.inject(FormBuilderService);
formOperationsService = TestBed.inject(SectionFormOperationsService);
collectionDataService = TestBed.inject(CollectionDataService);
compAsAny.pathCombiner = new JsonPatchOperationPathCombiner('sections', sectionObject.id);
});
afterEach(() => {
fixture.destroy();
comp = null;
compAsAny = null;
});
// Test initialisation of the submission section
it('Should init section properly', () => {
collectionDataService.findById.and.returnValue(createSuccessfulRemoteDataObject$(mockCollection));
sectionsServiceStub.getSectionErrors.and.returnValue(observableOf([]));
sectionsServiceStub.isSectionReadOnly.and.returnValue(observableOf(false));
compAsAny.submissionService.getSubmissionScope.and.returnValue(SubmissionScopeType.WorkspaceItem);
spyOn(comp, 'getSectionStatus').and.returnValue(observableOf(true));
spyOn(comp, 'getDuplicateData').and.returnValue(observableOf({ potentialDuplicates: duplicates }));
expect(comp.isLoading).toBeTruthy();
comp.onSectionInit();
fixture.detectChanges();
expect(comp.isLoading).toBeFalsy();
});
// The following tests look for proper logic in the getSectionStatus() implementation
// These are very simple as we don't really have a 'false' state unless we're still loading
it('Should return TRUE if the isLoading is FALSE', () => {
compAsAny.isLoading = false;
expect(compAsAny.getSectionStatus()).toBeObservable(cold('(a|)', {
a: true,
}));
});
it('Should return FALSE', () => {
compAsAny.isLoadin = true;
expect(compAsAny.getSectionStatus()).toBeObservable(cold('(a|)', {
a: false,
}));
});
});
});
// declare a test component
@Component({
selector: 'ds-test-cmp',
template: ``,
})
class TestComponent {
}

View File

@@ -0,0 +1,130 @@
import {
ChangeDetectionStrategy,
Component,
Inject,
} from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import {
Observable,
of as observableOf,
Subscription,
} from 'rxjs';
import { Metadata } from '../../../core/shared/metadata.utils';
import { WorkspaceitemSectionDuplicatesObject } from '../../../core/submission/models/workspaceitem-section-duplicates.model';
import { URLCombiner } from '../../../core/url-combiner/url-combiner';
import { getItemModuleRoute } from '../../../item-page/item-page-routing-paths';
import { AlertType } from '../../../shared/alert/alert-type';
import { SubmissionService } from '../../submission.service';
import { SectionModelComponent } from '../models/section.model';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsService } from '../sections.service';
import { renderSectionFor } from '../sections-decorator';
import { SectionsType } from '../sections-type';
/**
* Detect duplicates step
*
* @author Kim Shepherd
*/
@Component({
selector: 'ds-submission-section-duplicates',
templateUrl: './section-duplicates.component.html',
changeDetection: ChangeDetectionStrategy.Default,
})
@renderSectionFor(SectionsType.Duplicates)
export class SubmissionSectionDuplicatesComponent extends SectionModelComponent {
protected readonly Metadata = Metadata;
/**
* The Alert categories.
* @type {AlertType}
*/
public AlertTypeEnum = AlertType;
/**
* Variable to track if the section is loading.
* @type {boolean}
*/
public isLoading = true;
/**
* Array to track all subscriptions and unsubscribe them onDestroy
* @type {Array}
*/
protected subs: Subscription[] = [];
/**
* Initialize instance variables.
*
* @param {TranslateService} translate
* @param {SectionsService} sectionService
* @param {SubmissionService} submissionService
* @param {string} injectedCollectionId
* @param {SectionDataObject} injectedSectionData
* @param {string} injectedSubmissionId
*/
constructor(protected translate: TranslateService,
protected sectionService: SectionsService,
protected submissionService: SubmissionService,
@Inject('collectionIdProvider') public injectedCollectionId: string,
@Inject('sectionDataProvider') public injectedSectionData: SectionDataObject,
@Inject('submissionIdProvider') public injectedSubmissionId: string) {
super(injectedCollectionId, injectedSectionData, injectedSubmissionId);
}
ngOnInit() {
super.ngOnInit();
}
/**
* Initialize all instance variables and retrieve configuration.
*/
onSectionInit() {
this.isLoading = false;
}
/**
* Check if identifier section has read-only visibility
*/
isReadOnly(): boolean {
return true;
}
/**
* Unsubscribe from all subscriptions, if needed.
*/
onSectionDestroy(): void {
return;
}
/**
* Get section status. Because this simple component never requires human interaction, this is basically
* always going to be the opposite of "is this section still loading". This is not the place for API response
* error checking but determining whether the step can 'proceed'.
*
* @return Observable<boolean>
* the section status
*/
public getSectionStatus(): Observable<boolean> {
return observableOf(!this.isLoading);
}
/**
* Get duplicate data as observable from the section data
*/
public getDuplicateData(): Observable<WorkspaceitemSectionDuplicatesObject> {
return this.sectionService.getSectionData(this.submissionId, this.sectionData.id, this.sectionData.sectionType) as
Observable<WorkspaceitemSectionDuplicatesObject>;
}
/**
* Construct and return an item link for use with a preview item stub
* @param uuid
*/
public getItemLink(uuid: any) {
return new URLCombiner(getItemModuleRoute(), uuid).toString();
}
}

View File

@@ -1,20 +1,26 @@
import { TestBed, waitForAsync } from '@angular/core/testing';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import {
TestBed,
waitForAsync,
} from '@angular/core/testing';
import {
DYNAMIC_FORM_CONTROL_TYPE_ARRAY,
DYNAMIC_FORM_CONTROL_TYPE_GROUP,
DynamicFormControlEvent,
DynamicInputModel
DynamicInputModel,
} from '@ng-dynamic-forms/core';
import {
TranslateLoader,
TranslateModule,
} from '@ngx-translate/core';
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
import { getMockFormBuilderService } from '../../../shared/mocks/form-builder-service.mock';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { TranslateLoaderMock } from '../../../shared/mocks/translate-loader.mock';
import { SectionFormOperationsService } from './section-form-operations.service';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { VocabularyEntry } from '../../../core/submission/vocabularies/models/vocabulary-entry.model';
import { DynamicRowArrayModel } from '../../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model';
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
import { FormFieldMetadataValueObject } from '../../../shared/form/builder/models/form-field-metadata-value.model';
import { FormFieldPreviousValueObject } from '../../../shared/form/builder/models/form-field-previous-value-object';
import { getMockFormBuilderService } from '../../../shared/mocks/form-builder-service.mock';
import {
mockInputWithAuthorityValueModel,
mockInputWithFormFieldValueModel,
@@ -25,13 +31,10 @@ import {
mockQualdropInputModel,
MockQualdropModel,
MockRelationModel,
mockRowGroupModel
mockRowGroupModel,
} from '../../../shared/mocks/form-models.mock';
import { FormFieldMetadataValueObject } from '../../../shared/form/builder/models/form-field-metadata-value.model';
import { VocabularyEntry } from '../../../core/submission/vocabularies/models/vocabulary-entry.model';
import {
DynamicRowArrayModel
} from '../../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model';
import { TranslateLoaderMock } from '../../../shared/mocks/translate-loader.mock';
import { SectionFormOperationsService } from './section-form-operations.service';
import { APP_DATA_SERVICES_MAP } from '../../../../config/app-config.interface';
describe('SectionFormOperationsService test suite', () => {
@@ -40,10 +43,10 @@ describe('SectionFormOperationsService test suite', () => {
let serviceAsAny: any;
const jsonPatchOpBuilder: any = jasmine.createSpyObj('jsonPatchOpBuilder', {
add: jasmine.createSpy('add'),
replace: jasmine.createSpy('replace'),
remove: jasmine.createSpy('remove'),
});
add: jasmine.createSpy('add'),
replace: jasmine.createSpy('replace'),
remove: jasmine.createSpy('remove'),
});
const pathCombiner = new JsonPatchOperationPathCombiner('sections', 'test');
const dynamicFormControlChangeEvent: DynamicFormControlEvent = {
@@ -52,7 +55,7 @@ describe('SectionFormOperationsService test suite', () => {
control: null,
group: null,
model: null,
type: 'change'
type: 'change',
};
const dynamicFormControlRemoveEvent: DynamicFormControlEvent = {
@@ -61,7 +64,7 @@ describe('SectionFormOperationsService test suite', () => {
control: null,
group: null,
model: null,
type: 'remove'
type: 'remove',
};
beforeEach(waitForAsync(() => {
@@ -70,16 +73,16 @@ describe('SectionFormOperationsService test suite', () => {
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: TranslateLoaderMock
}
})
useClass: TranslateLoaderMock,
},
}),
],
providers: [
{ provide: FormBuilderService, useValue: getMockFormBuilderService() },
{ provide: JsonPatchOperationsBuilder, useValue: jsonPatchOpBuilder },
{ provide: APP_DATA_SERVICES_MAP, useValue: {} },
SectionFormOperationsService
]
SectionFormOperationsService,
],
}).compileComponents().then();
}));
@@ -118,8 +121,8 @@ describe('SectionFormOperationsService test suite', () => {
it('should return the index of the array to which the element belongs', () => {
const event = Object.assign({}, dynamicFormControlChangeEvent, {
context: {
index: 1
}
index: 1,
},
});
expect(service.getArrayIndexFromEvent(event)).toBe(1);
@@ -130,10 +133,10 @@ describe('SectionFormOperationsService test suite', () => {
model: {
parent: {
parent: {
index: 2
}
}
}
index: 2,
},
},
},
});
spyOn(serviceAsAny, 'isPartOfArrayOfGroup').and.returnValue(true);
@@ -161,10 +164,10 @@ describe('SectionFormOperationsService test suite', () => {
type: DYNAMIC_FORM_CONTROL_TYPE_GROUP,
parent: {
context: {
type: DYNAMIC_FORM_CONTROL_TYPE_ARRAY
}
}
}
type: DYNAMIC_FORM_CONTROL_TYPE_ARRAY,
},
},
},
};
expect(service.isPartOfArrayOfGroup(model as any)).toBeTruthy();
@@ -172,7 +175,7 @@ describe('SectionFormOperationsService test suite', () => {
it('should return false when parent element doesn\'t belong to an array group element', () => {
const model = {
parent: null
parent: null,
};
expect(service.isPartOfArrayOfGroup(model as any)).toBeFalsy();
@@ -185,19 +188,19 @@ describe('SectionFormOperationsService test suite', () => {
const context = {
groups: [
{
group: [MockQualdropModel]
}
]
group: [MockQualdropModel],
},
],
};
const model = {
parent: {
parent: {
context: context
}
}
context: context,
},
},
};
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: model
model: model,
});
const expectMap = new Map();
expectMap.set(MockQualdropModel.qualdropId, [MockQualdropModel.value]);
@@ -211,17 +214,17 @@ describe('SectionFormOperationsService test suite', () => {
const context = {
groups: [
{
group: [MockQualdropModel]
}
]
group: [MockQualdropModel],
},
],
};
const model = {
parent: {
context: context
}
context: context,
},
};
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: model
model: model,
});
const expectMap = new Map();
expectMap.set(MockQualdropModel.qualdropId, [MockQualdropModel.value]);
@@ -251,19 +254,19 @@ describe('SectionFormOperationsService test suite', () => {
const context = {
groups: [
{
group: [MockQualdropModel]
}
]
group: [MockQualdropModel],
},
],
};
const model = {
parent: {
parent: {
context: context
}
}
context: context,
},
},
};
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: model
model: model,
});
const expectPath = 'dc.identifier.issn/0';
spyOn(serviceAsAny, 'getArrayIndexFromEvent').and.returnValue(0);
@@ -277,17 +280,17 @@ describe('SectionFormOperationsService test suite', () => {
const context = {
groups: [
{
group: [MockQualdropModel]
}
]
group: [MockQualdropModel],
},
],
};
const model = {
parent: {
context: context
}
context: context,
},
};
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: model
model: model,
});
const expectPath = 'dc.identifier.issn/0';
spyOn(serviceAsAny, 'getArrayIndexFromEvent').and.returnValue(0);
@@ -301,7 +304,7 @@ describe('SectionFormOperationsService test suite', () => {
describe('getFieldPathSegmentedFromChangeEvent', () => {
it('should return field segmented path properly', () => {
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: mockQualdropInputModel
model: mockQualdropInputModel,
});
formBuilderService.isQualdropGroup.and.returnValues(false, false);
@@ -310,7 +313,7 @@ describe('SectionFormOperationsService test suite', () => {
it('should return field segmented path properly when model is DynamicQualdropModel', () => {
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: MockQualdropModel
model: MockQualdropModel,
});
formBuilderService.isQualdropGroup.and.returnValue(true);
@@ -320,8 +323,8 @@ describe('SectionFormOperationsService test suite', () => {
it('should return field segmented path properly when model belongs to a DynamicQualdropModel', () => {
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: {
parent: MockQualdropModel
}
parent: MockQualdropModel,
},
});
formBuilderService.isQualdropGroup.and.returnValues(false, true);
@@ -334,8 +337,8 @@ describe('SectionFormOperationsService test suite', () => {
it('should return field value properly when model belongs to a DynamicQualdropModel', () => {
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: {
parent: MockQualdropModel
}
parent: MockQualdropModel,
},
});
formBuilderService.isModelInCustomGroup.and.returnValue(true);
const expectedValue = 'test';
@@ -345,18 +348,18 @@ describe('SectionFormOperationsService test suite', () => {
it('should return field value properly when model is DynamicRelationGroupModel', () => {
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: MockRelationModel
model: MockRelationModel,
});
formBuilderService.isModelInCustomGroup.and.returnValue(false);
formBuilderService.isRelationGroup.and.returnValue(true);
const expectedValue = {
journal: [
'journal test 1',
'journal test 2'
'journal test 2',
],
issue: [
'issue test 1',
'issue test 2'
'issue test 2',
],
};
@@ -365,7 +368,7 @@ describe('SectionFormOperationsService test suite', () => {
it('should return field value properly when model has language', () => {
let event = Object.assign({}, dynamicFormControlChangeEvent, {
model: mockInputWithLanguageModel
model: mockInputWithLanguageModel,
});
formBuilderService.isModelInCustomGroup.and.returnValue(false);
formBuilderService.isRelationGroup.and.returnValue(false);
@@ -374,19 +377,19 @@ describe('SectionFormOperationsService test suite', () => {
expect(service.getFieldValueFromChangeEvent(event)).toEqual(expectedValue);
event = Object.assign({}, dynamicFormControlChangeEvent, {
model: mockInputWithLanguageAndAuthorityModel
model: mockInputWithLanguageAndAuthorityModel,
});
expectedValue = Object.assign(new VocabularyEntry(), mockInputWithLanguageAndAuthorityModel.value, {language: mockInputWithLanguageAndAuthorityModel.language});
expectedValue = Object.assign(new VocabularyEntry(), mockInputWithLanguageAndAuthorityModel.value, { language: mockInputWithLanguageAndAuthorityModel.language });
expect(service.getFieldValueFromChangeEvent(event)).toEqual(expectedValue);
event = Object.assign({}, dynamicFormControlChangeEvent, {
model: mockInputWithLanguageAndAuthorityArrayModel
model: mockInputWithLanguageAndAuthorityArrayModel,
});
expectedValue = [
Object.assign(new VocabularyEntry(), mockInputWithLanguageAndAuthorityArrayModel.value[0],
{ language: mockInputWithLanguageAndAuthorityArrayModel.language }
)
{ language: mockInputWithLanguageAndAuthorityArrayModel.language },
),
];
expect(service.getFieldValueFromChangeEvent(event)).toEqual(expectedValue);
@@ -394,7 +397,7 @@ describe('SectionFormOperationsService test suite', () => {
it('should return field value properly when model has an object as value', () => {
let event = Object.assign({}, dynamicFormControlChangeEvent, {
model: mockInputWithFormFieldValueModel
model: mockInputWithFormFieldValueModel,
});
formBuilderService.isModelInCustomGroup.and.returnValue(false);
formBuilderService.isRelationGroup.and.returnValue(false);
@@ -403,14 +406,14 @@ describe('SectionFormOperationsService test suite', () => {
expect(service.getFieldValueFromChangeEvent(event)).toEqual(expectedValue);
event = Object.assign({}, dynamicFormControlChangeEvent, {
model: mockInputWithAuthorityValueModel
model: mockInputWithAuthorityValueModel,
});
expectedValue = mockInputWithAuthorityValueModel.value;
expect(service.getFieldValueFromChangeEvent(event)).toEqual(expectedValue);
event = Object.assign({}, dynamicFormControlChangeEvent, {
model: mockInputWithObjectValueModel
model: mockInputWithObjectValueModel,
});
expectedValue = mockInputWithObjectValueModel.value;
@@ -465,8 +468,8 @@ describe('SectionFormOperationsService test suite', () => {
const previousValue = new FormFieldPreviousValueObject(['path', 'test'], 'value');
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: {
parent: MockQualdropModel
}
parent: MockQualdropModel,
},
});
spyOn(service, 'getFieldPathFromEvent').and.returnValue('path/0');
spyOn(service, 'getFieldPathSegmentedFromChangeEvent').and.returnValue('path');
@@ -485,8 +488,8 @@ describe('SectionFormOperationsService test suite', () => {
const previousValue = new FormFieldPreviousValueObject(['path', 'test'], 'value');
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: {
parent: MockRelationModel
}
parent: MockRelationModel,
},
});
spyOn(service, 'getFieldPathFromEvent').and.returnValue('path/0');
spyOn(service, 'getFieldPathSegmentedFromChangeEvent').and.returnValue('path');
@@ -506,8 +509,8 @@ describe('SectionFormOperationsService test suite', () => {
const previousValue = new FormFieldPreviousValueObject(['path', 'test'], 'value');
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: {
parent: mockRowGroupModel
}
parent: mockRowGroupModel,
},
});
spyOn(service, 'getFieldPathFromEvent').and.returnValue('path/0');
spyOn(service, 'getFieldPathSegmentedFromChangeEvent').and.returnValue('path');
@@ -527,8 +530,8 @@ describe('SectionFormOperationsService test suite', () => {
const previousValue = new FormFieldPreviousValueObject(['path', 'test'], 'value');
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: {
parent: mockRowGroupModel
}
parent: mockRowGroupModel,
},
});
const spyPath = spyOn(service, 'getFieldPathFromEvent').and.returnValue('path/0');
spyOn(service, 'getFieldPathSegmentedFromChangeEvent').and.returnValue('path');
@@ -556,8 +559,8 @@ describe('SectionFormOperationsService test suite', () => {
const previousValue = new FormFieldPreviousValueObject(['path', 'test'], 'value');
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: {
parent: mockRowGroupModel
}
parent: mockRowGroupModel,
},
});
spyOn(service, 'getFieldPathFromEvent').and.returnValue('path/0');
spyOn(service, 'getFieldPathSegmentedFromChangeEvent').and.returnValue('path');
@@ -581,8 +584,8 @@ describe('SectionFormOperationsService test suite', () => {
let previousValue = new FormFieldPreviousValueObject(['path', 'test'], 'value');
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: {
parent: mockRowGroupModel
}
parent: mockRowGroupModel,
},
});
const spyPath = spyOn(service, 'getFieldPathFromEvent').and.returnValue('path/0');
spyOn(service, 'getFieldPathSegmentedFromChangeEvent').and.returnValue('path');
@@ -611,8 +614,8 @@ describe('SectionFormOperationsService test suite', () => {
const previousValue = new FormFieldPreviousValueObject(['path', 'test'], 'value');
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: {
parent: mockRowGroupModel
}
parent: mockRowGroupModel,
},
});
spyOn(service, 'getFieldPathFromEvent').and.returnValue('path/0');
spyOn(service, 'getFieldPathSegmentedFromChangeEvent').and.returnValue('path');
@@ -636,8 +639,8 @@ describe('SectionFormOperationsService test suite', () => {
const previousValue = new FormFieldPreviousValueObject(['path', 'test'], null);
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: {
parent: mockRowGroupModel
}
parent: mockRowGroupModel,
},
});
spyOn(service, 'getFieldPathFromEvent').and.returnValue('path/0');
spyOn(service, 'getFieldPathSegmentedFromChangeEvent').and.returnValue('path');
@@ -662,8 +665,8 @@ describe('SectionFormOperationsService test suite', () => {
const previousValue = new FormFieldPreviousValueObject(['path', 'test'], 'value');
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: {
parent: mockRowGroupModel
}
parent: mockRowGroupModel,
},
});
const spyPath = spyOn(service, 'getFieldPathFromEvent').and.returnValue('path/0');
spyOn(service, 'getFieldPathSegmentedFromChangeEvent').and.returnValue('path');
@@ -697,8 +700,8 @@ describe('SectionFormOperationsService test suite', () => {
const previousValue = new FormFieldPreviousValueObject(['path', 'test'], 'value');
const event = Object.assign({}, dynamicFormControlChangeEvent, {
model: {
parent: mockRowGroupModel
}
parent: mockRowGroupModel,
},
});
spyOn(service, 'getFieldPathFromEvent').and.returnValue('path/1');
spyOn(service, 'getFieldPathSegmentedFromChangeEvent').and.returnValue('path');
@@ -716,7 +719,7 @@ describe('SectionFormOperationsService test suite', () => {
expect(jsonPatchOpBuilder.add).toHaveBeenCalledWith(
pathCombiner.getPath('path'),
new FormFieldMetadataValueObject('test'),
true
true,
);
});
});
@@ -812,7 +815,7 @@ describe('SectionFormOperationsService test suite', () => {
isDraggable: true,
groupFactory: () => {
return [
new DynamicInputModel({ id: 'testFormRowArrayGroupInput' })
new DynamicInputModel({ id: 'testFormRowArrayGroupInput' }),
];
},
required: false,
@@ -820,8 +823,8 @@ describe('SectionFormOperationsService test suite', () => {
metadataFields: ['dc.contributor.author'],
hasSelectableMetadata: true,
showButtons: true,
typeBindRelations: []
}
typeBindRelations: [],
},
);
spyOn(serviceAsAny, 'getFieldPathSegmentedFromChangeEvent').and.returnValue('path');
previousValue = new FormFieldPreviousValueObject(['path'], null);
@@ -835,7 +838,7 @@ describe('SectionFormOperationsService test suite', () => {
pathCombiner,
dynamicFormControlChangeEvent,
arrayModel,
previousValue
previousValue,
);
expect(jsonPatchOpBuilder.add).not.toHaveBeenCalled();
@@ -845,10 +848,10 @@ describe('SectionFormOperationsService test suite', () => {
it('should dispatch a json-path add operation when a array value is not empty', () => {
const pathValue = [
new FormFieldMetadataValueObject('test'),
new FormFieldMetadataValueObject('test two')
new FormFieldMetadataValueObject('test two'),
];
formBuilderService.getValueFromModel.and.returnValue({
path:pathValue
path:pathValue,
});
spyOn(previousValue, 'isPathEqual').and.returnValue(false);
@@ -856,13 +859,13 @@ describe('SectionFormOperationsService test suite', () => {
pathCombiner,
dynamicFormControlChangeEvent,
arrayModel,
previousValue
previousValue,
);
expect(jsonPatchOpBuilder.add).toHaveBeenCalledWith(
pathCombiner.getPath('path'),
pathValue,
false
false,
);
expect(jsonPatchOpBuilder.remove).not.toHaveBeenCalled();
});
@@ -875,7 +878,7 @@ describe('SectionFormOperationsService test suite', () => {
pathCombiner,
dynamicFormControlChangeEvent,
arrayModel,
previousValue
previousValue,
);
expect(jsonPatchOpBuilder.add).not.toHaveBeenCalled();

View File

@@ -1,31 +1,40 @@
import { Injectable } from '@angular/core';
import isEqual from 'lodash/isEqual';
import isObject from 'lodash/isObject';
import {
DYNAMIC_FORM_CONTROL_TYPE_ARRAY,
DYNAMIC_FORM_CONTROL_TYPE_GROUP,
DynamicFormArrayGroupModel,
DynamicFormControlEvent,
DynamicFormControlModel,
isDynamicFormControlEvent
isDynamicFormControlEvent,
} from '@ng-dynamic-forms/core';
import { hasValue, isNotEmpty, isNotNull, isNotUndefined, isNull, isUndefined } from '../../../shared/empty.util';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { FormFieldPreviousValueObject } from '../../../shared/form/builder/models/form-field-previous-value-object';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { FormFieldLanguageValueObject } from '../../../shared/form/builder/models/form-field-language-value.model';
import { DsDynamicInputModel } from '../../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model';
import { VocabularyEntry } from '../../../core/submission/vocabularies/models/vocabulary-entry.model';
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
import { FormFieldMetadataValueObject } from '../../../shared/form/builder/models/form-field-metadata-value.model';
import { DynamicQualdropModel } from '../../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-qualdrop.model';
import { DynamicRelationGroupModel } from '../../../shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model';
import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
import { deepClone } from 'fast-json-patch';
import { dateToString, isNgbDateStruct } from '../../../shared/date.util';
import isEqual from 'lodash/isEqual';
import isObject from 'lodash/isObject';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { VocabularyEntry } from '../../../core/submission/vocabularies/models/vocabulary-entry.model';
import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
import {
dateToString,
isNgbDateStruct,
} from '../../../shared/date.util';
import {
hasValue,
isNotEmpty,
isNotNull,
isNotUndefined,
isNull,
isUndefined,
} from '../../../shared/empty.util';
import { DsDynamicInputModel } from '../../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model';
import { DynamicQualdropModel } from '../../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-qualdrop.model';
import { DynamicRowArrayModel } from '../../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model';
import { DynamicRelationGroupModel } from '../../../shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model';
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
import { FormFieldLanguageValueObject } from '../../../shared/form/builder/models/form-field-language-value.model';
import { FormFieldMetadataValueObject } from '../../../shared/form/builder/models/form-field-metadata-value.model';
import { FormFieldPreviousValueObject } from '../../../shared/form/builder/models/form-field-previous-value-object';
/**
* The service handling all form section operations
@@ -57,9 +66,9 @@ export class SectionFormOperationsService {
* representing if field value related to the specified operation has stored value
*/
public dispatchOperationsFromEvent(pathCombiner: JsonPatchOperationPathCombiner,
event: DynamicFormControlEvent,
previousValue: FormFieldPreviousValueObject,
hasStoredValue: boolean): void {
event: DynamicFormControlEvent,
previousValue: FormFieldPreviousValueObject,
hasStoredValue: boolean): void {
switch (event.type) {
case 'remove':
this.dispatchOperationsFromRemoveEvent(pathCombiner, event, previousValue);
@@ -296,8 +305,8 @@ export class SectionFormOperationsService {
* the [[FormFieldPreviousValueObject]] for the specified operation
*/
protected dispatchOperationsFromRemoveEvent(pathCombiner: JsonPatchOperationPathCombiner,
event: DynamicFormControlEvent,
previousValue: FormFieldPreviousValueObject): void {
event: DynamicFormControlEvent,
previousValue: FormFieldPreviousValueObject): void {
const path = this.getFieldPathFromEvent(event);
const value = this.getFieldValueFromChangeEvent(event);
@@ -321,7 +330,7 @@ export class SectionFormOperationsService {
*/
protected dispatchOperationsFromAddEvent(
pathCombiner: JsonPatchOperationPathCombiner,
event: DynamicFormControlEvent
event: DynamicFormControlEvent,
): void {
const path = this.getFieldPathSegmentedFromChangeEvent(event);
const value = deepClone(this.getFieldValueFromChangeEvent(event));
@@ -360,11 +369,11 @@ export class SectionFormOperationsService {
* representing if field value related to the specified operation has stored value
*/
protected dispatchOperationsFromChangeEvent(pathCombiner: JsonPatchOperationPathCombiner,
event: DynamicFormControlEvent,
previousValue: FormFieldPreviousValueObject,
hasStoredValue: boolean): void {
event: DynamicFormControlEvent,
previousValue: FormFieldPreviousValueObject,
hasStoredValue: boolean): void {
if (event.context && event.context instanceof DynamicFormArrayGroupModel) {
if (event.context && event.context instanceof DynamicFormArrayGroupModel) {
// Model is a DynamicRowArrayModel
this.handleArrayGroupPatch(pathCombiner, event, (event as any).context.context, previousValue);
return;
@@ -399,7 +408,7 @@ export class SectionFormOperationsService {
if (isNotEmpty(moveFrom.path) && isNotEmpty(moveTo.path) && moveFrom.path !== moveTo.path) {
this.operationsBuilder.move(
moveTo,
moveFrom.path
moveFrom.path,
);
}
}
@@ -448,9 +457,9 @@ export class SectionFormOperationsService {
* the [[FormFieldPreviousValueObject]] for the specified operation
*/
protected dispatchOperationsFromMap(valueMap: Map<string, any>,
pathCombiner: JsonPatchOperationPathCombiner,
event: DynamicFormControlEvent,
previousValue: FormFieldPreviousValueObject): void {
pathCombiner: JsonPatchOperationPathCombiner,
event: DynamicFormControlEvent,
previousValue: FormFieldPreviousValueObject): void {
const currentValueMap = valueMap;
if (event.type === 'remove') {
const path = this.getQualdropItemPathFromEvent(event);
@@ -493,8 +502,8 @@ export class SectionFormOperationsService {
* the [[FormFieldPreviousValueObject]] for the specified operation
*/
private dispatchOperationsFromMoveEvent(pathCombiner: JsonPatchOperationPathCombiner,
event: DynamicFormControlEvent,
previousValue: FormFieldPreviousValueObject) {
event: DynamicFormControlEvent,
previousValue: FormFieldPreviousValueObject) {
return this.handleArrayGroupPatch(pathCombiner, event.$event, (event as any).$event.arrayModel, previousValue);
}
@@ -512,9 +521,9 @@ export class SectionFormOperationsService {
* the [[FormFieldPreviousValueObject]] for the specified operation
*/
private handleArrayGroupPatch(pathCombiner: JsonPatchOperationPathCombiner,
event,
model: DynamicRowArrayModel,
previousValue: FormFieldPreviousValueObject) {
event,
model: DynamicRowArrayModel,
previousValue: FormFieldPreviousValueObject) {
const arrayValue = this.formBuilder.getValueFromModel([model]);
const segmentedPath = this.getFieldPathSegmentedFromChangeEvent(event);
@@ -522,7 +531,7 @@ export class SectionFormOperationsService {
this.operationsBuilder.add(
pathCombiner.getPath(segmentedPath),
arrayValue[segmentedPath],
false
false,
);
} else if (previousValue.isPathEqual(this.formBuilder.getPath(event.model))) {
this.operationsBuilder.remove(pathCombiner.getPath(segmentedPath));

View File

@@ -1,48 +1,51 @@
import { ChangeDetectorRef, Component, NO_ERRORS_SCHEMA } from '@angular/core';
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
import { of as observableOf } from 'rxjs';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { createTestComponent } from '../../../shared/testing/utils.test';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
import { SubmissionService } from '../../submission.service';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service.stub';
import { getMockTranslateService } from '../../../shared/mocks/translate.service.mock';
import { SectionsService } from '../sections.service';
import { SectionsServiceStub } from '../../../shared/testing/sections-service.stub';
import { SubmissionSectionFormComponent } from './section-form.component';
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
import { getMockFormBuilderService } from '../../../shared/mocks/form-builder-service.mock';
import { getMockFormOperationsService } from '../../../shared/mocks/form-operations-service.mock';
import { SectionFormOperationsService } from './section-form-operations.service';
import { getMockFormService } from '../../../shared/mocks/form-service.mock';
import { FormService } from '../../../shared/form/form.service';
import { SubmissionFormsConfigDataService } from '../../../core/config/submission-forms-config-data.service';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsType } from '../sections-type';
import {
mockSubmissionCollectionId, mockSubmissionId, mockUploadResponse1ParsedErrors,
} from '../../../shared/mocks/submission.mock';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { FormComponent } from '../../../shared/form/form.component';
import { FormFieldModel } from '../../../shared/form/builder/models/form-field.model';
import { FormFieldMetadataValueObject } from '../../../shared/form/builder/models/form-field-metadata-value.model';
import { DynamicRowGroupModel } from '../../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-group-model';
import { DsDynamicInputModel } from '../../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model';
import { DynamicFormControlEvent, DynamicFormControlEventType } from '@ng-dynamic-forms/core';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { ChangeDetectorRef, Component, NO_ERRORS_SCHEMA, } from '@angular/core';
import { ComponentFixture, inject, TestBed, waitForAsync, } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule, } from '@angular/forms';
import { DynamicFormControlEvent, DynamicFormControlEventType, } from '@ng-dynamic-forms/core';
import { TranslateModule, TranslateService, } from '@ngx-translate/core';
import { cold } from 'jasmine-marbles';
import { of as observableOf } from 'rxjs';
import { ObjectCacheService } from '../../../core/cache/object-cache.service';
import { FormRowModel } from '../../../core/config/models/config-submission-form.model';
import { SubmissionFormsConfigDataService } from '../../../core/config/submission-forms-config-data.service';
import { RequestService } from '../../../core/data/request.service';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { WorkflowItem } from '../../../core/submission/models/workflowitem.model';
import { WorkspaceItem } from '../../../core/submission/models/workspaceitem.model';
import { SubmissionObjectDataService } from '../../../core/submission/submission-object-data.service';
import { ObjectCacheService } from '../../../core/cache/object-cache.service';
import { RequestService } from '../../../core/data/request.service';
import { DsDynamicInputModel } from '../../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model';
import {
DynamicRowGroupModel
} from '../../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-group-model';
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
import { FormFieldModel } from '../../../shared/form/builder/models/form-field.model';
import { FormFieldMetadataValueObject } from '../../../shared/form/builder/models/form-field-metadata-value.model';
import { FormComponent } from '../../../shared/form/form.component';
import { FormService } from '../../../shared/form/form.service';
import { getMockFormBuilderService } from '../../../shared/mocks/form-builder-service.mock';
import { getMockFormOperationsService } from '../../../shared/mocks/form-operations-service.mock';
import { getMockFormService } from '../../../shared/mocks/form-service.mock';
import {
mockSubmissionCollectionId,
mockSubmissionId,
mockUploadResponse1ParsedErrors,
} from '../../../shared/mocks/submission.mock';
import { getMockTranslateService } from '../../../shared/mocks/translate.service.mock';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
import { cold } from 'jasmine-marbles';
import { WorkflowItem } from '../../../core/submission/models/workflowitem.model';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
import { SectionsServiceStub } from '../../../shared/testing/sections-service.stub';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service.stub';
import { createTestComponent } from '../../../shared/testing/utils.test';
import { SubmissionSectionError } from '../../objects/submission-section-error.model';
import { SubmissionService } from '../../submission.service';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsService } from '../sections.service';
import { SectionsType } from '../sections-type';
import { SubmissionSectionFormComponent } from './section-form.component';
import { SectionFormOperationsService } from './section-form-operations.service';
import { getMockThemeService } from '../../../shared/mocks/theme-service.mock';
import { ThemeService } from '../../../shared/theme-support/theme.service';
@@ -64,7 +67,7 @@ const sectionObject: SectionDataObject = {
serverValidationErrors: [],
header: 'submit.progressbar.describe.stepone',
id: 'traditionalpageone',
sectionType: SectionsType.SubmissionForm
sectionType: SectionsType.SubmissionForm,
};
const testFormConfiguration = {
@@ -74,7 +77,7 @@ const testFormConfiguration = {
fields: [
{
input: {
type: 'onebox'
type: 'onebox',
},
label: 'Title',
mandatory: 'true',
@@ -82,18 +85,18 @@ const testFormConfiguration = {
hints: ' Enter Title.',
selectableMetadata: [
{
metadata: 'dc.title'
}
metadata: 'dc.title',
},
],
languageCodes: []
} as FormFieldModel
]
languageCodes: [],
} as FormFieldModel,
],
} as FormRowModel,
{
fields: [
{
input: {
type: 'onebox'
type: 'onebox',
},
label: 'Author',
mandatory: 'false',
@@ -101,20 +104,20 @@ const testFormConfiguration = {
hints: ' Enter Author.',
selectableMetadata: [
{
metadata: 'dc.contributor'
}
metadata: 'dc.contributor',
},
],
languageCodes: []
} as FormFieldModel
]
languageCodes: [],
} as FormFieldModel,
],
} as FormRowModel,
],
type: 'submissionform',
_links: {
self: {
href: 'testFormConfiguration.url'
}
}
href: 'testFormConfiguration.url',
},
},
} as any;
const testFormModel = [
@@ -125,7 +128,7 @@ const testFormModel = [
new DynamicRowGroupModel({
id: 'df-row-group-config-2',
group: [new DsDynamicInputModel({ id: 'dc.contributor', metadataFields: [], repeatable: false, submissionId: '1234', hasSelectableMetadata: false })],
})
}),
];
const dynamicFormControlEvent: DynamicFormControlEvent = {
@@ -134,7 +137,7 @@ const dynamicFormControlEvent: DynamicFormControlEvent = {
control: null,
group: testFormModel[0] as any,
model: testFormModel[0].group[0],
type: DynamicFormControlEventType.Change
type: DynamicFormControlEventType.Change,
};
describe('SubmissionSectionFormComponent test suite', () => {
@@ -166,7 +169,7 @@ describe('SubmissionSectionFormComponent test suite', () => {
TranslateModule.forRoot(),
FormComponent,
SubmissionSectionFormComponent,
TestComponent
TestComponent,
],
providers: [
{ provide: FormBuilderService, useValue: getMockFormBuilderService() },
@@ -187,9 +190,9 @@ describe('SubmissionSectionFormComponent test suite', () => {
{ provide: 'submissionIdProvider', useValue: submissionId },
{ provide: SubmissionObjectDataService, useValue: { getHrefByID: () => observableOf('testUrl'), findById: () => createSuccessfulRemoteDataObject$(new WorkspaceItem()) } },
ChangeDetectorRef,
SubmissionSectionFormComponent
SubmissionSectionFormComponent,
],
schemas: [NO_ERRORS_SCHEMA]
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents().then();
}));
@@ -283,7 +286,7 @@ describe('SubmissionSectionFormComponent test suite', () => {
const sectionData = {};
const sectionError: SubmissionSectionError = {
message: 'test' + 'Error: test',
path: '/sections/' + sectionObject.id
path: '/sections/' + sectionObject.id,
};
comp.initForm(sectionData);
@@ -295,11 +298,11 @@ describe('SubmissionSectionFormComponent test suite', () => {
it('should return true when has Metadata Enrichment', () => {
const newSectionData = {
'dc.title': [new FormFieldMetadataValueObject('test')]
'dc.title': [new FormFieldMetadataValueObject('test')],
};
compAsAny.formData = {};
compAsAny.sectionData.data = {
'dc.title': [new FormFieldMetadataValueObject('test')]
'dc.title': [new FormFieldMetadataValueObject('test')],
};
spyOn(compAsAny, 'inCurrentSubmissionScope').and.callThrough();
@@ -309,11 +312,11 @@ describe('SubmissionSectionFormComponent test suite', () => {
it('should return false when has not Metadata Enrichment', () => {
const newSectionData = {
'dc.title': [new FormFieldMetadataValueObject('test')]
'dc.title': [new FormFieldMetadataValueObject('test')],
};
compAsAny.formData = newSectionData;
compAsAny.sectionData.data = {
'dc.title': [new FormFieldMetadataValueObject('test')]
'dc.title': [new FormFieldMetadataValueObject('test')],
};
spyOn(compAsAny, 'inCurrentSubmissionScope').and.callThrough();
@@ -323,7 +326,7 @@ describe('SubmissionSectionFormComponent test suite', () => {
it('should return false when metadata has Metadata Enrichment but not belonging to sectionMetadata', () => {
const newSectionData = {
'dc.title': [new FormFieldMetadataValueObject('test')]
'dc.title': [new FormFieldMetadataValueObject('test')],
};
compAsAny.formData = newSectionData;
compAsAny.sectionMetadata = [];
@@ -340,16 +343,16 @@ describe('SubmissionSectionFormComponent test suite', () => {
{
selectableMetadata: [{ metadata: 'scoped.workflow' }],
scope: 'WORKFLOW',
} as FormFieldModel
]
} as FormFieldModel,
],
},
{
fields: [
{
selectableMetadata: [{ metadata: 'scoped.workspace' }],
scope: 'WORKSPACE',
} as FormFieldModel
]
} as FormFieldModel,
],
},
{
fields: [
@@ -371,10 +374,10 @@ describe('SubmissionSectionFormComponent test suite', () => {
fields: [
{
selectableMetadata: [{ metadata: 'dc.title' }],
} as FormFieldModel
]
}
]
} as FormFieldModel,
],
},
],
};
});
@@ -437,7 +440,7 @@ describe('SubmissionSectionFormComponent test suite', () => {
spyOn(comp, 'initForm');
spyOn(comp, 'checksForErrors');
const sectionData: any = {
'dc.title': [new FormFieldMetadataValueObject('test')]
'dc.title': [new FormFieldMetadataValueObject('test')],
};
const sectionError = [];
comp.sectionData.data = {};
@@ -458,7 +461,7 @@ describe('SubmissionSectionFormComponent test suite', () => {
spyOn(comp, 'initForm');
spyOn(comp, 'checksForErrors');
const sectionData: any = {
'dc.title': [new FormFieldMetadataValueObject('test')]
'dc.title': [new FormFieldMetadataValueObject('test')],
};
comp.sectionData.data = {};
comp.sectionData.errorsToShow = [];
@@ -497,7 +500,7 @@ describe('SubmissionSectionFormComponent test suite', () => {
sectionObject.id,
'test',
parsedSectionErrors,
[]
[],
);
expect(comp.sectionData.errorsToShow).toEqual(parsedSectionErrors);
});
@@ -506,7 +509,7 @@ describe('SubmissionSectionFormComponent test suite', () => {
formService.isValid.and.returnValue(observableOf(true));
sectionsServiceStub.getSectionServerErrors.and.returnValue(observableOf([]));
const expected = cold('(b|)', {
b: true
b: true,
});
expect(compAsAny.getSectionStatus()).toBeObservable(expected);
@@ -516,7 +519,7 @@ describe('SubmissionSectionFormComponent test suite', () => {
formService.isValid.and.returnValue(observableOf(true));
sectionsServiceStub.getSectionServerErrors.and.returnValue(observableOf(parsedSectionErrors));
const expected = cold('(b|)', {
b: false
b: false,
});
expect(compAsAny.getSectionStatus()).toBeObservable(expected);
@@ -526,7 +529,7 @@ describe('SubmissionSectionFormComponent test suite', () => {
formService.isValid.and.returnValue(observableOf(false));
sectionsServiceStub.getSectionServerErrors.and.returnValue(observableOf([]));
const expected = cold('(b|)', {
b: false
b: false,
});
expect(compAsAny.getSectionStatus()).toBeObservable(expected);
@@ -535,14 +538,14 @@ describe('SubmissionSectionFormComponent test suite', () => {
it('should subscribe to state properly', () => {
spyOn(comp, 'updateForm');
const formData = {
'dc.title': [new FormFieldMetadataValueObject('test')]
'dc.title': [new FormFieldMetadataValueObject('test')],
};
const sectionData: any = {
'dc.title': [new FormFieldMetadataValueObject('test')]
'dc.title': [new FormFieldMetadataValueObject('test')],
};
const sectionState = {
data: sectionData,
errorsToShow: parsedSectionErrors
errorsToShow: parsedSectionErrors,
};
formService.getFormData.and.returnValue(observableOf(formData));
@@ -619,7 +622,7 @@ describe('SubmissionSectionFormComponent test suite', () => {
it('should check if has stored value in the section state', () => {
comp.sectionData.data = {
'dc.title': [new FormFieldMetadataValueObject('test')]
'dc.title': [new FormFieldMetadataValueObject('test')],
} as any;
expect(comp.hasStoredValue('dc.title', 0)).toBeTruthy();

View File

@@ -1,43 +1,42 @@
import { ChangeDetectorRef, Component, Inject, ViewChild } from '@angular/core';
import { DynamicFormControlEvent, DynamicFormControlModel } from '@ng-dynamic-forms/core';
import { combineLatest as observableCombineLatest, Observable, Subscription } from 'rxjs';
import { distinctUntilChanged, filter, find, map, mergeMap, take, tap } from 'rxjs/operators';
import { ChangeDetectorRef, Component, Inject, ViewChild, } from '@angular/core';
import { DynamicFormControlEvent, DynamicFormControlModel, } from '@ng-dynamic-forms/core';
import { TranslateService } from '@ngx-translate/core';
import findIndex from 'lodash/findIndex';
import isEqual from 'lodash/isEqual';
import { combineLatest as observableCombineLatest, Observable, Subscription, } from 'rxjs';
import { distinctUntilChanged, filter, find, map, mergeMap, take, tap, } from 'rxjs/operators';
import { environment } from '../../../../environments/environment';
import { ObjectCacheService } from '../../../core/cache/object-cache.service';
import { ConfigObject } from '../../../core/config/models/config.model';
import { FormRowModel } from '../../../core/config/models/config-submission-form.model';
import { SubmissionFormsModel } from '../../../core/config/models/config-submission-forms.model';
import { SubmissionFormsConfigDataService } from '../../../core/config/submission-forms-config-data.service';
import { RemoteData } from '../../../core/data/remote-data';
import { RequestService } from '../../../core/data/request.service';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { getFirstSucceededRemoteData, getRemoteDataPayload, } from '../../../core/shared/operators';
import { SubmissionObject } from '../../../core/submission/models/submission-object.model';
import { WorkflowItem } from '../../../core/submission/models/workflowitem.model';
import { WorkspaceItem } from '../../../core/submission/models/workspaceitem.model';
import { WorkspaceitemSectionFormObject } from '../../../core/submission/models/workspaceitem-section-form.model';
import { SubmissionObjectDataService } from '../../../core/submission/submission-object-data.service';
import { SubmissionScopeType } from '../../../core/submission/submission-scope-type';
import { hasValue, isEmpty, isNotEmpty, isUndefined, } from '../../../shared/empty.util';
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
import { FormFieldPreviousValueObject } from '../../../shared/form/builder/models/form-field-previous-value-object';
import { FormComponent } from '../../../shared/form/form.component';
import { FormService } from '../../../shared/form/form.service';
import { SectionModelComponent } from '../models/section.model';
import { SubmissionFormsConfigDataService } from '../../../core/config/submission-forms-config-data.service';
import { hasValue, isEmpty, isNotEmpty, isUndefined } from '../../../shared/empty.util';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { SubmissionFormsModel } from '../../../core/config/models/config-submission-forms.model';
import { FormFieldPreviousValueObject } from '../../../shared/form/builder/models/form-field-previous-value-object';
import { SectionDataObject } from '../models/section-data.model';
import { SubmissionService } from '../../submission.service';
import { SectionFormOperationsService } from './section-form-operations.service';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { SectionsService } from '../sections.service';
import { difference } from '../../../shared/object.util';
import { WorkspaceitemSectionFormObject } from '../../../core/submission/models/workspaceitem-section-form.model';
import { WorkspaceItem } from '../../../core/submission/models/workspaceitem.model';
import { getFirstSucceededRemoteData, getRemoteDataPayload } from '../../../core/shared/operators';
import { SubmissionObjectDataService } from '../../../core/submission/submission-object-data.service';
import { ObjectCacheService } from '../../../core/cache/object-cache.service';
import { RequestService } from '../../../core/data/request.service';
import { followLink } from '../../../shared/utils/follow-link-config.model';
import { environment } from '../../../../environments/environment';
import { ConfigObject } from '../../../core/config/models/config.model';
import { RemoteData } from '../../../core/data/remote-data';
import { SubmissionScopeType } from '../../../core/submission/submission-scope-type';
import { WorkflowItem } from '../../../core/submission/models/workflowitem.model';
import { SubmissionObject } from '../../../core/submission/models/submission-object.model';
import { SubmissionSectionObject } from '../../objects/submission-section-object.model';
import { SubmissionSectionError } from '../../objects/submission-section-error.model';
import { FormRowModel } from '../../../core/config/models/config-submission-form.model';
import { SubmissionSectionObject } from '../../objects/submission-section-object.model';
import { SubmissionService } from '../../submission.service';
import { SectionModelComponent } from '../models/section.model';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsService } from '../sections.service';
import { SectionFormOperationsService } from './section-form-operations.service';
import { ThemedLoadingComponent } from '../../../shared/loading/themed-loading.component';
import { NgIf } from '@angular/common';
@@ -188,7 +187,7 @@ export class SubmissionSectionFormComponent extends SectionModelComponent {
this.submissionObjectService.findById(this.submissionId, true, false, followLink('item')).pipe(
getFirstSucceededRemoteData(),
getRemoteDataPayload()),
this.sectionService.isSectionReadOnly(this.submissionId, this.sectionData.id, this.submissionService.getSubmissionScope())
this.sectionService.isSectionReadOnly(this.submissionId, this.sectionData.id, this.submissionService.getSubmissionScope()),
])),
take(1))
.subscribe(([sectionData, submissionObject, isSectionReadOnly]: [WorkspaceitemSectionFormObject, SubmissionObject, boolean]) => {
@@ -224,11 +223,11 @@ export class SubmissionSectionFormComponent extends SectionModelComponent {
protected getSectionStatus(): Observable<boolean> {
const formStatus$ = this.formService.isValid(this.formId);
const serverValidationStatus$ = this.sectionService.getSectionServerErrors(this.submissionId, this.sectionData.id).pipe(
map((validationErrors) => isEmpty(validationErrors))
map((validationErrors) => isEmpty(validationErrors)),
);
return observableCombineLatest([formStatus$, serverValidationStatus$]).pipe(
map(([formValidation, serverSideValidation]: [boolean, boolean]) => formValidation && serverSideValidation)
map(([formValidation, serverSideValidation]: [boolean, boolean]) => formValidation && serverSideValidation),
);
}
@@ -309,7 +308,7 @@ export class SubmissionSectionFormComponent extends SectionModelComponent {
this.collectionId,
sectionData,
this.submissionService.getSubmissionScope(),
this.isSectionReadonly
this.isSectionReadonly,
);
const sectionMetadata = this.sectionService.computeSectionConfiguredMetadata(this.formConfig);
this.sectionService.updateSectionData(this.submissionId, this.sectionData.id, sectionData, this.sectionData.errorsToShow, this.sectionData.serverValidationErrors, sectionMetadata);
@@ -317,9 +316,11 @@ export class SubmissionSectionFormComponent extends SectionModelComponent {
const msg: string = this.translate.instant('error.submission.sections.init-form-error') + e.toString();
const sectionError: SubmissionSectionError = {
message: msg,
path: '/sections/' + this.sectionData.id
path: '/sections/' + this.sectionData.id,
};
console.error(e.stack);
if (e instanceof Error) {
console.error(e.stack);
}
this.sectionService.setSectionError(this.submissionId, this.sectionData.id, sectionError);
}
}
@@ -395,7 +396,7 @@ export class SubmissionSectionFormComponent extends SectionModelComponent {
this.fieldsOnTheirWayToBeRemoved = new Map();
this.sectionMetadata = sectionState.metadata;
this.updateForm(sectionState.data as WorkspaceitemSectionFormObject, sectionState.errorsToShow);
})
}),
);
}
@@ -421,7 +422,7 @@ export class SubmissionSectionFormComponent extends SectionModelComponent {
}
private hasRelatedCustomError(medatata): boolean {
const index = findIndex(this.sectionData.errorsToShow, {path: this.pathCombiner.getPath(medatata).path});
const index = findIndex(this.sectionData.errorsToShow, { path: this.pathCombiner.getPath(medatata).path });
if (index !== -1) {
const error = this.sectionData.errorsToShow[index];
const validator = error.message.replace('error.validation.', '');

View File

@@ -3,58 +3,59 @@ import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { NgxPaginationModule } from 'ngx-pagination';
import { cold } from 'jasmine-marbles';
import { of as observableOf } from 'rxjs';
import { TranslateModule } from '@ngx-translate/core';
import { cold } from 'jasmine-marbles';
import { NgxPaginationModule } from 'ngx-pagination';
import { of as observableOf } from 'rxjs';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
import { createTestComponent } from '../../../shared/testing/utils.test';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
import { SubmissionService } from '../../submission.service';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service.stub';
import { SectionsService } from '../sections.service';
import { SectionsServiceStub } from '../../../shared/testing/sections-service.stub';
import { SubmissionFormsConfigDataService } from '../../../core/config/submission-forms-config-data.service';
import { CollectionDataService } from '../../../core/data/collection-data.service';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { PaginationService } from '../../../core/pagination/pagination.service';
import { Collection } from '../../../core/shared/collection.model';
import { Item } from '../../../core/shared/item.model';
import { License } from '../../../core/shared/license.model';
import {
WorkspaceitemSectionIdentifiersObject
} from '../../../core/submission/models/workspaceitem-section-identifiers.model';
import { SubmissionScopeType } from '../../../core/submission/submission-scope-type';
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
import { FormService } from '../../../shared/form/form.service';
import { getMockFormOperationsService } from '../../../shared/mocks/form-operations-service.mock';
import { getMockFormService } from '../../../shared/mocks/form-service.mock';
import { FormService } from '../../../shared/form/form.service';
import { SubmissionFormsConfigDataService } from '../../../core/config/submission-forms-config-data.service';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsType } from '../sections-type';
import { mockSubmissionCollectionId, mockSubmissionId } from '../../../shared/mocks/submission.mock';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { SubmissionSectionIdentifiersComponent } from './section-identifiers.component';
import { CollectionDataService } from '../../../core/data/collection-data.service';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { SectionFormOperationsService } from '../form/section-form-operations.service';
import { SubmissionScopeType } from '../../../core/submission/submission-scope-type';
import { License } from '../../../core/shared/license.model';
import { Collection } from '../../../core/shared/collection.model';
import { ObjNgFor } from '../../../shared/utils/object-ngfor.pipe';
import { VarDirective } from '../../../shared/utils/var.directive';
import { WorkspaceitemSectionIdentifiersObject } from '../../../core/submission/models/workspaceitem-section-identifiers.model';
import { Item } from '../../../core/shared/item.model';
import { PaginationService } from '../../../core/pagination/pagination.service';
import { mockSubmissionCollectionId, mockSubmissionId, } from '../../../shared/mocks/submission.mock';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub';
import { ConfigurationDataService } from '../../../core/data/configuration-data.service';
import { ConfigurationProperty } from '../../../core/shared/configuration-property.model';
import { SectionsServiceStub } from '../../../shared/testing/sections-service.stub';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service.stub';
import { createTestComponent } from '../../../shared/testing/utils.test';
import { ObjNgFor } from '../../../shared/utils/object-ngfor.pipe';
import { VarDirective } from '../../../shared/utils/var.directive';
import { SubmissionService } from '../../submission.service';
import { SectionFormOperationsService } from '../form/section-form-operations.service';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsService } from '../sections.service';
import { SectionsType } from '../sections-type';
import { SubmissionSectionIdentifiersComponent } from './section-identifiers.component';
function getMockSubmissionFormsConfigService(): SubmissionFormsConfigDataService {
return jasmine.createSpyObj('FormOperationsService', {
getConfigAll: jasmine.createSpy('getConfigAll'),
getConfigByHref: jasmine.createSpy('getConfigByHref'),
getConfigByName: jasmine.createSpy('getConfigByName'),
getConfigBySearch: jasmine.createSpy('getConfigBySearch')
getConfigBySearch: jasmine.createSpy('getConfigBySearch'),
});
}
function getMockCollectionDataService(): CollectionDataService {
return jasmine.createSpyObj('CollectionDataService', {
findById: jasmine.createSpy('findById'),
findByHref: jasmine.createSpy('findByHref')
findByHref: jasmine.createSpy('findByHref'),
});
}
@@ -65,9 +66,9 @@ const mockItem = Object.assign(new Item(), {
'dc.title': [
{
language: null,
value: 'mockmatch'
}
]
value: 'mockmatch',
},
],
},
});
@@ -77,16 +78,16 @@ const identifierData: WorkspaceitemSectionIdentifiersObject = {
value: 'https://doi.org/10.33515/dspace-61',
identifierType: 'doi',
identifierStatus: 'TO_BE_REGISTERED',
type: 'identifier'
type: 'identifier',
},
{
value: '123456789/418',
identifierType: 'handle',
identifierStatus: null,
type: 'identifier'
}
type: 'identifier',
},
],
displayTypes: ['doi', 'handle']
displayTypes: ['doi', 'handle'],
};
// Mock section object to use with tests
@@ -100,7 +101,7 @@ const sectionObject: SectionDataObject = {
header: 'submission.sections.submit.progressbar.identifiers',
id: 'identifiers',
sectionType: SectionsType.Identifiers,
sectionVisibility: null
sectionVisibility: null,
};
describe('SubmissionSectionIdentifiersComponent test suite', () => {
@@ -139,9 +140,9 @@ describe('SubmissionSectionIdentifiersComponent test suite', () => {
{
key: 'dc.title',
language: 'en_US',
value: 'Community 1-Collection 1'
value: 'Community 1-Collection 1',
}],
license: createSuccessfulRemoteDataObject$(Object.assign(new License(), { text: licenseText }))
license: createSuccessfulRemoteDataObject$(Object.assign(new License(), { text: licenseText })),
});
const paginationService = new PaginationServiceStub();
@@ -175,9 +176,9 @@ describe('SubmissionSectionIdentifiersComponent test suite', () => {
{ provide: ConfigurationDataService, useValue: configurationDataService },
ChangeDetectorRef,
FormBuilderService,
SubmissionSectionIdentifiersComponent
SubmissionSectionIdentifiersComponent,
],
schemas: [NO_ERRORS_SCHEMA]
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents().then();
}));
@@ -243,13 +244,13 @@ describe('SubmissionSectionIdentifiersComponent test suite', () => {
it('Should return TRUE if the isLoading is FALSE', () => {
compAsAny.isLoading = false;
expect(compAsAny.getSectionStatus()).toBeObservable(cold('(a|)', {
a: true
a: true,
}));
});
it('Should return FALSE if the identifier data is missing handle', () => {
compAsAny.isLoadin = true;
expect(compAsAny.getSectionStatus()).toBeObservable(cold('(a|)', {
a: false
a: false,
}));
});
});

View File

@@ -2,14 +2,15 @@ import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
import { Observable, of as observableOf, Subscription } from 'rxjs';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { SectionModelComponent } from '../models/section.model';
import { SectionDataObject } from '../models/section-data.model';
import { SubmissionService } from '../../submission.service';
import { AlertType } from '../../../shared/alert/alert-type';
import { SectionsService } from '../sections.service';
import {
WorkspaceitemSectionIdentifiersObject
} from '../../../core/submission/models/workspaceitem-section-identifiers.model';
import { AlertType } from '../../../shared/alert/alert-type';
import { SubmissionService } from '../../submission.service';
import { SectionModelComponent } from '../models/section.model';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsService } from '../sections.service';
import { AsyncPipe, NgForOf, NgIf } from '@angular/common';
import { VarDirective } from '../../../shared/utils/var.directive';
@@ -81,7 +82,7 @@ export class SubmissionSectionIdentifiersComponent extends SectionModelComponent
}
ngOnInit() {
super.ngOnInit();
super.ngOnInit();
}
/**

View File

@@ -1,42 +1,41 @@
import { ChangeDetectorRef, Component, NO_ERRORS_SCHEMA } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
import { of as observableOf } from 'rxjs';
import { ComponentFixture, inject, TestBed, waitForAsync, } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule, } from '@angular/forms';
import { DynamicCheckboxModel, DynamicFormControlEvent, DynamicFormControlEventType, } from '@ng-dynamic-forms/core';
import { TranslateModule } from '@ngx-translate/core';
import { DynamicCheckboxModel, DynamicFormControlEvent, DynamicFormControlEventType } from '@ng-dynamic-forms/core';
import { cold } from 'jasmine-marbles';
import { of as observableOf } from 'rxjs';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
import { createTestComponent } from '../../../shared/testing/utils.test';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
import { SubmissionService } from '../../submission.service';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service.stub';
import { SectionsService } from '../sections.service';
import { SectionsServiceStub } from '../../../shared/testing/sections-service.stub';
import { SubmissionFormsConfigDataService } from '../../../core/config/submission-forms-config-data.service';
import { CollectionDataService } from '../../../core/data/collection-data.service';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { Collection } from '../../../core/shared/collection.model';
import { License } from '../../../core/shared/license.model';
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
import { FormFieldMetadataValueObject } from '../../../shared/form/builder/models/form-field-metadata-value.model';
import { FormComponent } from '../../../shared/form/form.component';
import { FormService } from '../../../shared/form/form.service';
import { getMockFormOperationsService } from '../../../shared/mocks/form-operations-service.mock';
import { getMockFormService } from '../../../shared/mocks/form-service.mock';
import { FormService } from '../../../shared/form/form.service';
import { SubmissionFormsConfigDataService } from '../../../core/config/submission-forms-config-data.service';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsType } from '../sections-type';
import {
mockLicenseParsedErrors,
mockSubmissionCollectionId,
mockSubmissionId
mockSubmissionId,
} from '../../../shared/mocks/submission.mock';
import { FormComponent } from '../../../shared/form/form.component';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { SubmissionSectionLicenseComponent } from './section-license.component';
import { CollectionDataService } from '../../../core/data/collection-data.service';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
import { SectionsServiceStub } from '../../../shared/testing/sections-service.stub';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service.stub';
import { createTestComponent } from '../../../shared/testing/utils.test';
import { SubmissionService } from '../../submission.service';
import { SectionFormOperationsService } from '../form/section-form-operations.service';
import { Collection } from '../../../core/shared/collection.model';
import { License } from '../../../core/shared/license.model';
import { FormFieldMetadataValueObject } from '../../../shared/form/builder/models/form-field-metadata-value.model';
import { cold } from 'jasmine-marbles';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsService } from '../sections.service';
import { SectionsType } from '../sections-type';
import { SubmissionSectionLicenseComponent } from './section-license.component';
import { provideMockStore } from '@ngrx/store/testing';
import {
DsDynamicTypeBindRelationService
@@ -64,9 +63,9 @@ const mockCollection = Object.assign(new Collection(), {
{
key: 'dc.title',
language: 'en_US',
value: 'Community 1-Collection 1'
value: 'Community 1-Collection 1',
}],
license: createSuccessfulRemoteDataObject$(Object.assign(new License(), { text: licenseText }))
license: createSuccessfulRemoteDataObject$(Object.assign(new License(), { text: licenseText })),
});
function getMockSubmissionFormsConfigService(): SubmissionFormsConfigDataService {
@@ -74,7 +73,7 @@ function getMockSubmissionFormsConfigService(): SubmissionFormsConfigDataService
getConfigAll: jasmine.createSpy('getConfigAll'),
getConfigByHref: jasmine.createSpy('getConfigByHref'),
getConfigByName: jasmine.createSpy('getConfigByName'),
getConfigBySearch: jasmine.createSpy('getConfigBySearch')
getConfigBySearch: jasmine.createSpy('getConfigBySearch'),
});
}
@@ -84,13 +83,13 @@ const sectionObject: SectionDataObject = {
data: {
url: null,
acceptanceDate: null,
granted: false
granted: false,
},
errorsToShow: [],
serverValidationErrors: [],
header: 'submit.progressbar.describe.license',
id: 'license',
sectionType: SectionsType.License
sectionType: SectionsType.License,
};
const dynamicFormControlEvent: DynamicFormControlEvent = {
@@ -99,7 +98,7 @@ const dynamicFormControlEvent: DynamicFormControlEvent = {
control: null,
group: null,
model: null,
type: DynamicFormControlEventType.Change
type: DynamicFormControlEventType.Change,
};
describe('SubmissionSectionLicenseComponent test suite', () => {
@@ -124,7 +123,7 @@ describe('SubmissionSectionLicenseComponent test suite', () => {
const mockCollectionDataService = jasmine.createSpyObj('CollectionDataService', {
findById: jasmine.createSpy('findById'),
findByHref: jasmine.createSpy('findByHref')
findByHref: jasmine.createSpy('findByHref'),
});
const initialState: any = {
core: {
@@ -144,7 +143,7 @@ describe('SubmissionSectionLicenseComponent test suite', () => {
TranslateModule.forRoot(),
FormComponent,
SubmissionSectionLicenseComponent,
TestComponent
TestComponent,
],
providers: [
{ provide: CollectionDataService, useValue: mockCollectionDataService },
@@ -165,9 +164,9 @@ describe('SubmissionSectionLicenseComponent test suite', () => {
{ provide: APP_CONFIG, useValue: environment },
{ provide: APP_DATA_SERVICES_MAP, useValue: {} },
{ provide: APP_DYNAMIC_FORM_CONTROL_FN, useValue: dsDynamicFormControlMapFn },
SubmissionSectionLicenseComponent
SubmissionSectionLicenseComponent,
],
schemas: [NO_ERRORS_SCHEMA]
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents().then();
}));
@@ -238,7 +237,7 @@ describe('SubmissionSectionLicenseComponent test suite', () => {
expect(model.value).toBeFalsy();
expect(comp.licenseText$).toBeObservable(cold('(ab|)', {
a: '',
b: licenseText
b: licenseText,
}));
});
@@ -246,7 +245,7 @@ describe('SubmissionSectionLicenseComponent test suite', () => {
comp.sectionData.data = {
url: 'url',
acceptanceDate: Date.now(),
granted: true
granted: true,
} as any;
fixture.detectChanges();
const model = formBuilderService.findById('granted', comp.formModel);
@@ -255,7 +254,7 @@ describe('SubmissionSectionLicenseComponent test suite', () => {
expect(model.value).toBeTruthy();
expect(comp.licenseText$).toBeObservable(cold('(ab|)', {
a: '',
b: licenseText
b: licenseText,
}));
});
@@ -303,7 +302,7 @@ describe('SubmissionSectionLicenseComponent test suite', () => {
comp.sectionData.data = {
url: 'url',
acceptanceDate: Date.now(),
granted: true
granted: true,
} as any;
fixture.detectChanges();

View File

@@ -1,13 +1,14 @@
import { AfterViewChecked, ChangeDetectorRef, Component, Inject, ViewChild } from '@angular/core';
import { AfterViewChecked, ChangeDetectorRef, Component, Inject, ViewChild, } from '@angular/core';
import {
DynamicCheckboxModel,
DynamicFormControlEvent,
DynamicFormControlModel,
DynamicFormLayout
DynamicFormLayout,
} from '@ng-dynamic-forms/core';
import { TranslateService } from '@ngx-translate/core';
import { Observable, Subscription, } from 'rxjs';
import { distinctUntilChanged, filter, find, map, mergeMap, startWith, take, } from 'rxjs/operators';
import { Observable, Subscription } from 'rxjs';
import { distinctUntilChanged, filter, find, map, mergeMap, startWith, take } from 'rxjs/operators';
import { CollectionDataService } from '../../../core/data/collection-data.service';
import { RemoteData } from '../../../core/data/remote-data';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
@@ -15,19 +16,17 @@ import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/jso
import { Collection } from '../../../core/shared/collection.model';
import { License } from '../../../core/shared/license.model';
import { WorkspaceitemSectionLicenseObject } from '../../../core/submission/models/workspaceitem-section-license.model';
import { hasValue, isNotEmpty, isNotNull, isNotUndefined } from '../../../shared/empty.util';
import { hasValue, isNotEmpty, isNotNull, isNotUndefined, } from '../../../shared/empty.util';
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
import { FormComponent } from '../../../shared/form/form.component';
import { FormService } from '../../../shared/form/form.service';
import { followLink } from '../../../shared/utils/follow-link-config.model';
import { SubmissionService } from '../../submission.service';
import { SectionFormOperationsService } from '../form/section-form-operations.service';
import { SectionDataObject } from '../models/section-data.model';
import { SectionModelComponent } from '../models/section.model';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsService } from '../sections.service';
import { SECTION_LICENSE_FORM_LAYOUT, SECTION_LICENSE_FORM_MODEL } from './section-license.model';
import { TranslateService } from '@ngx-translate/core';
import { AsyncPipe, NgIf } from '@angular/common';
/**

View File

@@ -5,9 +5,9 @@ export const SECTION_LICENSE_FORM_LAYOUT = {
element: {
container: 'custom-control custom-checkbox pl-1',
control: 'custom-control-input',
label: 'custom-control-label pt-1'
}
}
label: 'custom-control-label pt-1',
},
},
};
export const SECTION_LICENSE_FORM_MODEL = [
@@ -17,12 +17,12 @@ export const SECTION_LICENSE_FORM_MODEL = [
required: true,
value: false,
validators: {
required: null
required: null,
},
errorMessages: {
required: 'submission.sections.license.required',
notgranted: 'submission.sections.license.notgranted'
notgranted: 'submission.sections.license.notgranted',
},
type: 'CHECKBOX',
}
},
];

View File

@@ -1,6 +1,6 @@
import { WorkspaceitemSectionDataType } from '../../../core/submission/models/workspaceitem-sections.model';
import { SectionsType } from '../sections-type';
import { SubmissionSectionError } from '../../objects/submission-section-error.model';
import { SectionsType } from '../sections-type';
/**
* An interface to represent section model

View File

@@ -1,11 +1,24 @@
import { Component, Inject, OnDestroy, OnInit } from '@angular/core';
import {
Component,
Inject,
OnDestroy,
OnInit,
} from '@angular/core';
import {
Observable,
Subscription,
} from 'rxjs';
import {
filter,
startWith,
} from 'rxjs/operators';
import { Observable, Subscription } from 'rxjs';
import { filter, startWith } from 'rxjs/operators';
import { SectionDataObject } from './section-data.model';
import {
hasValue,
isNotUndefined,
} from '../../../shared/empty.util';
import { SectionsService } from '../sections.service';
import { hasValue, isNotUndefined } from '../../../shared/empty.util';
import { SectionDataObject } from './section-data.model';
export interface SectionDataModel {
sectionData: SectionDataObject;
@@ -16,7 +29,7 @@ export interface SectionDataModel {
*/
@Component({
selector: 'ds-section-model',
template: ''
template: '',
})
export abstract class SectionModelComponent implements OnDestroy, OnInit, SectionDataModel {
protected abstract sectionService: SectionsService;

View File

@@ -0,0 +1,96 @@
import {
cold,
getTestScheduler,
} from 'jasmine-marbles';
import { of } from 'rxjs';
import { TestScheduler } from 'rxjs/testing';
import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service';
import { ObjectCacheService } from '../../../core/cache/object-cache.service';
import { RestResponse } from '../../../core/cache/response.models';
import { CreateData } from '../../../core/data/base/create-data';
import { testCreateDataImplementation } from '../../../core/data/base/create-data.spec';
import { DeleteData } from '../../../core/data/base/delete-data';
import { testDeleteDataImplementation } from '../../../core/data/base/delete-data.spec';
import { FindAllData } from '../../../core/data/base/find-all-data';
import { testFindAllDataImplementation } from '../../../core/data/base/find-all-data.spec';
import { PatchData } from '../../../core/data/base/patch-data';
import { testPatchDataImplementation } from '../../../core/data/base/patch-data.spec';
import { RemoteData } from '../../../core/data/remote-data';
import { RequestService } from '../../../core/data/request.service';
import { RequestEntry } from '../../../core/data/request-entry.model';
import { RequestEntryState } from '../../../core/data/request-entry-state.model';
import { HALEndpointService } from '../../../core/shared/hal-endpoint.service';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
import { CoarNotifyConfigDataService } from './coar-notify-config-data.service';
describe('CoarNotifyConfigDataService test', () => {
let scheduler: TestScheduler;
let service: CoarNotifyConfigDataService;
let requestService: RequestService;
let rdbService: RemoteDataBuildService;
let objectCache: ObjectCacheService;
let halService: HALEndpointService;
let notificationsService: NotificationsService;
let responseCacheEntry: RequestEntry;
const endpointURL = `https://rest.api/rest/api/coar-notify`;
const requestUUID = '8b3c613a-5a4b-438b-9686-be1d5b4a1c5a';
const remoteDataMocks = {
Success: new RemoteData(null, null, null, RequestEntryState.Success, null, null, 200),
};
function initTestService() {
return new CoarNotifyConfigDataService(
requestService,
rdbService,
objectCache,
halService,
notificationsService,
);
}
beforeEach(() => {
scheduler = getTestScheduler();
objectCache = {} as ObjectCacheService;
notificationsService = {} as NotificationsService;
responseCacheEntry = new RequestEntry();
responseCacheEntry.request = { href: 'https://rest.api/' } as any;
responseCacheEntry.response = new RestResponse(true, 200, 'Success');
requestService = jasmine.createSpyObj('requestService', {
generateRequestId: requestUUID,
send: true,
removeByHrefSubstring: {},
getByHref: of(responseCacheEntry),
getByUUID: of(responseCacheEntry),
});
halService = jasmine.createSpyObj('halService', {
getEndpoint: of(endpointURL),
});
rdbService = jasmine.createSpyObj('rdbService', {
buildSingle: createSuccessfulRemoteDataObject$({}, 500),
buildList: cold('a', { a: remoteDataMocks.Success }),
});
service = initTestService();
});
describe('composition', () => {
const initCreateService = () => new CoarNotifyConfigDataService(null, null, null, null, null) as unknown as CreateData<any>;
const initFindAllService = () => new CoarNotifyConfigDataService(null, null, null, null, null) as unknown as FindAllData<any>;
const initDeleteService = () => new CoarNotifyConfigDataService(null, null, null, null, null) as unknown as DeleteData<any>;
const initPatchService = () => new CoarNotifyConfigDataService(null, null, null, null, null) as unknown as PatchData<any>;
testCreateDataImplementation(initCreateService);
testFindAllDataImplementation(initFindAllService);
testPatchDataImplementation(initPatchService);
testDeleteDataImplementation(initDeleteService);
});
});

View File

@@ -1,32 +1,47 @@
import { Injectable } from '@angular/core';
import { dataService } from '../../../core/data/base/data-service.decorator';
import { IdentifiableDataService } from '../../../core/data/base/identifiable-data.service';
import { FindAllData, FindAllDataImpl } from '../../../core/data/base/find-all-data';
import { DeleteData, DeleteDataImpl } from '../../../core/data/base/delete-data';
import { RequestService } from '../../../core/data/request.service';
import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service';
import { ObjectCacheService } from '../../../core/cache/object-cache.service';
import { HALEndpointService } from '../../../core/shared/hal-endpoint.service';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { FindListOptions } from '../../../core/data/find-list-options.model';
import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model';
import { Operation } from 'fast-json-patch';
import { Observable } from 'rxjs';
import { RemoteData } from '../../../core/data/remote-data';
import {
map,
take,
} from 'rxjs/operators';
import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service';
import { RequestParam } from '../../../core/cache/models/request-param.model';
import { ObjectCacheService } from '../../../core/cache/object-cache.service';
import {
CreateData,
CreateDataImpl,
} from '../../../core/data/base/create-data';
import { dataService } from '../../../core/data/base/data-service.decorator';
import {
DeleteData,
DeleteDataImpl,
} from '../../../core/data/base/delete-data';
import {
FindAllData,
FindAllDataImpl,
} from '../../../core/data/base/find-all-data';
import { IdentifiableDataService } from '../../../core/data/base/identifiable-data.service';
import {
PatchData,
PatchDataImpl,
} from '../../../core/data/base/patch-data';
import { ChangeAnalyzer } from '../../../core/data/change-analyzer';
import { FindListOptions } from '../../../core/data/find-list-options.model';
import { PaginatedList } from '../../../core/data/paginated-list.model';
import { NoContent } from '../../../core/shared/NoContent.model';
import { map, take } from 'rxjs/operators';
import { URLCombiner } from '../../../core/url-combiner/url-combiner';
import { RemoteData } from '../../../core/data/remote-data';
import { MultipartPostRequest } from '../../../core/data/request.models';
import { RequestService } from '../../../core/data/request.service';
import { RestRequest } from '../../../core/data/rest-request.model';
import { RestRequestMethod } from '../../../core/data/rest-request-method';
import { HALEndpointService } from '../../../core/shared/hal-endpoint.service';
import { NoContent } from '../../../core/shared/NoContent.model';
import { URLCombiner } from '../../../core/url-combiner/url-combiner';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model';
import { SUBMISSION_COAR_NOTIFY_CONFIG } from './section-coar-notify-service.resource-type';
import { SubmissionCoarNotifyConfig } from './submission-coar-notify.config';
import { CreateData, CreateDataImpl } from '../../../core/data/base/create-data';
import { PatchData, PatchDataImpl } from '../../../core/data/base/patch-data';
import { ChangeAnalyzer } from '../../../core/data/change-analyzer';
import { Operation } from 'fast-json-patch';
import { RestRequestMethod } from '../../../core/data/rest-request-method';
import { getFirstCompletedRemoteData } from '../../../core/shared/operators';
import { hasValue } from '../../../shared/empty.util';
/**
@@ -57,8 +72,8 @@ export class CoarNotifyConfigDataService extends IdentifiableDataService<Submiss
}
create(object: SubmissionCoarNotifyConfig): Observable<RemoteData<SubmissionCoarNotifyConfig>> {
return this.createData.create(object);
create(object: SubmissionCoarNotifyConfig, ...params: RequestParam[]): Observable<RemoteData<SubmissionCoarNotifyConfig>> {
return this.createData.create(object, ...params);
}
patch(object: SubmissionCoarNotifyConfig, operations: Operation[]): Observable<RemoteData<SubmissionCoarNotifyConfig>> {
@@ -81,6 +96,7 @@ export class CoarNotifyConfigDataService extends IdentifiableDataService<Submiss
return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow);
}
public delete(objectId: string, copyVirtualMetadata?: string[]): Observable<RemoteData<NoContent>> {
return this.deleteData.delete(objectId, copyVirtualMetadata);
}
@@ -97,21 +113,12 @@ export class CoarNotifyConfigDataService extends IdentifiableDataService<Submiss
map((endpoint: string) => {
const body = this.getInvocationFormData(files);
return new MultipartPostRequest(requestId, endpoint, body);
})
}),
).subscribe((request: RestRequest) => this.requestService.send(request));
return this.rdbService.buildFromRequestUUID<SubmissionCoarNotifyConfig>(requestId);
}
public SubmissionCoarNotifyConfigModelWithNameExistsAndCanExecute(scriptName: string): Observable<boolean> {
return this.findById(scriptName).pipe(
getFirstCompletedRemoteData(),
map((rd: RemoteData<SubmissionCoarNotifyConfig>) => {
return hasValue(rd.payload);
}),
);
}
private getInvocationFormData(files: File[]): FormData {
const form: FormData = new FormData();
files.forEach((file: File) => {

View File

@@ -44,7 +44,7 @@
[scrollWindow]="false"
>
<button
*ngIf="(filterServices(ldnPattern.pattern) | async)?.length == 0"
*ngIf="(filterServices(ldnPattern.pattern) | async)?.length === 0"
class="dropdown-item collection-item text-truncate w-100"
>
{{'submission.section.section-coar-notify.dropdown.no-data' | translate}}
@@ -58,7 +58,7 @@
</button>
<button
*ngFor="let serviceOption of filterServices(ldnPattern.pattern ) | async"
[ngClass]="{'bg-light': ldnServiceByPattern[ldnPattern.pattern ].services[serviceIndex]?.id == serviceOption.id}"
[ngClass]="{'bg-light': ldnServiceByPattern[ldnPattern.pattern ].services[serviceIndex]?.id === serviceOption.id}"
class="dropdown-item collection-item text-truncate w-100"
(click)="onChange(ldnPattern.pattern, serviceIndex, serviceOption)"
>
@@ -92,7 +92,7 @@
</small>
<ng-container *ngIf="(getShownSectionErrors$(ldnPattern.pattern , serviceIndex) | async)?.length > 0">
<small class="row text-danger" *ngFor="let error of (getShownSectionErrors$(ldnPattern.pattern , serviceIndex) | async)">
{{ error.message | translate}}
{{ error.message | translate}}
</small>
</ng-container>
<div

View File

@@ -1,22 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SubmissionSectionCoarNotifyComponent } from './section-coar-notify.component';
import { LdnServicesService } from '../../../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service';
import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { SectionsService } from '../sections.service';
import { CoarNotifyConfigDataService } from './coar-notify-config-data.service';
import { ChangeDetectorRef } from '@angular/core';
import { SubmissionCoarNotifyConfig } from './submission-coar-notify.config';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
import { createPaginatedList } from '../../../shared/testing/utils.test';
import {
ComponentFixture,
TestBed,
} from '@angular/core/testing';
import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap';
import { TranslateModule } from '@ngx-translate/core';
import { of } from 'rxjs';
import { LdnServicesService } from '../../../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service';
import { NotifyServicePattern } from '../../../admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model';
import {
LdnService,
LdnServiceByPattern
LdnServiceByPattern,
} from '../../../admin/admin-ldn-services/ldn-services-model/ldn-services.model';
import { NotifyServicePattern } from '../../../admin/admin-ldn-services/ldn-services-model/ldn-service-patterns.model';
import { TranslateModule } from '@ngx-translate/core';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
import { createPaginatedList } from '../../../shared/testing/utils.test';
import { SectionsService } from '../sections.service';
import { CoarNotifyConfigDataService } from './coar-notify-config-data.service';
import { SubmissionSectionCoarNotifyComponent } from './section-coar-notify.component';
import { SubmissionCoarNotifyConfig } from './submission-coar-notify.config';
describe('SubmissionSectionCoarNotifyComponent', () => {
let component: SubmissionSectionCoarNotifyComponent;
@@ -33,8 +36,8 @@ describe('SubmissionSectionCoarNotifyComponent', () => {
const patterns: SubmissionCoarNotifyConfig[] = Object.assign(
[new SubmissionCoarNotifyConfig()],
{
patterns: [{pattern: 'review', multipleRequest: false}, {pattern: 'endorsment', multipleRequest: false}],
}
patterns: [{ pattern: 'review', multipleRequest: false }, { pattern: 'endorsment', multipleRequest: false }],
},
);
const patternsPL = createPaginatedList(patterns);
const coarNotifyConfig = createSuccessfulRemoteDataObject$(patternsPL);
@@ -45,7 +48,7 @@ describe('SubmissionSectionCoarNotifyComponent', () => {
]);
coarNotifyConfigDataService = jasmine.createSpyObj(
'CoarNotifyConfigDataService',
['findAll']
['findAll'],
);
operationsBuilder = jasmine.createSpyObj('JsonPatchOperationsBuilder', [
'remove',
@@ -88,8 +91,8 @@ describe('SubmissionSectionCoarNotifyComponent', () => {
Object.assign([], {
path: 'sections/sectionId/data/notifyCoar',
message: 'error',
})
)
}),
),
);
fixture.detectChanges();
});
@@ -111,7 +114,7 @@ describe('SubmissionSectionCoarNotifyComponent', () => {
});
describe('onChange', () => {
const ldnPattern = {pattern: 'review', multipleRequest: false};
const ldnPattern = { pattern: 'review', multipleRequest: false };
const index = 0;
const selectedService: LdnService = Object.assign(new LdnService(), {
id: 1,
@@ -127,7 +130,7 @@ describe('SubmissionSectionCoarNotifyComponent', () => {
beforeEach(() => {
component.ldnServiceByPattern[ldnPattern.pattern] = {
allowsMultipleRequests: false,
services: []
services: [],
} as LdnServiceByPattern;
component.patterns = [];
@@ -148,7 +151,7 @@ describe('SubmissionSectionCoarNotifyComponent', () => {
component.onChange(ldnPattern.pattern, index, null);
expect(componentAsAny.operationsBuilder.flushOperation).toHaveBeenCalledWith(
componentAsAny.pathCombiner.getPath([ldnPattern.pattern, '-'])
componentAsAny.pathCombiner.getPath([ldnPattern.pattern, '-']),
);
expect(component.ldnServiceByPattern[ldnPattern.pattern].services[index]).toBeNull();
expect(component.previousServices[ldnPattern.pattern].services[index]).toBeNull();
@@ -168,7 +171,7 @@ describe('SubmissionSectionCoarNotifyComponent', () => {
component.ldnServiceByPattern[ldnPattern.pattern].services[index] = previousService;
component.previousServices[ldnPattern.pattern] = {
allowsMultipleRequests: false,
services: [previousService]
services: [previousService],
} as LdnServiceByPattern;
component.onChange(ldnPattern.pattern, index, selectedService);
@@ -177,13 +180,13 @@ describe('SubmissionSectionCoarNotifyComponent', () => {
componentAsAny.pathCombiner.getPath([ldnPattern.pattern, '-']),
[selectedService.id],
false,
true
true,
);
expect(component.ldnServiceByPattern[ldnPattern.pattern].services[index]).toEqual(
selectedService
selectedService,
);
expect(component.previousServices[ldnPattern.pattern].services[index].id).toEqual(
selectedService.id
selectedService.id,
);
});
@@ -194,20 +197,20 @@ describe('SubmissionSectionCoarNotifyComponent', () => {
componentAsAny.pathCombiner.getPath([ldnPattern.pattern, '-']),
[selectedService.id],
false,
true
true,
);
expect(component.ldnServiceByPattern[ldnPattern.pattern].services[index]).toEqual(
selectedService
selectedService,
);
expect(component.previousServices[ldnPattern.pattern].services[index].id).toEqual(
selectedService.id
selectedService.id,
);
});
});
describe('initSelectedServicesByPattern', () => {
const pattern1 = {pattern: 'review', multipleRequest: false};
const pattern2 = {pattern: 'endorsement', multipleRequest: false};
const pattern1 = { pattern: 'review', multipleRequest: false };
const pattern2 = { pattern: 'endorsement', multipleRequest: false };
const service1: LdnService = Object.assign(new LdnService(), {
id: 1,
uuid: 1,
@@ -246,16 +249,16 @@ describe('SubmissionSectionCoarNotifyComponent', () => {
beforeEach(() => {
ldnServicesService.findByInboundPattern.and.returnValue(
createSuccessfulRemoteDataObject$(createPaginatedList(services))
createSuccessfulRemoteDataObject$(createPaginatedList(services)),
);
component.ldnServiceByPattern[pattern1.pattern] = {
allowsMultipleRequests: false,
services: []
services: [],
} as LdnServiceByPattern;
component.ldnServiceByPattern[pattern2.pattern] = {
allowsMultipleRequests: false,
services: []
services: [],
} as LdnServiceByPattern;
component.patterns = [pattern1, pattern2];
@@ -289,7 +292,7 @@ describe('SubmissionSectionCoarNotifyComponent', () => {
});
describe('addService', () => {
const ldnPattern = {pattern: 'review', multipleRequest: false};
const ldnPattern = { pattern: 'review', multipleRequest: false };
const service: any = {
id: 1,
name: 'service1',
@@ -299,7 +302,7 @@ describe('SubmissionSectionCoarNotifyComponent', () => {
beforeEach(() => {
component.ldnServiceByPattern[ldnPattern.pattern] = {
allowsMultipleRequests: false,
services: []
services: [],
} as LdnServiceByPattern;
});
@@ -311,7 +314,7 @@ describe('SubmissionSectionCoarNotifyComponent', () => {
});
describe('removeService', () => {
const ldnPattern = {pattern: 'review', multipleRequest: false};
const ldnPattern = { pattern: 'review', multipleRequest: false };
const service1: LdnService = Object.assign(new LdnService(), {
id: 1,
name: 'service1',
@@ -343,7 +346,7 @@ describe('SubmissionSectionCoarNotifyComponent', () => {
beforeEach(() => {
component.ldnServiceByPattern[ldnPattern.pattern] = {
allowsMultipleRequests: false,
services: []
services: [],
} as LdnServiceByPattern;
});
@@ -380,7 +383,7 @@ describe('SubmissionSectionCoarNotifyComponent', () => {
beforeEach(() => {
ldnServicesService.findByInboundPattern.and.returnValue(
createSuccessfulRemoteDataObject$(createPaginatedList(services))
createSuccessfulRemoteDataObject$(createPaginatedList(services)),
);
});
@@ -414,7 +417,7 @@ describe('SubmissionSectionCoarNotifyComponent', () => {
{ path: 'sections/sectionId/data/notifyCoar', message: 'error' },
];
sectionService.getSectionServerErrors.and.returnValue(
of(validationErrors)
of(validationErrors),
);
componentAsAny.getSectionServerErrorsAndSetErrorsToDisplay();
@@ -422,7 +425,7 @@ describe('SubmissionSectionCoarNotifyComponent', () => {
expect(sectionService.setSectionError).toHaveBeenCalledWith(
component.submissionId,
component.sectionData.id,
validationErrors[0]
validationErrors[0],
);
});
});

View File

@@ -5,6 +5,8 @@ import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { SectionsService } from '../sections.service';
import { SectionDataObject } from '../models/section-data.model';
import { NgbDropdown, NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
import { filter, map, take, tap, } from 'rxjs/operators';
import { hasValue, isEmpty, isNotEmpty } from '../../../shared/empty.util';
@@ -16,11 +18,9 @@ import {
import { LdnServicesService } from '../../../admin/admin-ldn-services/ldn-services-data/ldn-services-data.service';
import {
LdnService,
LdnServiceByPattern
LdnServiceByPattern,
} from '../../../admin/admin-ldn-services/ldn-services-model/ldn-services.model';
import { CoarNotifyConfigDataService } from './coar-notify-config-data.service';
import { filter, map, take, tap } from 'rxjs/operators';
import { NgbDropdown, NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
import { SubmissionSectionError } from '../../objects/submission-section-error.model';
import { LdnPattern } from './submission-coar-notify.config';
import { AsyncPipe, NgClass, NgForOf, NgIf } from '@angular/common';
@@ -44,7 +44,7 @@ import { InfiniteScrollModule } from 'ngx-infinite-scroll';
NgClass,
InfiniteScrollModule
],
providers: [NgbDropdown]
providers: [NgbDropdown],
})
export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent {
@@ -87,6 +87,8 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent
*/
protected subs: Subscription[] = [];
private filteredServicesByPattern = {};
constructor(protected ldnServicesService: LdnServicesService,
// protected formOperationsService: SectionFormOperationsService,
protected operationsBuilder: JsonPatchOperationsBuilder,
@@ -115,7 +117,7 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent
setCoarNotifyConfig() {
this.subs.push(
this.coarNotifyConfigDataService.findAll().pipe(
getFirstCompletedRemoteData()
getFirstCompletedRemoteData(),
).subscribe((data) => {
if (data.hasSucceeded) {
this.patterns = data.payload.page[0].patterns;
@@ -140,7 +142,7 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent
if (!this.previousServices[pattern]) {
this.previousServices[pattern] = {
services: [],
allowsMultipleRequests: this.patterns.find(ldnPattern => ldnPattern.pattern === pattern)?.multipleRequest
allowsMultipleRequests: this.patterns.find(ldnPattern => ldnPattern.pattern === pattern)?.multipleRequest,
};
}
@@ -153,11 +155,14 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent
if (hasPrevValueStored) {
// when there is a previous value stored and it is different from the new one
this.operationsBuilder.flushOperation(this.pathCombiner.getPath([pattern, '-']));
if (this.filteredServicesByPattern[pattern]?.includes(this.previousServices[pattern].services[index])){
this.operationsBuilder.remove(this.pathCombiner.getPath([pattern, index.toString()]));
}
}
if (!hasPrevValueStored || (selectedService?.id && hasPrevValueStored) || (!hasValue(selectedService) && hasPrevValueStored)) {
if (!hasPrevValueStored || (selectedService?.id && hasPrevValueStored)) {
// add the path when there is no previous value stored
this.operationsBuilder.add(this.pathCombiner.getPath([pattern, '-']), hasValue(selectedService) ? [selectedService.id] : [], false, true);
this.operationsBuilder.add(this.pathCombiner.getPath([pattern, '-']), [selectedService.id], false, true);
}
// set the previous value to the new value
this.previousServices[pattern].services[index] = this.ldnServiceByPattern[pattern].services[index];
@@ -182,7 +187,7 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent
if (!this.ldnServiceByPattern[ldnPattern.pattern]) {
this.ldnServiceByPattern[ldnPattern.pattern] = {
services: [],
allowsMultipleRequests: ldnPattern.multipleRequest
allowsMultipleRequests: ldnPattern.multipleRequest,
};
}
@@ -191,12 +196,12 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent
this.addService(ldnPattern, selection);
return this.sectionData.data[ldnPattern.pattern].includes(service.uuid);
});
})
}),
);
} else {
this.ldnServiceByPattern[ldnPattern.pattern] = {
services: [],
allowsMultipleRequests: ldnPattern.multipleRequest
allowsMultipleRequests: ldnPattern.multipleRequest,
};
this.addService(ldnPattern, null);
}
@@ -214,7 +219,7 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent
if (!this.ldnServiceByPattern[ldnPattern.pattern]) {
this.ldnServiceByPattern[ldnPattern.pattern] = {
services: [],
allowsMultipleRequests: ldnPattern.multipleRequest
allowsMultipleRequests: ldnPattern.multipleRequest,
};
}
this.ldnServiceByPattern[ldnPattern.pattern].services.push(newService);
@@ -253,12 +258,20 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent
filter((rd) => rd.hasSucceeded),
getRemoteDataPayload(),
getPaginatedListPayload(),
tap(res => {
if (!this.filteredServicesByPattern[pattern]){
this.filteredServicesByPattern[pattern] = [];
}
if (this.filteredServicesByPattern[pattern].length === 0) {
this.filteredServicesByPattern[pattern].push(...res);
}
}),
map((res: LdnService[]) => res.filter((service) => {
if (!this.hasSectionData){
this.hasSectionData = this.hasInboundPattern(service, pattern);
}
return this.hasInboundPattern(service, pattern);
}))
if (!this.hasSectionData){
this.hasSectionData = this.hasInboundPattern(service, pattern);
}
return this.hasInboundPattern(service, pattern);
})),
);
}
@@ -308,7 +321,7 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent
const path = `${pattern}/${index}`;
return error.path.includes(path);
});
})
}),
);
}
@@ -317,7 +330,7 @@ export class SubmissionSectionCoarNotifyComponent extends SectionModelComponent
*/
protected getSectionStatus(): Observable<boolean> {
return this.sectionService.getSectionServerErrors(this.submissionId, this.sectionData.id).pipe(
map((validationErrors) => isEmpty(validationErrors)
map((validationErrors) => isEmpty(validationErrors),
));
}

View File

@@ -1,11 +1,15 @@
import { CacheableObject } from '../../../core/cache/cacheable-object.model';
import { autoserialize, deserialize, deserializeAs, inheritSerialization } from 'cerialize';
import {
autoserialize,
deserialize,
deserializeAs,
inheritSerialization,
} from 'cerialize';
import { excludeFromEquals } from '../../../core/utilities/equals.decorators';
import { typedObject } from '../../../core/cache/builders/build-decorators';
import { CacheableObject } from '../../../core/cache/cacheable-object.model';
import { excludeFromEquals } from '../../../core/utilities/equals.decorators';
import { COAR_NOTIFY_WORKSPACEITEM } from './section-coar-notify-service.resource-type';
/** An CoarNotify and its properties. */
@typedObject
@inheritSerialization(CacheableObject)
@@ -14,16 +18,16 @@ export class SubmissionCoarNotifyWorkspaceitemModel extends CacheableObject {
@excludeFromEquals
@autoserialize
endorsement?: number[];
endorsement?: number[];
@deserializeAs('id')
review?: number[];
review?: number[];
@autoserialize
ingest?: number[];
ingest?: number[];
@deserialize
_links: {
_links: {
self: {
href: string;
};

View File

@@ -1,9 +1,14 @@
import { ResourceType } from '../../../core/shared/resource-type';
import { CacheableObject } from '../../../core/cache/cacheable-object.model';
import { autoserialize, deserialize, deserializeAs, inheritSerialization } from 'cerialize';
import {
autoserialize,
deserialize,
deserializeAs,
inheritSerialization,
} from 'cerialize';
import { excludeFromEquals } from '../../../core/utilities/equals.decorators';
import { typedObject } from '../../../core/cache/builders/build-decorators';
import { CacheableObject } from '../../../core/cache/cacheable-object.model';
import { ResourceType } from '../../../core/shared/resource-type';
import { excludeFromEquals } from '../../../core/utilities/equals.decorators';
import { SUBMISSION_COAR_NOTIFY_CONFIG } from './section-coar-notify-service.resource-type';
export interface LdnPattern {
@@ -18,19 +23,19 @@ export class SubmissionCoarNotifyConfig extends CacheableObject {
@excludeFromEquals
@autoserialize
type: ResourceType;
type: ResourceType;
@autoserialize
id: string;
id: string;
@deserializeAs('id')
uuid: string;
uuid: string;
@autoserialize
patterns: LdnPattern[];
patterns: LdnPattern[];
@deserialize
_links: {
_links: {
self: {
href: string;
};

View File

@@ -9,5 +9,6 @@ export enum SectionsType {
SherpaPolicies = 'sherpaPolicy',
Identifiers = 'identifiers',
Collection = 'collection',
CoarNotify = 'coarnotify'
CoarNotify = 'coarnotify',
Duplicates = 'duplicates'
}

View File

@@ -1,15 +1,27 @@
import { ChangeDetectorRef, Directive, Input, OnDestroy, OnInit } from '@angular/core';
import { Observable, Subscription } from 'rxjs';
import { map } from 'rxjs/operators';
import {
ChangeDetectorRef,
Directive,
Input,
OnDestroy,
OnInit,
} from '@angular/core';
import uniq from 'lodash/uniq';
import {
Observable,
Subscription,
} from 'rxjs';
import { map } from 'rxjs/operators';
import { SectionsService } from './sections.service';
import { hasValue, isNotEmpty, isNotNull } from '../../shared/empty.util';
import parseSectionErrorPaths, { SectionErrorPath } from '../utils/parseSectionErrorPaths';
import { SubmissionService } from '../submission.service';
import { SectionsType } from './sections-type';
import {
hasValue,
isNotEmpty,
isNotNull,
} from '../../shared/empty.util';
import { SubmissionSectionError } from '../objects/submission-section-error.model';
import { SubmissionService } from '../submission.service';
import parseSectionErrorPaths, { SectionErrorPath } from '../utils/parseSectionErrorPaths';
import { SectionsService } from './sections.service';
import { SectionsType } from './sections-type';
/**
* Directive for handling generic section functionality
@@ -141,7 +153,7 @@ export class SectionsDirective implements OnDestroy, OnInit {
this.submissionService.dispatchSave(this.submissionId);
}
}
})
}),
);
this.enabled = this.sectionService.isSectionEnabled(this.submissionId, this.sectionId);

View File

@@ -1,42 +1,54 @@
import { TestBed, waitForAsync } from '@angular/core/testing';
import { cold, getTestScheduler } from 'jasmine-marbles';
import { of as observableOf } from 'rxjs';
import { Store, StoreModule } from '@ngrx/store';
import {
TestBed,
waitForAsync,
} from '@angular/core/testing';
import {
Store,
StoreModule,
} from '@ngrx/store';
import {
TranslateLoader,
TranslateModule,
TranslateService,
} from '@ngx-translate/core';
import { ScrollToService } from '@nicky-lenaers/ngx-scroll-to';
import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
import {
cold,
getTestScheduler,
} from 'jasmine-marbles';
import { of as observableOf } from 'rxjs';
import { submissionReducers } from '../submission.reducers';
import { TranslateLoaderMock } from '../../shared/mocks/translate-loader.mock';
import { NotificationsService } from '../../shared/notifications/notifications.service';
import { SubmissionService } from '../submission.service';
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
import { SubmissionServiceStub } from '../../shared/testing/submission-service.stub';
import { getMockTranslateService } from '../../shared/mocks/translate.service.mock';
import { SectionsService } from './sections.service';
import { storeModuleConfig } from '../../app.reducer';
import { SubmissionScopeType } from '../../core/submission/submission-scope-type';
import { FormClearErrorsAction } from '../../shared/form/form.actions';
import { FormService } from '../../shared/form/form.service';
import { getMockFormService } from '../../shared/mocks/form-service.mock';
import { getMockScrollToService } from '../../shared/mocks/scroll-to-service.mock';
import {
mockSectionsData,
mockSectionsErrors,
mockSubmissionState,
mockSubmissionStateWithoutUpload
mockSubmissionStateWithoutUpload,
} from '../../shared/mocks/submission.mock';
import { getMockTranslateService } from '../../shared/mocks/translate.service.mock';
import { TranslateLoaderMock } from '../../shared/mocks/translate-loader.mock';
import { NotificationsService } from '../../shared/notifications/notifications.service';
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
import { SubmissionServiceStub } from '../../shared/testing/submission-service.stub';
import {
DisableSectionAction,
EnableSectionAction,
InertSectionErrorsAction,
RemoveSectionErrorsAction,
SectionStatusChangeAction,
UpdateSectionDataAction
UpdateSectionDataAction,
} from '../objects/submission-objects.actions';
import { FormClearErrorsAction } from '../../shared/form/form.actions';
import parseSectionErrors from '../utils/parseSectionErrors';
import { SubmissionScopeType } from '../../core/submission/submission-scope-type';
import { getMockScrollToService } from '../../shared/mocks/scroll-to-service.mock';
import { storeModuleConfig } from '../../app.reducer';
import { SectionsType } from './sections-type';
import { FormService } from '../../shared/form/form.service';
import { getMockFormService } from '../../shared/mocks/form-service.mock';
import { SubmissionSectionError } from '../objects/submission-section-error.model';
import { submissionReducers } from '../submission.reducers';
import { SubmissionService } from '../submission.service';
import parseSectionErrors from '../utils/parseSectionErrors';
import { SectionsService } from './sections.service';
import { SectionsType } from './sections-type';
describe('SectionsService test suite', () => {
let notificationsServiceStub: NotificationsServiceStub;
@@ -56,7 +68,7 @@ describe('SectionsService test suite', () => {
const store: any = jasmine.createSpyObj('store', {
dispatch: jasmine.createSpy('dispatch'),
select: jasmine.createSpy('select')
select: jasmine.createSpy('select'),
});
const formService: any = getMockFormService();
@@ -68,9 +80,9 @@ describe('SectionsService test suite', () => {
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: TranslateLoaderMock
}
})
useClass: TranslateLoaderMock,
},
}),
],
providers: [
{ provide: NotificationsService, useClass: NotificationsServiceStub },
@@ -79,8 +91,8 @@ describe('SectionsService test suite', () => {
{ provide: TranslateService, useValue: getMockTranslateService() },
{ provide: Store, useValue: store },
{ provide: FormService, useValue: formService },
SectionsService
]
SectionsService,
],
}).compileComponents();
}));
@@ -161,7 +173,7 @@ describe('SectionsService test suite', () => {
store.select.and.returnValue(observableOf(sectionData[sectionId]));
const expected = cold('(b|)', {
b: sectionData[sectionId]
b: sectionData[sectionId],
});
expect(service.getSectionData(submissionId, sectionId, SectionsType.SubmissionForm)).toBeObservable(expected);
@@ -173,7 +185,7 @@ describe('SectionsService test suite', () => {
store.select.and.returnValue(observableOf(sectionErrors[sectionId]));
const expected = cold('(b|)', {
b: sectionErrors[sectionId]
b: sectionErrors[sectionId],
});
expect(service.getSectionErrors(submissionId, sectionId)).toBeObservable(expected);
@@ -185,7 +197,7 @@ describe('SectionsService test suite', () => {
store.select.and.returnValue(observableOf(sectionState));
const expected = cold('(b|)', {
b: sectionState
b: sectionState,
});
expect(service.getSectionState(submissionId, sectionId, SectionsType.SubmissionForm)).toBeObservable(expected);
@@ -197,7 +209,7 @@ describe('SectionsService test suite', () => {
store.select.and.returnValue(observableOf({ isValid: false }));
let expected = cold('(b|)', {
b: false
b: false,
});
expect(service.isSectionValid(submissionId, sectionId)).toBeObservable(expected);
@@ -205,7 +217,7 @@ describe('SectionsService test suite', () => {
store.select.and.returnValue(observableOf({ isValid: true }));
expected = cold('(b|)', {
b: true
b: true,
});
expect(service.isSectionValid(submissionId, sectionId)).toBeObservable(expected);
@@ -217,7 +229,7 @@ describe('SectionsService test suite', () => {
submissionServiceStub.getActiveSectionId.and.returnValue(observableOf(sectionId));
let expected = cold('(b|)', {
b: true
b: true,
});
expect(service.isSectionActive(submissionId, sectionId)).toBeObservable(expected);
@@ -225,7 +237,7 @@ describe('SectionsService test suite', () => {
submissionServiceStub.getActiveSectionId.and.returnValue(observableOf('test'));
expected = cold('(b|)', {
b: false
b: false,
});
expect(service.isSectionActive(submissionId, sectionId)).toBeObservable(expected);
@@ -237,7 +249,7 @@ describe('SectionsService test suite', () => {
store.select.and.returnValue(observableOf({ enabled: false }));
let expected = cold('(b|)', {
b: false
b: false,
});
expect(service.isSectionEnabled(submissionId, sectionId)).toBeObservable(expected);
@@ -245,7 +257,7 @@ describe('SectionsService test suite', () => {
store.select.and.returnValue(observableOf({ enabled: true }));
expected = cold('(b|)', {
b: true
b: true,
});
expect(service.isSectionEnabled(submissionId, sectionId)).toBeObservable(expected);
@@ -257,12 +269,12 @@ describe('SectionsService test suite', () => {
store.select.and.returnValue(observableOf({
visibility: {
main: null,
other: 'READONLY'
}
other: 'READONLY',
},
}));
const expected = cold('(b|)', {
b: true
b: true,
});
expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkflowItem)).toBeObservable(expected);
@@ -272,12 +284,12 @@ describe('SectionsService test suite', () => {
store.select.and.returnValue(observableOf({
visibility: {
main: null,
other: 'READONLY'
}
other: 'READONLY',
},
}));
const expected = cold('(b|)', {
b: false
b: false,
});
expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkspaceItem)).toBeObservable(expected);
@@ -285,11 +297,11 @@ describe('SectionsService test suite', () => {
it('should return an observable of false when it\'s not a readonly section', () => {
store.select.and.returnValue(observableOf({
visibility: null
visibility: null,
}));
const expected = cold('(b|)', {
b: false
b: false,
});
expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkflowItem)).toBeObservable(expected);
@@ -301,7 +313,7 @@ describe('SectionsService test suite', () => {
store.select.and.returnValue(observableOf(submissionState));
const expected = cold('(b|)', {
b: true
b: true,
});
expect(service.isSectionAvailable(submissionId, sectionId)).toBeObservable(expected);
@@ -311,7 +323,7 @@ describe('SectionsService test suite', () => {
store.select.and.returnValue(observableOf(submissionState));
const expected = cold('(b|)', {
b: false
b: false,
});
expect(service.isSectionAvailable(submissionId, 'test')).toBeObservable(expected);
@@ -323,7 +335,7 @@ describe('SectionsService test suite', () => {
store.select.and.returnValue(observableOf(submissionState));
const expected = cold('(b|)', {
b: true
b: true,
});
expect(service.isSectionTypeAvailable(submissionId, SectionsType.Upload)).toBeObservable(expected);
@@ -333,7 +345,7 @@ describe('SectionsService test suite', () => {
store.select.and.returnValue(observableOf(submissionStateWithoutUpload));
const expected = cold('(b|)', {
b: false
b: false,
});
expect(service.isSectionAvailable(submissionId, SectionsType.Upload)).toBeObservable(expected);
@@ -345,7 +357,7 @@ describe('SectionsService test suite', () => {
store.select.and.returnValue(observableOf(submissionState));
const expected = cold('(b|)', {
b: true
b: true,
});
expect(service.isSectionType(submissionId, 'upload', SectionsType.Upload)).toBeObservable(expected);
@@ -355,7 +367,7 @@ describe('SectionsService test suite', () => {
store.select.and.returnValue(observableOf(submissionState));
const expected = cold('(b|)', {
b: false
b: false,
});
expect(service.isSectionType(submissionId, sectionId, SectionsType.Upload)).toBeObservable(expected);
@@ -365,7 +377,7 @@ describe('SectionsService test suite', () => {
store.select.and.returnValue(observableOf(submissionState));
const expected = cold('(b|)', {
b: false
b: false,
});
expect(service.isSectionType(submissionId, 'no-such-id', SectionsType.Upload)).toBeObservable(expected);
@@ -396,7 +408,7 @@ describe('SectionsService test suite', () => {
const error: SubmissionSectionError = {
path: 'test',
message: 'message test'
message: 'message test',
};
service.setSectionError(submissionId, sectionId, error);
@@ -446,10 +458,10 @@ describe('SectionsService test suite', () => {
rows: [{
fields: [{
selectableMetadata: [{
metadata: 'dc.contributor.author'
}]
}]
}]
metadata: 'dc.contributor.author',
}],
}],
}],
};
const expectedConfiguredMetadata = [ 'dc.contributor.author' ];

View File

@@ -1,16 +1,41 @@
import { Injectable } from '@angular/core';
import { combineLatest, Observable } from 'rxjs';
import { distinctUntilChanged, filter, map, mergeMap, take } from 'rxjs/operators';
import { parseReviver } from '@ng-dynamic-forms/core';
import { Store } from '@ngrx/store';
import { TranslateService } from '@ngx-translate/core';
import { ScrollToConfigOptions, ScrollToService } from '@nicky-lenaers/ngx-scroll-to';
import {
ScrollToConfigOptions,
ScrollToService,
} from '@nicky-lenaers/ngx-scroll-to';
import findIndex from 'lodash/findIndex';
import findKey from 'lodash/findKey';
import isEqual from 'lodash/isEqual';
import {
combineLatest,
Observable,
} from 'rxjs';
import {
distinctUntilChanged,
filter,
map,
mergeMap,
take,
} from 'rxjs/operators';
import { SubmissionState } from '../submission.reducers';
import { hasValue, isEmpty, isNotEmpty, isNotUndefined } from '../../shared/empty.util';
import { SubmissionFormsModel } from '../../core/config/models/config-submission-forms.model';
import { JsonPatchOperationPathCombiner } from '../../core/json-patch/builder/json-patch-operation-path-combiner';
import { WorkspaceitemSectionDataType } from '../../core/submission/models/workspaceitem-sections.model';
import { normalizeSectionData } from '../../core/submission/submission-response-parsing.service';
import { SubmissionScopeType } from '../../core/submission/submission-scope-type';
import {
hasValue,
isEmpty,
isNotEmpty,
isNotUndefined,
} from '../../shared/empty.util';
import { FormClearErrorsAction } from '../../shared/form/form.actions';
import { FormError } from '../../shared/form/form.reducer';
import { FormService } from '../../shared/form/form.service';
import { NotificationsService } from '../../shared/notifications/notifications.service';
import {
DisableSectionAction,
EnableSectionAction,
@@ -18,33 +43,22 @@ import {
RemoveSectionErrorsAction,
SectionStatusChangeAction,
SetSectionFormId,
UpdateSectionDataAction
UpdateSectionDataAction,
} from '../objects/submission-objects.actions';
import {
SubmissionObjectEntry
} from '../objects/submission-objects.reducer';
import { SubmissionObjectEntry } from '../objects/submission-objects.reducer';
import { SubmissionSectionError } from '../objects/submission-section-error.model';
import { SubmissionSectionObject } from '../objects/submission-section-object.model';
import {
submissionObjectFromIdSelector,
submissionSectionDataFromIdSelector,
submissionSectionErrorsFromIdSelector,
submissionSectionFromIdSelector,
submissionSectionServerErrorsFromIdSelector
submissionSectionServerErrorsFromIdSelector,
} from '../selectors';
import { SubmissionScopeType } from '../../core/submission/submission-scope-type';
import parseSectionErrorPaths, { SectionErrorPath } from '../utils/parseSectionErrorPaths';
import { FormClearErrorsAction } from '../../shared/form/form.actions';
import { NotificationsService } from '../../shared/notifications/notifications.service';
import { SubmissionState } from '../submission.reducers';
import { SubmissionService } from '../submission.service';
import { WorkspaceitemSectionDataType } from '../../core/submission/models/workspaceitem-sections.model';
import parseSectionErrorPaths, { SectionErrorPath } from '../utils/parseSectionErrorPaths';
import { SectionsType } from './sections-type';
import { normalizeSectionData } from '../../core/submission/submission-response-parsing.service';
import { SubmissionFormsModel } from '../../core/config/models/config-submission-forms.model';
import { parseReviver } from '@ng-dynamic-forms/core';
import { FormService } from '../../shared/form/form.service';
import { JsonPatchOperationPathCombiner } from '../../core/json-patch/builder/json-patch-operation-path-combiner';
import { FormError } from '../../shared/form/form.reducer';
import { SubmissionSectionObject } from '../objects/submission-section-object.model';
import { SubmissionSectionError } from '../objects/submission-section-error.model';
/**
* A service that provides methods used in submission process.
@@ -197,12 +211,12 @@ export class SectionsService {
const sectionErrors = formErrors
.map((error) => ({
path: pathCombiner.getPath(error.fieldId.replace(/\_/g, '.')).path,
message: error.message
message: error.message,
} as SubmissionSectionError))
.filter((sectionError: SubmissionSectionError) => findIndex(state.errorsToShow, { path: sectionError.path }) === -1);
return [...state.errorsToShow, ...sectionErrors];
})
))
}),
)),
);
}
@@ -257,13 +271,13 @@ export class SectionsService {
map((sectionState: SubmissionSectionObject) => {
if (hasValue(sectionState.data) && sectionType === SectionsType.SubmissionForm) {
return Object.assign({}, sectionState, {
data: normalizeSectionData(sectionState.data)
data: normalizeSectionData(sectionState.data),
});
} else {
return sectionState;
}
}),
distinctUntilChanged()
distinctUntilChanged(),
);
}
@@ -336,7 +350,7 @@ export class SectionsService {
return isNotEmpty(sectionObj.visibility)
&& ((sectionObj.visibility.other === 'READONLY' && submissionScope !== SubmissionScopeType.WorkspaceItem)
|| (sectionObj.visibility.main === 'READONLY' && submissionScope === SubmissionScopeType.WorkspaceItem)
);
);
}),
distinctUntilChanged());
}
@@ -407,7 +421,7 @@ export class SectionsService {
this.store.dispatch(new EnableSectionAction(submissionId, sectionId));
const config: ScrollToConfigOptions = {
target: sectionId,
offset: -70
offset: -70,
};
this.scrollToService.scrollTo(config);
@@ -449,7 +463,7 @@ export class SectionsService {
data: WorkspaceitemSectionDataType,
errorsToShow: SubmissionSectionError[] = [],
serverValidationErrors: SubmissionSectionError[] = [],
metadata?: string[]
metadata?: string[],
) {
if (isNotEmpty(data)) {
const isAvailable$ = this.isSectionAvailable(submissionId, sectionId);

View File

@@ -1,13 +1,18 @@
import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap';
import { TranslateLoaderMock } from '../../../../shared/mocks/translate-loader.mock';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ContentAccordionComponent } from './content-accordion.component';
import { DebugElement } from '@angular/core';
import {
ComponentFixture,
TestBed,
} from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap';
import {
TranslateLoader,
TranslateModule,
} from '@ngx-translate/core';
import { SherpaDataResponse } from '../../../../shared/mocks/section-sherpa-policies.service.mock';
import { TranslateLoaderMock } from '../../../../shared/mocks/translate-loader.mock';
import { ContentAccordionComponent } from './content-accordion.component';
describe('ContentAccordionComponent', () => {
let component: ContentAccordionComponent;
@@ -20,12 +25,12 @@ describe('ContentAccordionComponent', () => {
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: TranslateLoaderMock
}
useClass: TranslateLoaderMock,
},
}),
NgbCollapseModule,
ContentAccordionComponent
]
],
})
.compileComponents();
});

View File

@@ -1,4 +1,7 @@
import { Component, Input } from '@angular/core';
import {
Component,
Input,
} from '@angular/core';
import { PermittedVersions } from '../../../../core/submission/models/sherpa-policies-details.model';
import { NgForOf, NgIf, TitleCasePipe } from '@angular/common';

View File

@@ -1,12 +1,17 @@
import { TranslateLoaderMock } from '../../../../shared/testing/translate-loader.mock';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MetadataInformationComponent } from './metadata-information.component';
import { DebugElement } from '@angular/core';
import {
ComponentFixture,
TestBed,
} from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import {
TranslateLoader,
TranslateModule,
} from '@ngx-translate/core';
import { SherpaDataResponse } from '../../../../shared/mocks/section-sherpa-policies.service.mock';
import { TranslateLoaderMock } from '../../../../shared/testing/translate-loader.mock';
import { MetadataInformationComponent } from './metadata-information.component';
describe('MetadataInformationComponent', () => {
let component: MetadataInformationComponent;
@@ -19,11 +24,11 @@ describe('MetadataInformationComponent', () => {
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: TranslateLoaderMock
}
useClass: TranslateLoaderMock,
},
}),
MetadataInformationComponent
]
],
})
.compileComponents();
});

View File

@@ -1,4 +1,7 @@
import { Component, Input } from '@angular/core';
import {
Component,
Input,
} from '@angular/core';
import { Metadata } from '../../../../core/submission/models/sherpa-policies-details.model';
import { DatePipe, NgIf } from '@angular/common';

View File

@@ -1,11 +1,11 @@
import { TranslateLoaderMock } from '../../../../shared/testing/translate-loader.mock';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PublicationInformationComponent } from './publication-information.component';
import { DebugElement } from '@angular/core';
import { ComponentFixture, TestBed, } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateLoader, TranslateModule, } from '@ngx-translate/core';
import { SherpaDataResponse } from '../../../../shared/mocks/section-sherpa-policies.service.mock';
import { TranslateLoaderMock } from '../../../../shared/testing/translate-loader.mock';
import { PublicationInformationComponent } from './publication-information.component';
describe('PublicationInformationComponent', () => {
let component: PublicationInformationComponent;
@@ -19,11 +19,11 @@ describe('PublicationInformationComponent', () => {
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: TranslateLoaderMock
}
useClass: TranslateLoaderMock,
},
}),
PublicationInformationComponent
]
],
})
.compileComponents();
});

View File

@@ -1,4 +1,4 @@
import { Component, Input } from '@angular/core';
import { Component, Input, } from '@angular/core';
import { Journal } from '../../../../core/submission/models/sherpa-policies-details.model';
import { NgForOf, NgIf } from '@angular/common';

View File

@@ -1,12 +1,12 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PublisherPolicyComponent } from './publisher-policy.component';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { ComponentFixture, TestBed, } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { TranslateLoader, TranslateModule, } from '@ngx-translate/core';
import { SherpaDataResponse } from '../../../../shared/mocks/section-sherpa-policies.service.mock';
import { TranslateLoaderMock } from '../../../../shared/mocks/translate-loader.mock';
import { ContentAccordionComponent } from '../content-accordion/content-accordion.component';
import { PublisherPolicyComponent } from './publisher-policy.component';
describe('PublisherPolicyComponent', () => {
let component: PublisherPolicyComponent;
@@ -19,8 +19,8 @@ describe('PublisherPolicyComponent', () => {
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: TranslateLoaderMock
}
useClass: TranslateLoaderMock,
},
}),
PublisherPolicyComponent,
]

View File

@@ -1,4 +1,4 @@
import { Component, Input } from '@angular/core';
import { Component, Input, } from '@angular/core';
import { Policy } from '../../../../core/submission/models/sherpa-policies-details.model';
import { AlertType } from '../../../../shared/alert/alert-type';

View File

@@ -1,22 +1,21 @@
import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service.stub';
import { SherpaDataResponse } from '../../../shared/mocks/section-sherpa-policies.service.mock';
import { ComponentFixture, inject, TestBed } from '@angular/core/testing';
import { SectionsService } from '../sections.service';
import { SectionsServiceStub } from '../../../shared/testing/sections-service.stub';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { BrowserModule, By } from '@angular/platform-browser';
import { Store } from '@ngrx/store';
import { AppState } from '../../../app.reducer';
import { SubmissionSectionSherpaPoliciesComponent } from './section-sherpa-policies.component';
import { SubmissionService } from '../../submission.service';
import { DebugElement } from '@angular/core';
import { TranslateLoaderMock } from '../../../shared/mocks/translate-loader.mock';
import { of as observableOf } from 'rxjs';
import { ComponentFixture, inject, TestBed, } from '@angular/core/testing';
import { BrowserModule, By, } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { Store } from '@ngrx/store';
import { TranslateLoader, TranslateModule, } from '@ngx-translate/core';
import { of as observableOf } from 'rxjs';
import { AppState } from '../../../app.reducer';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { SherpaDataResponse } from '../../../shared/mocks/section-sherpa-policies.service.mock';
import { TranslateLoaderMock } from '../../../shared/mocks/translate-loader.mock';
import { SectionsServiceStub } from '../../../shared/testing/sections-service.stub';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service.stub';
import { SubmissionService } from '../../submission.service';
import { SectionsService } from '../sections.service';
import { SubmissionSectionSherpaPoliciesComponent } from './section-sherpa-policies.component';
import { MetadataInformationComponent } from './metadata-information/metadata-information.component';
import { AlertComponent } from '../../../shared/alert/alert.component';
import { PublisherPolicyComponent } from './publisher-policy/publisher-policy.component';
@@ -49,7 +48,7 @@ describe('SubmissionSectionSherpaPoliciesComponent', () => {
errorsToShow: [],
serverValidationErrors: [],
isLoading: false,
isValid: true
isValid: true,
};
describe('SubmissionSectionSherpaPoliciesComponent', () => {
@@ -62,8 +61,8 @@ describe('SubmissionSectionSherpaPoliciesComponent', () => {
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: TranslateLoaderMock
}
useClass: TranslateLoaderMock,
},
}),
NgbCollapseModule,
SubmissionSectionSherpaPoliciesComponent

View File

@@ -1,18 +1,16 @@
import { AlertType } from '../../../shared/alert/alert-type';
import { Component, Inject } from '@angular/core';
import { BehaviorSubject, Observable, of, Subscription } from 'rxjs';
import { Component, Inject, } from '@angular/core';
import { BehaviorSubject, Observable, of, Subscription, } from 'rxjs';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import {
WorkspaceitemSectionSherpaPoliciesObject
} from '../../../core/submission/models/workspaceitem-section-sherpa-policies.model';
import { AlertType } from '../../../shared/alert/alert-type';
import { SubmissionService } from '../../submission.service';
import { SectionModelComponent } from '../models/section.model';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsService } from '../sections.service';
import { SectionModelComponent } from '../models/section.model';
import { SubmissionService } from '../../submission.service';
import { hasValue, isEmpty } from '../../../shared/empty.util';
import { MetadataInformationComponent } from './metadata-information/metadata-information.component';
import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap';
import { AlertComponent } from '../../../shared/alert/alert.component';
@@ -21,6 +19,7 @@ import { PublisherPolicyComponent } from './publisher-policy/publisher-policy.co
import { AsyncPipe, NgForOf, NgIf } from '@angular/common';
import { PublicationInformationComponent } from './publication-information/publication-information.component';
import { VarDirective } from '../../../shared/utils/var.directive';
import { hasValue, isEmpty } from '../../../shared/empty.util';
/**
* This component represents a section for the sherpa policy informations structure.
@@ -113,7 +112,7 @@ export class SubmissionSectionSherpaPoliciesComponent extends SectionModelCompon
this.sectionService.getSectionData(this.submissionId, this.sectionData.id, this.sectionData.sectionType)
.subscribe((sherpaPolicies: WorkspaceitemSectionSherpaPoliciesObject) => {
this.sherpaPoliciesData$.next(sherpaPolicies);
})
}),
);
}

View File

@@ -1,8 +1,8 @@
<ng-container *ngFor="let accessCondition of accessConditionsList">
<span *ngIf="accessCondition.action == 'DEFAULT_BITSTREAM_READ'" class="badge badge-primary mt-3 mr-2">
<span *ngIf="accessCondition.action === 'DEFAULT_BITSTREAM_READ'" class="badge badge-primary mt-3 mr-2">
{{accessCondition.name}} {{accessCondition.startDate}} {{accessCondition.endDate}}
</span>
<span *ngIf="accessCondition.name == 'lease'" class="badge badge-primary mt-3 mr-2">{{accessCondition.name}} from {{accessCondition.endDate}}</span>
<span *ngIf="accessCondition.name == 'embargo'" class="badge badge-dark mt-3 mr-2">{{accessCondition.name}} until {{accessCondition.startDate}}</span>
<span *ngIf="accessCondition.name === 'lease'" class="badge badge-primary mt-3 mr-2">{{accessCondition.name}} from {{accessCondition.endDate}}</span>
<span *ngIf="accessCondition.name === 'embargo'" class="badge badge-dark mt-3 mr-2">{{accessCondition.name}} until {{accessCondition.startDate}}</span>
<br>
</ng-container>

View File

@@ -1,13 +1,12 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit, } from '@angular/core';
import { find } from 'rxjs/operators';
import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service';
import { RemoteData } from '../../../../core/data/remote-data';
import { GroupDataService } from '../../../../core/eperson/group-data.service';
import { Group } from '../../../../core/eperson/models/group.model';
import { ResourcePolicy } from '../../../../core/resource-policy/models/resource-policy.model';
import { isEmpty } from '../../../../shared/empty.util';
import { Group } from '../../../../core/eperson/models/group.model';
import { RemoteData } from '../../../../core/data/remote-data';
import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service';
import { NgForOf, NgIf } from '@angular/common';
/**

View File

@@ -2,17 +2,38 @@ import { ChangeDetectorRef, Component, NO_ERRORS_SCHEMA } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { FormsModule, ReactiveFormsModule, } from '@angular/forms';
import { NgbActiveModal, NgbModal, } from '@ng-bootstrap/ng-bootstrap';
import {
DynamicFormArrayModel,
DynamicFormControlEvent,
DynamicFormGroupModel,
DynamicSelectModel
DynamicSelectModel,
} from '@ng-dynamic-forms/core';
import { of } from 'rxjs';
import {
JsonPatchOperationPathCombiner
} from '../../../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { JsonPatchOperationsBuilder } from '../../../../../core/json-patch/builder/json-patch-operations-builder';
import {
SubmissionJsonPatchOperationsService
} from '../../../../../core/submission/submission-json-patch-operations.service';
import { dateToISOFormat } from '../../../../../shared/date.util';
import {
DynamicCustomSwitchModel
} from '../../../../../shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.model';
import { FormBuilderService } from '../../../../../shared/form/builder/form-builder.service';
import { SubmissionServiceStub } from '../../../../../shared/testing/submission-service.stub';
import { SubmissionService } from '../../../../submission.service';
import { SubmissionSectionUploadFileEditComponent } from './section-upload-file-edit.component';
import {
FormFieldMetadataValueObject
} from '../../../../../shared/form/builder/models/form-field-metadata-value.model';
import { FormComponent } from '../../../../../shared/form/form.component';
import { FormService } from '../../../../../shared/form/form.service';
import { getMockFormService } from '../../../../../shared/mocks/form-service.mock';
import { getMockSectionUploadService } from '../../../../../shared/mocks/section-upload.service.mock';
import {
mockFileFormData,
mockSubmissionCollectionId,
@@ -22,29 +43,11 @@ import {
mockUploadConfigResponseMetadata,
mockUploadFiles,
} from '../../../../../shared/mocks/submission.mock';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { FormComponent } from '../../../../../shared/form/form.component';
import { FormService } from '../../../../../shared/form/form.service';
import { getMockFormService } from '../../../../../shared/mocks/form-service.mock';
import { createTestComponent } from '../../../../../shared/testing/utils.test';
import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { JsonPatchOperationsBuilder } from '../../../../../core/json-patch/builder/json-patch-operations-builder';
import {
SubmissionJsonPatchOperationsServiceStub
} from '../../../../../shared/testing/submission-json-patch-operations-service.stub';
import {
SubmissionJsonPatchOperationsService
} from '../../../../../core/submission/submission-json-patch-operations.service';
import { createTestComponent } from '../../../../../shared/testing/utils.test';
import { SectionUploadService } from '../../section-upload.service';
import { getMockSectionUploadService } from '../../../../../shared/mocks/section-upload.service.mock';
import {
FormFieldMetadataValueObject
} from '../../../../../shared/form/builder/models/form-field-metadata-value.model';
import {
JsonPatchOperationPathCombiner
} from '../../../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { dateToISOFormat } from '../../../../../shared/date.util';
import { of } from 'rxjs';
import { provideMockStore } from '@ngrx/store/testing';
import {
DsDynamicTypeBindRelationService
@@ -61,7 +64,6 @@ function getMockDsDynamicTypeBindRelationService(): DsDynamicTypeBindRelationSer
subscribeRelations: jasmine.createSpy('subscribeRelations')
});
}
import { DynamicCustomSwitchModel } from '../../../../../shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.model';
const jsonPatchOpBuilder: any = jasmine.createSpyObj('jsonPatchOpBuilder', {
add: jasmine.createSpy('add'),
@@ -146,7 +148,7 @@ describe('SubmissionSectionUploadFileEditComponent test suite', () => {
{ provide: APP_CONFIG, useValue: environment },
{ provide: APP_DATA_SERVICES_MAP, useValue: {} },
],
schemas: [NO_ERRORS_SCHEMA]
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents().then();
}));
@@ -216,8 +218,8 @@ describe('SubmissionSectionUploadFileEditComponent test suite', () => {
it('should init form model properly', () => {
comp.fileData = fileData;
comp.formId = 'testFileForm';
const maxStartDate = {year: 2022, month: 1, day: 12};
const maxEndDate = {year: 2019, month: 7, day: 12};
const maxStartDate = { year: 2022, month: 1, day: 12 };
const maxEndDate = { year: 2019, month: 7, day: 12 };
comp.formModel = compAsAny.buildFileEditForm();
@@ -242,8 +244,8 @@ describe('SubmissionSectionUploadFileEditComponent test suite', () => {
context: null,
control: null,
group: null,
model: {id: 'name'} as any,
type: 'change'
model: { id: 'name' } as any,
type: 'change',
};
spyOn(comp, 'setOptions');
@@ -290,7 +292,7 @@ describe('SubmissionSectionUploadFileEditComponent test suite', () => {
});
it('should save Bitstream File data properly when form is valid', fakeAsync(() => {
compAsAny.formRef = {formGroup: null};
compAsAny.formRef = { formGroup: null };
compAsAny.fileData = fileData;
compAsAny.pathCombiner = pathCombiner;
compAsAny.isPrimary = null;
@@ -303,10 +305,10 @@ describe('SubmissionSectionUploadFileEditComponent test suite', () => {
sections: {
upload: {
primary: true,
files: mockUploadFiles
}
}
})
files: mockUploadFiles,
},
},
}),
];
operationsService.jsonPatchByResourceID.and.returnValue(of(response));
@@ -327,21 +329,21 @@ describe('SubmissionSectionUploadFileEditComponent test suite', () => {
expect(operationsBuilder.add).toHaveBeenCalledWith(
pathCombiner.getPath([...pathFragment, path]),
mockFileFormData.metadata['dc.title'],
true
true,
);
path = 'metadata/dc.description';
expect(operationsBuilder.add).toHaveBeenCalledWith(
pathCombiner.getPath([...pathFragment, path]),
mockFileFormData.metadata['dc.description'],
true
true,
);
path = 'accessConditions';
expect(operationsBuilder.add).toHaveBeenCalledWith(
pathCombiner.getPath([...pathFragment, path]),
accessConditionsToSave,
true
true,
);
expect(uploadService.updateFileData).toHaveBeenCalledWith(submissionId, sectionId, mockUploadFiles[0].uuid, mockUploadFiles[0]);
@@ -349,7 +351,7 @@ describe('SubmissionSectionUploadFileEditComponent test suite', () => {
}));
it('should update Bitstream data properly when access options are omitted', fakeAsync(() => {
compAsAny.formRef = {formGroup: null};
compAsAny.formRef = { formGroup: null };
compAsAny.fileData = fileData;
compAsAny.pathCombiner = pathCombiner;
formService.validateAllFormFields.and.callFake(() => null);
@@ -359,10 +361,10 @@ describe('SubmissionSectionUploadFileEditComponent test suite', () => {
Object.assign(mockSubmissionObject, {
sections: {
upload: {
files: mockUploadFiles
}
}
})
files: mockUploadFiles,
},
},
}),
];
operationsService.jsonPatchByResourceID.and.returnValue(of(response));
comp.saveBitstreamData();
@@ -371,7 +373,7 @@ describe('SubmissionSectionUploadFileEditComponent test suite', () => {
}));
it('should not save Bitstream File data properly when form is not valid', fakeAsync(() => {
compAsAny.formRef = {formGroup: null};
compAsAny.formRef = { formGroup: null };
compAsAny.pathCombiner = pathCombiner;
formService.validateAllFormFields.and.callFake(() => null);
formService.isValid.and.returnValue(of(false));

View File

@@ -1,6 +1,6 @@
import { ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild, } from '@angular/core';
import { UntypedFormControl } from '@angular/forms';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import {
DYNAMIC_FORM_CONTROL_TYPE_DATEPICKER,
DynamicDatePickerModel,
@@ -10,13 +10,40 @@ import {
DynamicFormGroupModel,
DynamicSelectModel,
MATCH_ENABLED,
OR_OPERATOR
OR_OPERATOR,
} from '@ng-dynamic-forms/core';
import { DynamicDateControlValue } from '@ng-dynamic-forms/core/lib/model/dynamic-date-control.model';
import { DynamicFormControlCondition } from '@ng-dynamic-forms/core/lib/model/misc/dynamic-form-control-relation.model';
import { Subscription } from 'rxjs';
import { filter, mergeMap, take, } from 'rxjs/operators';
import {
DynamicCustomSwitchModel
} from 'src/app/shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.model';
import { AccessConditionOption } from '../../../../../core/config/models/config-access-condition-option.model';
import { SubmissionFormsModel } from '../../../../../core/config/models/config-submission-forms.model';
import {
JsonPatchOperationPathCombiner
} from '../../../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { JsonPatchOperationsBuilder } from '../../../../../core/json-patch/builder/json-patch-operations-builder';
import { SubmissionObject } from '../../../../../core/submission/models/submission-object.model';
import {
WorkspaceitemSectionUploadObject
} from '../../../../../core/submission/models/workspaceitem-section-upload.model';
import {
WorkspaceitemSectionUploadFileObject
} from '../../../../../core/submission/models/workspaceitem-section-upload-file.model';
import {
SubmissionJsonPatchOperationsService
} from '../../../../../core/submission/submission-json-patch-operations.service';
import { dateToISOFormat } from '../../../../../shared/date.util';
import { hasNoValue, hasValue, isNotEmpty, isNotNull, } from '../../../../../shared/empty.util';
import { FormBuilderService } from '../../../../../shared/form/builder/form-builder.service';
import { FormFieldModel } from '../../../../../shared/form/builder/models/form-field.model';
import { FormComponent } from '../../../../../shared/form/form.component';
import { FormService } from '../../../../../shared/form/form.service';
import { SubmissionService } from '../../../../submission.service';
import { SectionUploadService } from '../../section-upload.service';
import {
BITSTREAM_ACCESS_CONDITION_GROUP_CONFIG,
BITSTREAM_ACCESS_CONDITION_GROUP_LAYOUT,
@@ -31,35 +58,11 @@ import {
BITSTREAM_FORM_PRIMARY,
BITSTREAM_FORM_PRIMARY_LAYOUT,
BITSTREAM_METADATA_FORM_GROUP_CONFIG,
BITSTREAM_METADATA_FORM_GROUP_LAYOUT
BITSTREAM_METADATA_FORM_GROUP_LAYOUT,
} from './section-upload-file-edit.model';
import { hasNoValue, hasValue, isNotEmpty, isNotNull } from '../../../../../shared/empty.util';
import { SubmissionFormsModel } from '../../../../../core/config/models/config-submission-forms.model';
import { FormFieldModel } from '../../../../../shared/form/builder/models/form-field.model';
import { AccessConditionOption } from '../../../../../core/config/models/config-access-condition-option.model';
import { SubmissionService } from '../../../../submission.service';
import { FormService } from '../../../../../shared/form/form.service';
import { FormComponent } from '../../../../../shared/form/form.component';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { filter, mergeMap, take } from 'rxjs/operators';
import { dateToISOFormat } from '../../../../../shared/date.util';
import { JsonPatchOperationsBuilder } from '../../../../../core/json-patch/builder/json-patch-operations-builder';
import {
SubmissionJsonPatchOperationsService
} from '../../../../../core/submission/submission-json-patch-operations.service';
import {
JsonPatchOperationPathCombiner
} from '../../../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { SectionUploadService } from '../../section-upload.service';
import { Subscription } from 'rxjs';
import { DynamicFormControlCondition } from '@ng-dynamic-forms/core/lib/model/misc/dynamic-form-control-relation.model';
import { DynamicDateControlValue } from '@ng-dynamic-forms/core/lib/model/dynamic-date-control.model';
import { NgIf } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { POLICY_DEFAULT_WITH_LIST } from '../../section-upload-constants';
import { DynamicCustomSwitchModel } from 'src/app/shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.model';
import { SubmissionObject } from 'src/app/core/submission/models/submission-object.model';
import { WorkspaceitemSectionUploadObject } from 'src/app/core/submission/models/workspaceitem-section-upload.model';
@@ -78,7 +81,7 @@ import { WorkspaceitemSectionUploadObject } from 'src/app/core/submission/models
standalone: true
})
export class SubmissionSectionUploadFileEditComponent
implements OnInit, OnDestroy {
implements OnInit, OnDestroy {
/**
* The FormComponent reference
@@ -224,7 +227,7 @@ export class SubmissionSectionUploadFileEditComponent
metadataModel.value = {
year: date.getUTCFullYear(),
month: date.getUTCMonth() + 1,
day: date.getUTCDate()
day: date.getUTCDate(),
};
} else {
metadataModel.value = accessCondition[key];
@@ -309,8 +312,8 @@ export class SubmissionSectionUploadFileEditComponent
const configForm = Object.assign({}, this.configMetadataForm, {
fields: Object.assign([], this.configMetadataForm.rows[0].fields[0], [
this.configMetadataForm.rows[0].fields[0],
configDescr
])
configDescr,
]),
});
const formModel: DynamicFormControlModel[] = [];
@@ -322,7 +325,7 @@ export class SubmissionSectionUploadFileEditComponent
configForm,
this.collectionId,
this.fileData.metadata,
this.submissionService.getSubmissionScope()
this.submissionService.getSubmissionScope(),
);
formModel.push(new DynamicFormGroupModel(metadataGroupModelConfig, BITSTREAM_METADATA_FORM_GROUP_LAYOUT));
const accessConditionTypeModelConfig = Object.assign({}, BITSTREAM_FORM_ACCESS_CONDITION_TYPE_CONFIG);
@@ -334,8 +337,8 @@ export class SubmissionSectionUploadFileEditComponent
accessConditionTypeOptions.push(
{
label: accessCondition.name,
value: accessCondition.name
}
value: accessCondition.name,
},
);
}
accessConditionTypeModelConfig.options = accessConditionTypeOptions;
@@ -354,7 +357,7 @@ export class SubmissionSectionUploadFileEditComponent
maxStartDate = {
year: min.getUTCFullYear(),
month: min.getUTCMonth() + 1,
day: min.getUTCDate()
day: min.getUTCDate(),
};
}
}
@@ -365,7 +368,7 @@ export class SubmissionSectionUploadFileEditComponent
maxEndDate = {
year: max.getUTCFullYear(),
month: max.getUTCMonth() + 1,
day: max.getUTCDate()
day: max.getUTCDate(),
};
}
}
@@ -403,7 +406,7 @@ export class SubmissionSectionUploadFileEditComponent
// Number of access conditions blocks in form
accessConditionsArrayConfig.initialCount = isNotEmpty(this.fileData.accessConditions) ? this.fileData.accessConditions.length : 1;
formModel.push(
new DynamicFormArrayModel(accessConditionsArrayConfig, BITSTREAM_ACCESS_CONDITIONS_FORM_ARRAY_LAYOUT)
new DynamicFormArrayModel(accessConditionsArrayConfig, BITSTREAM_ACCESS_CONDITIONS_FORM_ARRAY_LAYOUT),
);
}
@@ -464,7 +467,7 @@ export class SubmissionSectionUploadFileEditComponent
currentAccessCondition.name = this.retrieveValueFromField(accessCondition.name);
/* When start and end date fields are deactivated, their values may be still present in formData,
therefore it is necessary to delete them if they're not allowed by the current access condition option. */
therefore it is necessary to delete them if they're not allowed by the current access condition option. */
if (!accessConditionOpt.hasStartDate) {
delete currentAccessCondition.startDate;
} else if (accessCondition.startDate) {
@@ -502,13 +505,13 @@ export class SubmissionSectionUploadFileEditComponent
if (isNotEmpty(accessConditionsToSave)) {
this.operationsBuilder.add(this.pathCombiner.getPath([...pathFragment, 'accessConditions']), accessConditionsToSave, true);
}
// dispatch a PATCH request to save metadata
return this.operationsService.jsonPatchByResourceID(
this.submissionService.getSubmissionObjectLinkName(),
this.submissionId,
this.pathCombiner.rootElement,
this.pathCombiner.subRootElement);
})
// dispatch a PATCH request to save metadata
return this.operationsService.jsonPatchByResourceID(
this.submissionService.getSubmissionObjectLinkName(),
this.submissionId,
this.pathCombiner.rootElement,
this.pathCombiner.subRootElement);
}),
).subscribe((result: SubmissionObject[]) => {
const section = result[0].sections[this.sectionId];
if (!section) {
@@ -521,7 +524,7 @@ export class SubmissionSectionUploadFileEditComponent
Object.keys(uploadSection.files)
.filter((key) => uploadSection.files[key].uuid === this.fileId)
.forEach((key) => this.uploadService.updateFileData(
this.submissionId, this.sectionId, this.fileId, uploadSection.files[key])
this.submissionId, this.sectionId, this.fileId, uploadSection.files[key]),
);
this.isSaving = false;
this.activeModal.close();

View File

@@ -11,28 +11,28 @@ import {
export const BITSTREAM_METADATA_FORM_GROUP_CONFIG: DynamicFormGroupModelConfig = {
id: 'metadata',
group: []
group: [],
};
export const BITSTREAM_METADATA_FORM_GROUP_LAYOUT: DynamicFormControlLayout = {
element: {
container: 'form-group',
label: 'col-form-label'
label: 'col-form-label',
},
grid: {
label: 'col-sm-3'
}
label: 'col-sm-3',
},
};
export const BITSTREAM_ACCESS_CONDITION_GROUP_CONFIG: DynamicFormGroupModelConfig = {
id: 'accessConditionGroup',
group: []
group: [],
};
export const BITSTREAM_ACCESS_CONDITION_GROUP_LAYOUT: DynamicFormControlLayout = {
element: {
host: 'form-group access-condition-group col',
container: 'pl-1 pr-1',
control: 'form-row '
}
control: 'form-row ',
},
};
export const BITSTREAM_ACCESS_CONDITIONS_FORM_ARRAY_CONFIG: DynamicFormArrayModelConfig = {
@@ -42,32 +42,32 @@ export const BITSTREAM_ACCESS_CONDITIONS_FORM_ARRAY_CONFIG: DynamicFormArrayMode
export const BITSTREAM_ACCESS_CONDITIONS_FORM_ARRAY_LAYOUT: DynamicFormControlLayout = {
grid: {
group: 'form-row pt-4',
}
},
};
export const BITSTREAM_FORM_ACCESS_CONDITION_TYPE_CONFIG: DynamicSelectModelConfig<any> = {
id: 'name',
label: 'submission.sections.upload.form.access-condition-label',
hint: 'submission.sections.upload.form.access-condition-hint',
options: []
options: [],
};
export const BITSTREAM_FORM_ACCESS_CONDITION_TYPE_LAYOUT: DynamicFormControlLayout = {
element: {
host: 'col-12',
label: 'col-form-label name-label'
}
label: 'col-form-label name-label',
},
};
export const BITSTREAM_FORM_PRIMARY_LAYOUT: DynamicFormControlLayout = {
element: {
host: 'col-12',
container: 'text-right'
container: 'text-right',
},
};
export const BITSTREAM_FORM_PRIMARY: DynamicSwitchModelConfig = {
id: 'primary',
name: 'primary',
label: 'bitstream.edit.form.primaryBitstream.label'
label: 'bitstream.edit.form.primaryBitstream.label',
};
@@ -82,24 +82,24 @@ export const BITSTREAM_FORM_ACCESS_CONDITION_START_DATE_CONFIG: DynamicDatePicke
{
match: MATCH_ENABLED,
operator: OR_OPERATOR,
when: []
}
when: [],
},
],
required: true,
validators: {
required: null
required: null,
},
errorMessages: {
required: 'submission.sections.upload.form.date-required-from'
}
required: 'submission.sections.upload.form.date-required-from',
},
};
export const BITSTREAM_FORM_ACCESS_CONDITION_START_DATE_LAYOUT: DynamicFormControlLayout = {
element: {
label: 'col-form-label'
label: 'col-form-label',
},
grid: {
host: 'col-6'
}
host: 'col-6',
},
};
export const BITSTREAM_FORM_ACCESS_CONDITION_END_DATE_CONFIG: DynamicDatePickerModelConfig = {
@@ -113,22 +113,22 @@ export const BITSTREAM_FORM_ACCESS_CONDITION_END_DATE_CONFIG: DynamicDatePickerM
{
match: MATCH_ENABLED,
operator: OR_OPERATOR,
when: []
}
when: [],
},
],
required: true,
validators: {
required: null
required: null,
},
errorMessages: {
required: 'submission.sections.upload.form.date-required-until'
}
required: 'submission.sections.upload.form.date-required-until',
},
};
export const BITSTREAM_FORM_ACCESS_CONDITION_END_DATE_LAYOUT: DynamicFormControlLayout = {
element: {
label: 'col-form-label'
label: 'col-form-label',
},
grid: {
host: 'col-6'
}
host: 'col-6',
},
};

View File

@@ -3,12 +3,12 @@
<!-- Default switch -->
<div class="col-md-2 d-flex justify-content-center align-items-center" >
<div class="custom-control custom-switch">
<input
type="checkbox"
class="custom-control-input"
id="primaryBitstream{{fileIndex}}"
<input
type="checkbox"
class="custom-control-input"
id="primaryBitstream{{fileIndex}}"
[disabled]="processingSaveStatus$ | async"
[checked]="isPrimary"
[checked]="isPrimary"
(change)="togglePrimaryBitstream($event)">
<label class="custom-control-label" for="primaryBitstream{{fileIndex}}">
<span class="sr-only" *ngIf="!isPrimary">{{'submission.sections.upload.primary.make' | translate:{ fileName: fileName } }}</span>
@@ -38,7 +38,7 @@
[disabled]="(processingDelete$ | async)"
(click)="$event.preventDefault();confirmDelete(content);">
<i *ngIf="(processingDelete$ | async)" class="fas fa-circle-notch fa-spin fa-2x text-danger"></i>
<i *ngIf="!(processingDelete$ | async)" class="fa fa-trash fa-2x text-danger"></i>
<i *ngIf="(processingDelete$ | async) !== true" class="fa fa-trash fa-2x text-danger"></i>
</button>
</ng-container>
</div>

View File

@@ -4,53 +4,51 @@ import { By } from '@angular/platform-browser';
import { AsyncPipe, CommonModule } from '@angular/common';
import { of, of as observableOf } from 'rxjs';
import { NgbModal, NgbModule, } from '@ng-bootstrap/ng-bootstrap';
import { TranslateModule } from '@ngx-translate/core';
import { FormService } from '../../../../shared/form/form.service';
import { getMockFormService } from '../../../../shared/mocks/form-service.mock';
import { HALEndpointService } from '../../../../core/shared/hal-endpoint.service';
import { HALEndpointServiceStub } from '../../../../shared/testing/hal-endpoint-service.stub';
import { NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { JsonPatchOperationPathCombiner } from '../../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { JsonPatchOperationsBuilder } from '../../../../core/json-patch/builder/json-patch-operations-builder';
import {
SubmissionJsonPatchOperationsServiceStub
} from '../../../../shared/testing/submission-json-patch-operations-service.stub';
import { HALEndpointService } from '../../../../core/shared/hal-endpoint.service';
import {
SubmissionJsonPatchOperationsService
} from '../../../../core/submission/submission-json-patch-operations.service';
import { SubmissionSectionUploadFileComponent } from './section-upload-file.component';
import { SubmissionServiceStub } from '../../../../shared/testing/submission-service.stub';
import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service';
import { FormService } from '../../../../shared/form/form.service';
import { getMockFormService } from '../../../../shared/mocks/form-service.mock';
import { getMockSectionUploadService } from '../../../../shared/mocks/section-upload.service.mock';
import {
mockSubmissionCollectionId,
mockSubmissionId,
mockUploadConfigResponse,
mockUploadFiles
mockUploadFiles,
} from '../../../../shared/mocks/submission.mock';
import { SubmissionService } from '../../../submission.service';
import { SectionUploadService } from '../section-upload.service';
import { HALEndpointServiceStub } from '../../../../shared/testing/hal-endpoint-service.stub';
import {
SubmissionJsonPatchOperationsServiceStub
} from '../../../../shared/testing/submission-json-patch-operations-service.stub';
import { SubmissionServiceStub } from '../../../../shared/testing/submission-service.stub';
import { createTestComponent } from '../../../../shared/testing/utils.test';
import { FileSizePipe } from '../../../../shared/utils/file-size-pipe';
import { JsonPatchOperationPathCombiner } from '../../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { getMockSectionUploadService } from '../../../../shared/mocks/section-upload.service.mock';
import { SubmissionService } from '../../../submission.service';
import { SectionUploadService } from '../section-upload.service';
import { SubmissionSectionUploadFileEditComponent } from './edit/section-upload-file-edit.component';
import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service';
import { SubmissionSectionUploadFileComponent } from './section-upload-file.component';
import { SubmissionSectionUploadFileViewComponent } from './view/section-upload-file-view.component';
import { ThemeService } from '../../../../shared/theme-support/theme.service';
import { getMockThemeService } from '../../../../shared/mocks/theme-service.mock';
import { POLICY_DEFAULT_WITH_LIST } from '../section-upload-constants';
import { APP_DATA_SERVICES_MAP } from '../../../../../config/app-config.interface';
const configMetadataFormMock = {
rows: [{
fields: [{
selectableMetadata: [
{metadata: 'dc.title', label: null, closed: false},
{metadata: 'dc.description', label: null, closed: false}
]
}]
}]
{ metadata: 'dc.title', label: null, closed: false },
{ metadata: 'dc.description', label: null, closed: false },
],
}],
}],
};
describe('SubmissionSectionUploadFileComponent test suite', () => {
@@ -91,7 +89,7 @@ describe('SubmissionSectionUploadFileComponent test suite', () => {
TranslateModule.forRoot(),
FileSizePipe,
SubmissionSectionUploadFileComponent,
TestComponent
TestComponent,
],
providers: [
{ provide: FormService, useValue: getMockFormService() },
@@ -106,9 +104,9 @@ describe('SubmissionSectionUploadFileComponent test suite', () => {
NgbModal,
SubmissionSectionUploadFileComponent,
SubmissionSectionUploadFileEditComponent,
FormBuilderService
FormBuilderService,
],
schemas: [NO_ERRORS_SCHEMA]
schemas: [NO_ERRORS_SCHEMA],
})
.overrideComponent(SubmissionSectionUploadFileComponent, {
remove: { imports: [
@@ -195,7 +193,7 @@ describe('SubmissionSectionUploadFileComponent test suite', () => {
expect(comp.fileData).toEqual(fileData);
});
it('should call deleteFile on delete confirmation', () => {
it('should call deleteFile on delete confirmation', async () => {
spyOn(compAsAny, 'deleteFile');
comp.fileData = fileData;
@@ -211,9 +209,8 @@ describe('SubmissionSectionUploadFileComponent test suite', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(compAsAny.deleteFile).toHaveBeenCalled();
});
await fixture.whenStable();
expect(compAsAny.deleteFile).toHaveBeenCalled();
});
it('should delete primary if file we delete is primary', () => {

View File

@@ -1,27 +1,35 @@
import {
Component,
Input,
OnChanges,
OnDestroy,
OnInit,
SimpleChanges,
ViewChild
Component,
Input,
OnChanges,
OnDestroy,
OnInit,
SimpleChanges,
ViewChild,
} from '@angular/core';
import { BehaviorSubject, Observable, Subscription } from 'rxjs';
import { filter } from 'rxjs/operators';
import { DynamicFormControlModel, } from '@ng-dynamic-forms/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { NgbModalOptions } from '@ng-bootstrap/ng-bootstrap/modal/modal-config';
import { DynamicFormControlModel } from '@ng-dynamic-forms/core';
import {
BehaviorSubject,
Observable,
Subscription,
} from 'rxjs';
import { filter } from 'rxjs/operators';
import { SectionUploadService } from '../section-upload.service';
import { hasValue, isNotUndefined } from '../../../../shared/empty.util';
import { FormService } from '../../../../shared/form/form.service';
import { JsonPatchOperationsBuilder } from '../../../../core/json-patch/builder/json-patch-operations-builder';
import { JsonPatchOperationPathCombiner } from '../../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { WorkspaceitemSectionUploadFileObject } from '../../../../core/submission/models/workspaceitem-section-upload-file.model';
import { SubmissionFormsModel } from '../../../../core/config/models/config-submission-forms.model';
import { SubmissionService } from '../../../submission.service';
import { JsonPatchOperationPathCombiner } from '../../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { JsonPatchOperationsBuilder } from '../../../../core/json-patch/builder/json-patch-operations-builder';
import { Bitstream } from '../../../../core/shared/bitstream.model';
import { WorkspaceitemSectionUploadFileObject } from '../../../../core/submission/models/workspaceitem-section-upload-file.model';
import { SubmissionJsonPatchOperationsService } from '../../../../core/submission/submission-json-patch-operations.service';
import {
hasValue,
isNotUndefined,
} from '../../../../shared/empty.util';
import { FormService } from '../../../../shared/form/form.service';
import { SubmissionService } from '../../../submission.service';
import { SectionUploadService } from '../section-upload.service';
import { SubmissionSectionUploadFileEditComponent } from './edit/section-upload-file-edit.component';
import { Bitstream } from '../../../../core/shared/bitstream.model';
import { NgbModalOptions } from '@ng-bootstrap/ng-bootstrap/modal/modal-config';
@@ -162,11 +170,11 @@ export class SubmissionSectionUploadFileComponent implements OnChanges, OnInit,
*/
protected pathCombiner: JsonPatchOperationPathCombiner;
/**
/**
* The [JsonPatchOperationPathCombiner] object
* @type {JsonPatchOperationPathCombiner}
*/
protected primaryBitstreamPathCombiner: JsonPatchOperationPathCombiner;
protected primaryBitstreamPathCombiner: JsonPatchOperationPathCombiner;
/**
* Array to track all subscriptions and unsubscribe them onDestroy
@@ -214,9 +222,9 @@ export class SubmissionSectionUploadFileComponent implements OnChanges, OnInit,
.getFileData(this.submissionId, this.sectionId, this.fileId)
.pipe(filter((bitstream) => isNotUndefined(bitstream)))
.subscribe((bitstream) => {
this.fileData = bitstream;
}
)
this.fileData = bitstream;
},
),
);
}
}
@@ -241,7 +249,7 @@ export class SubmissionSectionUploadFileComponent implements OnChanges, OnInit,
this.processingDelete$.next(true);
this.deleteFile();
}
}
},
);
}
@@ -252,7 +260,7 @@ export class SubmissionSectionUploadFileComponent implements OnChanges, OnInit,
*/
public getBitstream(): Bitstream {
return Object.assign(new Bitstream(), {
uuid: this.fileData.uuid
uuid: this.fileData.uuid,
});
}
@@ -300,7 +308,7 @@ export class SubmissionSectionUploadFileComponent implements OnChanges, OnInit,
this.formMetadata.push(metadatum.metadata);
});
});
}
},
);
}

View File

@@ -1,16 +1,20 @@
import { Component, Input } from '@angular/core';
import {
Component,
Input,
} from '@angular/core';
import { SubmissionFormsModel } from 'src/app/core/config/models/config-submission-forms.model';
import { ThemedComponent } from 'src/app/shared/theme-support/themed.component';
import { SubmissionSectionUploadFileComponent } from './section-upload-file.component';
@Component({
selector: 'ds-themed-submission-upload-section-file',
styleUrls: [],
selector: 'ds-themed-submission-upload-section-file',
styleUrls: [],
templateUrl: '../../../../shared/theme-support/themed.component.html',
standalone: true
})
export class ThemedSubmissionSectionUploadFileComponent
extends ThemedComponent<SubmissionSectionUploadFileComponent> {
extends ThemedComponent<SubmissionSectionUploadFileComponent> {
/**
* The list of available access condition
@@ -85,8 +89,8 @@ export class ThemedSubmissionSectionUploadFileComponent
'fileIndex',
'fileName',
'sectionId',
'submissionId'
];
'submissionId',
];
protected getComponentName(): string {
return 'SubmissionSectionUploadFileComponent';

View File

@@ -1,15 +1,16 @@
import { ChangeDetectionStrategy, Component, NO_ERRORS_SCHEMA } from '@angular/core';
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
import { ChangeDetectionStrategy, Component, NO_ERRORS_SCHEMA, } from '@angular/core';
import { ComponentFixture, inject, TestBed, waitForAsync, } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { mockUploadFiles } from '../../../../../shared/mocks/submission.mock';
import { FormComponent } from '../../../../../shared/form/form.component';
import { SubmissionSectionUploadFileViewComponent } from './section-upload-file-view.component';
import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe';
import { Metadata } from '../../../../../core/shared/metadata.utils';
import { FormComponent } from '../../../../../shared/form/form.component';
import { mockUploadFiles } from '../../../../../shared/mocks/submission.mock';
import { createTestComponent } from '../../../../../shared/testing/utils.test';
import { SubmissionSectionUploadAccessConditionsComponent } from '../../accessConditions/submission-section-upload-access-conditions.component';
import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe';
import { SubmissionSectionUploadFileViewComponent } from './section-upload-file-view.component';
import {
SubmissionSectionUploadAccessConditionsComponent
} from '../../accessConditions/submission-section-upload-access-conditions.component';
describe('SubmissionSectionUploadFileViewComponent test suite', () => {
@@ -26,12 +27,12 @@ describe('SubmissionSectionUploadFileViewComponent test suite', () => {
TruncatePipe,
FormComponent,
SubmissionSectionUploadFileViewComponent,
TestComponent
TestComponent,
],
providers: [
SubmissionSectionUploadFileViewComponent
SubmissionSectionUploadFileViewComponent,
],
schemas: [NO_ERRORS_SCHEMA]
schemas: [NO_ERRORS_SCHEMA],
})
.overrideComponent(SubmissionSectionUploadFileViewComponent, {
remove: {

View File

@@ -1,9 +1,11 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit, } from '@angular/core';
import { WorkspaceitemSectionUploadFileObject } from '../../../../../core/submission/models/workspaceitem-section-upload-file.model';
import { isNotEmpty } from '../../../../../shared/empty.util';
import { MetadataMap, MetadataValue, } from '../../../../../core/shared/metadata.models';
import { Metadata } from '../../../../../core/shared/metadata.utils';
import { MetadataMap, MetadataValue } from '../../../../../core/shared/metadata.models';
import {
WorkspaceitemSectionUploadFileObject
} from '../../../../../core/submission/models/workspaceitem-section-upload-file.model';
import { isNotEmpty } from '../../../../../shared/empty.util';
import {
SubmissionSectionUploadAccessConditionsComponent
} from '../../accessConditions/submission-section-upload-access-conditions.component';

View File

@@ -1,21 +1,22 @@
import { ChangeDetectorRef, Component, NO_ERRORS_SCHEMA } from '@angular/core';
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { cold } from 'jasmine-marbles';
import { of as observableOf } from 'rxjs';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
import { createTestComponent } from '../../../shared/testing/utils.test';
import { SubmissionObjectState } from '../../objects/submission-objects.reducer';
import { SubmissionService } from '../../submission.service';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service.stub';
import { SectionsService } from '../sections.service';
import { SectionsServiceStub } from '../../../shared/testing/sections-service.stub';
import { SubmissionUploadsModel } from '../../../core/config/models/config-submission-uploads.model';
import { SubmissionFormsConfigDataService } from '../../../core/config/submission-forms-config-data.service';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsType } from '../sections-type';
import { SubmissionUploadsConfigDataService } from '../../../core/config/submission-uploads-config-data.service';
import { CollectionDataService } from '../../../core/data/collection-data.service';
import { buildPaginatedList } from '../../../core/data/paginated-list.model';
import { GroupDataService } from '../../../core/eperson/group-data.service';
import { Group } from '../../../core/eperson/models/group.model';
import { ResourcePolicy } from '../../../core/resource-policy/models/resource-policy.model';
import { ResourcePolicyDataService } from '../../../core/resource-policy/resource-policy-data.service';
import { Collection } from '../../../core/shared/collection.model';
import { PageInfo } from '../../../core/shared/page-info.model';
import { getMockSectionUploadService } from '../../../shared/mocks/section-upload.service.mock';
import {
mockGroup,
mockSubmissionCollectionId,
@@ -26,19 +27,17 @@ import {
mockUploadFiles,
mockUploadFilesData,
} from '../../../shared/mocks/submission.mock';
import { SubmissionUploadsConfigDataService } from '../../../core/config/submission-uploads-config-data.service';
import { SectionUploadService } from './section-upload.service';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
import { SectionsServiceStub } from '../../../shared/testing/sections-service.stub';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service.stub';
import { createTestComponent } from '../../../shared/testing/utils.test';
import { SubmissionObjectState } from '../../objects/submission-objects.reducer';
import { SubmissionService } from '../../submission.service';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsService } from '../sections.service';
import { SectionsType } from '../sections-type';
import { SubmissionSectionUploadComponent } from './section-upload.component';
import { CollectionDataService } from '../../../core/data/collection-data.service';
import { GroupDataService } from '../../../core/eperson/group-data.service';
import { Collection } from '../../../core/shared/collection.model';
import { ResourcePolicy } from '../../../core/resource-policy/models/resource-policy.model';
import { ResourcePolicyDataService } from '../../../core/resource-policy/resource-policy-data.service';
import { Group } from '../../../core/eperson/models/group.model';
import { getMockSectionUploadService } from '../../../shared/mocks/section-upload.service.mock';
import { SubmissionUploadsModel } from '../../../core/config/models/config-submission-uploads.model';
import { buildPaginatedList } from '../../../core/data/paginated-list.model';
import { PageInfo } from '../../../core/shared/page-info.model';
import { SectionUploadService } from './section-upload.service';
import { AlertComponent } from '../../../shared/alert/alert.component';
import { ThemeService } from '../../../shared/theme-support/theme.service';
import { getMockThemeService } from '../../../shared/mocks/theme-service.mock';
@@ -50,13 +49,13 @@ function getMockSubmissionUploadsConfigService(): SubmissionFormsConfigDataServi
getConfigByHref: jasmine.createSpy('getConfigByHref'),
getConfigByName: jasmine.createSpy('getConfigByName'),
getConfigBySearch: jasmine.createSpy('getConfigBySearch'),
findByHref: jasmine.createSpy('findByHref')
findByHref: jasmine.createSpy('findByHref'),
});
}
function getMockCollectionDataService(): CollectionDataService {
return jasmine.createSpyObj('CollectionDataService', {
findById: jasmine.createSpy('findById')
findById: jasmine.createSpy('findById'),
});
}
@@ -69,7 +68,7 @@ function getMockGroupEpersonService(): GroupDataService {
function getMockResourcePolicyService(): ResourcePolicyDataService {
return jasmine.createSpyObj('ResourcePolicyService', {
findByHref: jasmine.createSpy('findByHref')
findByHref: jasmine.createSpy('findByHref'),
});
}
@@ -100,13 +99,13 @@ describe('SubmissionSectionUploadComponent test suite', () => {
config: 'https://dspace7.4science.it/or2018/api/config/submissionforms/upload',
mandatory: true,
data: {
files: []
files: [],
},
errorsToShow: [],
serverValidationErrors: [],
header: 'submit.progressbar.describe.upload',
id: 'upload-id',
sectionType: SectionsType.Upload
sectionType: SectionsType.Upload,
};
submissionId = mockSubmissionId;
collectionId = mockSubmissionCollectionId;
@@ -118,18 +117,18 @@ describe('SubmissionSectionUploadComponent test suite', () => {
{
key: 'dc.title',
language: 'en_US',
value: 'Community 1-Collection 1'
value: 'Community 1-Collection 1',
}],
_links: {
defaultAccessConditions: collectionId + '/defaultAccessConditions'
}
defaultAccessConditions: collectionId + '/defaultAccessConditions',
},
});
mockDefaultAccessCondition = Object.assign(new ResourcePolicy(), {
name: null,
groupUUID: '11cc35e5-a11d-4b64-b5b9-0052a5d15509',
id: 20,
uuid: 'resource-policy-20'
uuid: 'resource-policy-20',
});
uploadsConfigService = getMockSubmissionUploadsConfigService();
@@ -149,18 +148,18 @@ describe('SubmissionSectionUploadComponent test suite', () => {
submissionServiceStub.getSubmissionObject.and.returnValue(observableOf(submissionState));
collectionDataService.findById.and.returnValue(createSuccessfulRemoteDataObject$(Object.assign(new Collection(), mockCollection, {
defaultAccessConditions: createSuccessfulRemoteDataObject$(mockDefaultAccessCondition)
defaultAccessConditions: createSuccessfulRemoteDataObject$(mockDefaultAccessCondition),
})));
resourcePolicyService.findByHref.and.returnValue(createSuccessfulRemoteDataObject$(mockDefaultAccessCondition));
uploadsConfigService.findByHref.and.returnValue(createSuccessfulRemoteDataObject$(
buildPaginatedList(new PageInfo(), [mockUploadConfigResponse as any]))
buildPaginatedList(new PageInfo(), [mockUploadConfigResponse as any])),
);
groupService.findById.and.returnValues(
createSuccessfulRemoteDataObject$(Object.assign(new Group(), mockGroup)),
createSuccessfulRemoteDataObject$(Object.assign(new Group(), mockGroup))
createSuccessfulRemoteDataObject$(Object.assign(new Group(), mockGroup)),
);
bitstreamService.getUploadedFileList.and.returnValue(observableOf([]));
@@ -172,7 +171,7 @@ describe('SubmissionSectionUploadComponent test suite', () => {
CommonModule,
TranslateModule.forRoot(),
SubmissionSectionUploadComponent,
TestComponent
TestComponent,
],
providers: [
{ provide: CollectionDataService, useValue: collectionDataService },
@@ -187,9 +186,9 @@ describe('SubmissionSectionUploadComponent test suite', () => {
{ provide: ThemeService, useValue: getMockThemeService()},
{ provide: APP_DATA_SERVICES_MAP, useValue: {} },
ChangeDetectorRef,
SubmissionSectionUploadComponent
SubmissionSectionUploadComponent,
],
schemas: [NO_ERRORS_SCHEMA]
schemas: [NO_ERRORS_SCHEMA],
})
.overrideComponent(SubmissionSectionUploadComponent, {
remove: {
@@ -244,7 +243,7 @@ describe('SubmissionSectionUploadComponent test suite', () => {
submissionServiceStub.getSubmissionObject.and.returnValue(observableOf(submissionState));
collectionDataService.findById.and.returnValue(createSuccessfulRemoteDataObject$(Object.assign(new Collection(), mockCollection, {
defaultAccessConditions: createSuccessfulRemoteDataObject$(mockDefaultAccessCondition)
defaultAccessConditions: createSuccessfulRemoteDataObject$(mockDefaultAccessCondition),
})));
resourcePolicyService.findByHref.and.returnValue(createSuccessfulRemoteDataObject$(mockDefaultAccessCondition));
@@ -253,7 +252,7 @@ describe('SubmissionSectionUploadComponent test suite', () => {
groupService.findById.and.returnValues(
createSuccessfulRemoteDataObject$(Object.assign(new Group(), mockGroup)),
createSuccessfulRemoteDataObject$(Object.assign(new Group(), mockGroup))
createSuccessfulRemoteDataObject$(Object.assign(new Group(), mockGroup)),
);
comp.onSectionInit();
@@ -282,7 +281,7 @@ describe('SubmissionSectionUploadComponent test suite', () => {
groupService.findById.and.returnValues(
createSuccessfulRemoteDataObject$(Object.assign(new Group(), mockGroup)),
createSuccessfulRemoteDataObject$(Object.assign(new Group(), mockGroup))
createSuccessfulRemoteDataObject$(Object.assign(new Group(), mockGroup)),
);
bitstreamService.getUploadedFilesData.and.returnValue(observableOf(mockUploadFilesData));
@@ -319,21 +318,21 @@ describe('SubmissionSectionUploadComponent test suite', () => {
groupService.findById.and.returnValues(
createSuccessfulRemoteDataObject$(Object.assign(new Group(), mockGroup)),
createSuccessfulRemoteDataObject$(Object.assign(new Group(), mockGroup))
createSuccessfulRemoteDataObject$(Object.assign(new Group(), mockGroup)),
);
bitstreamService.getUploadedFileList.and.returnValue(cold('-a-b', {
a: [],
b: mockUploadFiles
b: mockUploadFiles,
}));
comp.onSectionInit();
expect(comp.required$.getValue()).toBe(true);
expect(comp.required$.getValue()).toBe(true);
expect(compAsAny.getSectionStatus()).toBeObservable(cold('-c-d', {
c: false,
d: true
d: true,
}));
});
@@ -349,12 +348,12 @@ describe('SubmissionSectionUploadComponent test suite', () => {
groupService.findById.and.returnValues(
createSuccessfulRemoteDataObject$(Object.assign(new Group(), mockGroup)),
createSuccessfulRemoteDataObject$(Object.assign(new Group(), mockGroup))
createSuccessfulRemoteDataObject$(Object.assign(new Group(), mockGroup)),
);
bitstreamService.getUploadedFileList.and.returnValue(cold('-a-b', {
a: [],
b: mockUploadFiles
b: mockUploadFiles,
}));
comp.onSectionInit();
@@ -363,7 +362,7 @@ describe('SubmissionSectionUploadComponent test suite', () => {
expect(compAsAny.getSectionStatus()).toBeObservable(cold('-c-d', {
c: true,
d: true
d: true,
}));
});
});

View File

@@ -1,31 +1,34 @@
import { ChangeDetectorRef, Component, Inject } from '@angular/core';
import { BehaviorSubject, combineLatest as observableCombineLatest, Observable, Subscription ,
combineLatest
import { ChangeDetectorRef, Component, Inject, } from '@angular/core';
import {
BehaviorSubject,
combineLatest,
combineLatest as observableCombineLatest,
Observable,
Subscription,
} from 'rxjs';
import { distinctUntilChanged, filter, map, mergeMap, switchMap, tap } from 'rxjs/operators';
import { distinctUntilChanged, filter, map, mergeMap, switchMap, tap, } from 'rxjs/operators';
import { WorkspaceitemSectionUploadObject } from 'src/app/core/submission/models/workspaceitem-section-upload.model';
import { SectionModelComponent } from '../models/section.model';
import { hasValue, isNotEmpty, isNotUndefined, isUndefined } from '../../../shared/empty.util';
import { SectionUploadService } from './section-upload.service';
import { CollectionDataService } from '../../../core/data/collection-data.service';
import { GroupDataService } from '../../../core/eperson/group-data.service';
import { ResourcePolicyDataService } from '../../../core/resource-policy/resource-policy-data.service';
import { SubmissionUploadsConfigDataService } from '../../../core/config/submission-uploads-config-data.service';
import { SubmissionUploadsModel } from '../../../core/config/models/config-submission-uploads.model';
import { SubmissionFormsModel } from '../../../core/config/models/config-submission-forms.model';
import { SectionDataObject } from '../models/section-data.model';
import { SubmissionObjectEntry } from '../../objects/submission-objects.reducer';
import { AlertType } from '../../../shared/alert/alert-type';
import { RemoteData } from '../../../core/data/remote-data';
import { Group } from '../../../core/eperson/models/group.model';
import { SectionsService } from '../sections.service';
import { SubmissionService } from '../../submission.service';
import { Collection } from '../../../core/shared/collection.model';
import { AccessConditionOption } from '../../../core/config/models/config-access-condition-option.model';
import { followLink } from '../../../shared/utils/follow-link-config.model';
import { getFirstSucceededRemoteData } from '../../../core/shared/operators';
import { DSONameService } from '../../../core/breadcrumbs/dso-name.service';
import { AccessConditionOption } from '../../../core/config/models/config-access-condition-option.model';
import { SubmissionFormsModel } from '../../../core/config/models/config-submission-forms.model';
import { SubmissionUploadsModel } from '../../../core/config/models/config-submission-uploads.model';
import { SubmissionUploadsConfigDataService } from '../../../core/config/submission-uploads-config-data.service';
import { CollectionDataService } from '../../../core/data/collection-data.service';
import { RemoteData } from '../../../core/data/remote-data';
import { GroupDataService } from '../../../core/eperson/group-data.service';
import { Group } from '../../../core/eperson/models/group.model';
import { ResourcePolicyDataService } from '../../../core/resource-policy/resource-policy-data.service';
import { Collection } from '../../../core/shared/collection.model';
import { getFirstSucceededRemoteData } from '../../../core/shared/operators';
import { AlertType } from '../../../shared/alert/alert-type';
import { hasValue, isNotEmpty, isNotUndefined, isUndefined, } from '../../../shared/empty.util';
import { followLink } from '../../../shared/utils/follow-link-config.model';
import { SubmissionObjectEntry } from '../../objects/submission-objects.reducer';
import { SubmissionService } from '../../submission.service';
import { SectionModelComponent } from '../models/section.model';
import { SectionDataObject } from '../models/section-data.model';
import { SectionsService } from '../sections.service';
import { ThemedSubmissionSectionUploadFileComponent } from './file/themed-section-upload-file.component';
import {
SubmissionSectionUploadAccessConditionsComponent
@@ -33,7 +36,7 @@ import {
import { AsyncPipe, NgForOf, NgIf } from '@angular/common';
import { AlertComponent } from '../../../shared/alert/alert.component';
import { TranslateModule } from '@ngx-translate/core';
import { WorkspaceitemSectionUploadObject } from 'src/app/core/submission/models/workspaceitem-section-upload.model';
import { SectionUploadService } from './section-upload.service';
export const POLICY_DEFAULT_NO_LIST = 1; // Banner1
export const POLICY_DEFAULT_WITH_LIST = 2; // Banner2
@@ -170,8 +173,8 @@ export class SubmissionSectionUploadComponent extends SectionModelComponent {
switchMap((config: SubmissionUploadsModel) =>
config.metadata.pipe(
getFirstSucceededRemoteData(),
map((remoteData: RemoteData<SubmissionFormsModel>) => remoteData.payload)
)
map((remoteData: RemoteData<SubmissionFormsModel>) => remoteData.payload),
),
));
this.subs.push(
@@ -183,7 +186,7 @@ export class SubmissionSectionUploadComponent extends SectionModelComponent {
filter((rd: RemoteData<Collection>) => isNotUndefined((rd.payload))),
tap((collectionRemoteData: RemoteData<Collection>) => this.collectionName = this.dsoNameService.getName(collectionRemoteData.payload)),
// TODO review this part when https://github.com/DSpace/dspace-angular/issues/575 is resolved
/* mergeMap((collectionRemoteData: RemoteData<Collection>) => {
/* mergeMap((collectionRemoteData: RemoteData<Collection>) => {
return this.resourcePolicyService.findByHref(
(collectionRemoteData.payload as any)._links.defaultAccessConditions.href
);
@@ -215,11 +218,11 @@ export class SubmissionSectionUploadComponent extends SectionModelComponent {
}),
distinctUntilChanged())
.subscribe(([configMetadataForm, { primary, files }]: [SubmissionFormsModel, WorkspaceitemSectionUploadObject]) => {
this.primaryBitstreamUUID = primary;
this.fileList = files;
this.fileNames = Array.from(files, file => this.getFileName(configMetadataForm, file));
}
)
this.primaryBitstreamUUID = primary;
this.fileList = files;
this.fileNames = Array.from(files, file => this.getFileName(configMetadataForm, file));
},
),
);
}

View File

@@ -1,9 +1,16 @@
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { TestBed, waitForAsync } from '@angular/core/testing';
import {
TestBed,
waitForAsync,
} from '@angular/core/testing';
import {
Store,
StoreModule,
} from '@ngrx/store';
import { JsonPatchOperationPathCombiner } from 'src/app/core/json-patch/builder/json-patch-operation-path-combiner';
import { JsonPatchOperationsBuilder } from 'src/app/core/json-patch/builder/json-patch-operations-builder';
import { SectionUploadService } from './section-upload.service';
import { Store, StoreModule } from '@ngrx/store';
const jsonPatchOpBuilder: any = jasmine.createSpyObj('jsonPatchOpBuilder', {
add: jasmine.createSpy('add'),
@@ -25,7 +32,7 @@ describe('SectionUploadService test suite', () => {
SectionUploadService,
{ provide: JsonPatchOperationsBuilder, useValue: jsonPatchOpBuilder },
],
schemas: [NO_ERRORS_SCHEMA]
schemas: [NO_ERRORS_SCHEMA],
});
}));
@@ -36,28 +43,28 @@ describe('SectionUploadService test suite', () => {
[
{
initialPrimary: null,
primary: true,
operationName: 'add',
expected: [primaryPath, fileId, false, true]
initialPrimary: null,
primary: true,
operationName: 'add',
expected: [primaryPath, fileId, false, true],
},
{
initialPrimary: true,
primary: false,
operationName: 'remove',
expected: [primaryPath]
initialPrimary: true,
primary: false,
operationName: 'remove',
expected: [primaryPath],
},
{
initialPrimary: false,
primary: true,
operationName: 'replace',
expected: [primaryPath, fileId, true]
}
initialPrimary: false,
primary: true,
operationName: 'replace',
expected: [primaryPath, fileId, true],
},
].forEach(({ initialPrimary, primary, operationName, expected }) => {
it(`updatePrimaryBitstreamOperation should add ${operationName} operation`, () => {
const path = pathCombiner.getPath('primary');
sectionUploadService.updatePrimaryBitstreamOperation(path, initialPrimary, primary, fileId);
expect(operationsBuilder[operationName]).toHaveBeenCalledWith(...expected);
});
const path = pathCombiner.getPath('primary');
sectionUploadService.updatePrimaryBitstreamOperation(path, initialPrimary, primary, fileId);
expect(operationsBuilder[operationName]).toHaveBeenCalledWith(...expected);
});
});
});

View File

@@ -1,22 +1,29 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { distinctUntilChanged, filter, map } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import {
distinctUntilChanged,
filter,
map,
} from 'rxjs/operators';
import { JsonPatchOperationPathObject } from 'src/app/core/json-patch/builder/json-patch-operation-path-combiner';
import { JsonPatchOperationsBuilder } from 'src/app/core/json-patch/builder/json-patch-operations-builder';
import { WorkspaceitemSectionUploadObject } from 'src/app/core/submission/models/workspaceitem-section-upload.model';
import { SubmissionState } from '../../submission.reducers';
import { WorkspaceitemSectionUploadFileObject } from '../../../core/submission/models/workspaceitem-section-upload-file.model';
import { isUndefined } from '../../../shared/empty.util';
import {
DeleteUploadedFileAction,
EditFileDataAction,
EditFilePrimaryBitstreamAction,
NewUploadedFileAction
NewUploadedFileAction,
} from '../../objects/submission-objects.actions';
import { submissionSectionDataFromIdSelector, submissionUploadedFileFromUuidSelector, submissionUploadedFilesFromIdSelector } from '../../selectors';
import { isUndefined } from '../../../shared/empty.util';
import { WorkspaceitemSectionUploadFileObject } from '../../../core/submission/models/workspaceitem-section-upload-file.model';
import { WorkspaceitemSectionUploadObject } from 'src/app/core/submission/models/workspaceitem-section-upload.model';
import { JsonPatchOperationPathObject } from 'src/app/core/json-patch/builder/json-patch-operation-path-combiner';
import { JsonPatchOperationsBuilder } from 'src/app/core/json-patch/builder/json-patch-operations-builder';
import {
submissionSectionDataFromIdSelector,
submissionUploadedFileFromUuidSelector,
submissionUploadedFilesFromIdSelector,
} from '../../selectors';
import { SubmissionState } from '../../submission.reducers';
/**
* A service that provides methods to handle submission's bitstream state.
@@ -32,7 +39,7 @@ export class SectionUploadService {
*/
constructor(private store: Store<SubmissionState>, private operationsBuilder: JsonPatchOperationsBuilder) {}
/**
/**
* Define and add an operation based on a change
*
* @param path
@@ -149,11 +156,11 @@ export class SectionUploadService {
*/
public addUploadedFile(submissionId: string, sectionId: string, fileUUID: string, data: WorkspaceitemSectionUploadFileObject) {
this.store.dispatch(
new NewUploadedFileAction(submissionId, sectionId, fileUUID, data)
new NewUploadedFileAction(submissionId, sectionId, fileUUID, data),
);
}
/**
/**
* Update primary bitstream into the state
*
* @param submissionId
@@ -163,9 +170,9 @@ export class SectionUploadService {
* @param fileUUID
* The bitstream UUID
*/
public updateFilePrimaryBitstream(submissionId: string, sectionId: string, fileUUID: string | null) {
public updateFilePrimaryBitstream(submissionId: string, sectionId: string, fileUUID: string | null) {
this.store.dispatch(
new EditFilePrimaryBitstreamAction(submissionId, sectionId, fileUUID)
new EditFilePrimaryBitstreamAction(submissionId, sectionId, fileUUID),
);
}
@@ -183,7 +190,7 @@ export class SectionUploadService {
*/
public updateFileData(submissionId: string, sectionId: string, fileUUID: string, data: WorkspaceitemSectionUploadFileObject) {
this.store.dispatch(
new EditFileDataAction(submissionId, sectionId, fileUUID, data)
new EditFileDataAction(submissionId, sectionId, fileUUID, data),
);
}
@@ -199,7 +206,7 @@ export class SectionUploadService {
*/
public removeUploadedFile(submissionId: string, sectionId: string, fileUUID: string) {
this.store.dispatch(
new DeleteUploadedFileAction(submissionId, sectionId, fileUUID)
new DeleteUploadedFileAction(submissionId, sectionId, fileUUID),
);
}
}