From 41fb94eee9a00e1a847831e249c530fc98e2718b Mon Sep 17 00:00:00 2001 From: "CITE\\dtziotzios" Date: Fri, 18 Jan 2019 19:03:45 +0200 Subject: [PATCH] ui resrtucturing --- .../108131ae-d07a-4e8c-8f75-8c8e33fe9974.xml | 1 + .../7b1bdf71-945e-40db-b8fb-1b2d313fbebe.xml | 1 + .../be3facf6-0eb9-4668-99d6-f99215ccec1b.xml | 1 + .../configurations/WebMVCConfiguration.java | 1 - .../DynamicProjectConfigurationDevelImpl.java | 2 +- .../configloaders/DevelConfigLoader.java | 2 +- .../facebook/FacebookTokenValidator.java | 2 +- .../resources/application-devel.properties | 6 +- .../application-production.properties | 28 +- .../resources/application-staging.properties | 28 +- .../src/main/resources/application.properties | 32 +- dmp-frontend/src/app/about/about.module.ts | 51 - dmp-frontend/src/app/about/about.routes.ts | 8 - .../app/about/components/about.component.html | 32 - .../app/about/components/about.component.ts | 22 - dmp-frontend/src/app/app-routing.module.ts | 153 +- dmp-frontend/src/app/app.component.scss | 11 +- dmp-frontend/src/app/app.component.ts | 20 +- dmp-frontend/src/app/app.module.ts | 132 +- .../common/date/moment-utc-date-adapter.ts | 44 + .../app/common/forms/common-forms.module.ts | 14 + .../forms/validation/custom-validator.ts | 32 + .../error-model/validation-error-model.ts | 90 + .../forms/validation/validation-context.ts | 20 + .../src/app/common/http/base-http-params.ts | 6 + .../src/app/common/http/common-http.module.ts | 54 + .../app/common/http/interceptor-context.ts | 10 + .../interceptors/auth-token.interceptor.ts | 26 + .../http/interceptors/base.interceptor.ts | 30 + .../http/interceptors/interceptor-type.ts | 9 + .../http/interceptors/json.interceptor.ts | 22 + .../http/interceptors/locale.interceptor.ts | 20 + .../progress-indication.interceptor.ts | 25 + .../request-timing.interceptor.ts | 32 + .../response-payload.interceptor.ts | 41 + .../unauthorized-response.interceptor.ts | 75 + .../app/common/material/material.module.ts | 107 + dmp-frontend/src/app/common/types/guid.ts | 66 + .../app/common/types/json/json-serializer.ts | 14 + .../types/json/serializable.ts} | 0 .../helpers/Pair.ts => common/types/pair.ts} | 0 .../src/app/common/ui/common-ui.module.ts | 18 + .../src/app/core/auth-guard.service.ts | 27 + .../common/enum/api-message-code.ts} | 0 .../src/app/core/common/enum/app-role.ts | 5 + .../src/app/core/common/enum/auth-provider.ts | 7 + .../enum/dataset-profile-combo-box-type.ts | 4 + .../enum/dataset-profile-field-view-style.ts | 8 + .../app/core/common/enum/dataset-status.ts | 5 + .../common/enum/dmp-profile-field-type.ts | 5 + .../app/core/common/enum/dmp-profile-type.ts | 3 + .../src/app/core/common/enum/dmp-status.ts | 5 + .../core/common/enum/external-dataset-type.ts | 4 + .../common/enum/project-state-type.ts} | 0 .../src/app/core/common/enum/project-type.ts | 4 + .../core/common/enum/recent-activity-type.ts | 5 + .../Status.ts => core/common/enum/status.ts} | 0 .../app/core/common/enum/validation-type.ts | 4 + .../src/app/core/core-service.module.ts | 86 + .../src/app/core/formatting.module.ts | 25 + .../admin/dataset-profile/dataset-profile.ts | 77 + .../src/app/core/model/auth/credential.ts | 4 + .../src/app/core/model/auth/login-info.ts | 7 + .../src/app/core/model/auth/principal.ts | 13 + .../src/app/core/model/base-form-model.ts | 4 + .../src/app/core/model/culture-info.ts | 5 + .../dashboard/dashboard-statistics-model.ts | 7 + .../core/model/dashboard/search-bar-item.ts | 7 + .../model/data-repository/data-repository.ts | 8 + .../core/model/data-table/column-ordering.ts | 3 + .../model/data-table/data-table-data.ts} | 0 .../model/data-table/data-table-request.ts | 14 + .../composite-field.ts | 16 + .../dataset-profile-definition.ts | 8 + .../default-value.ts | 4 + .../field-data/field-data.ts | 42 + .../dataset-profile-definition/field-group.ts | 51 + .../model/dataset-profile-definition/field.ts | 23 + .../multiplicity.ts | 7 + .../model/dataset-profile-definition/page.ts | 7 + .../model/dataset-profile-definition/rule.ts | 6 + .../dataset-profile-definition/section.ts | 13 + .../dataset-profile-definition/view-style.ts | 4 + .../app/core/model/dataset/dataset-listing.ts | 13 + .../app/core/model/dataset/dataset-profile.ts | 33 + .../app/core/model/dataset/dataset-wizard.ts | 24 + .../src/app/core/model/dataset/dataset.ts | 73 + .../model/dmp-profile/dmp-profile-field.ts | 11 + .../model/dmp-profile/dmp-profile-listing.ts | 10 + .../app/core/model/dmp-profile/dmp-profile.ts | 15 + .../model/dmp/dmp-dynamic-field-dependency.ts | 4 + .../app/core/model/dmp/dmp-dynamic-field.ts | 10 + .../src/app/core/model/dmp/dmp-listing.ts | 14 + dmp-frontend/src/app/core/model/dmp/dmp.ts | 26 + .../dmp/invitation/dmp-invitation-user.ts | 25 + .../model/dmp/invitation/dmp-invitation.ts | 17 + .../external-dataset/external-dataset.ts | 10 + .../external-sources/external-source-item.ts | 5 + .../external-sources/external-source-url.ts | 4 + .../external-sources-configuration.ts | 9 + .../help-content/active-topic-questions.ts | 0 .../model}/help-content/page-help-content.ts | 0 .../model}/help-content/page.ts | 0 .../model}/help-content/question.ts | 0 .../model}/help-content/topic.ts | 0 .../core/model/organisation/organization.ts | 8 + .../app/core/model/project/project-listing.ts | 16 + .../src/app/core/model/project/project.ts | 24 + .../src/app/core/model/registry/registry.ts | 9 + .../app/core/model/researcher/researcher.ts | 7 + .../src/app/core/model/service/service.ts | 9 + dmp-frontend/src/app/core/model/tag/tag.ts | 4 + .../src/app/core/model/user/user-listing.ts | 7 + dmp-frontend/src/app/core/model/user/user.ts | 7 + .../core/pipes/culture-info-display.pipe.ts | 11 + .../src/app/core/pipes/date-format.pipe.ts | 43 + .../app/core/pipes/date-time-format.pipe.ts | 46 + .../pipes/ng-for-limit.pipe.ts} | 0 .../src/app/core/pipes/pipe.service.ts | 10 + .../core/pipes/timezone-info-display.pipe.ts | 12 + .../src/app/core/query/base-criteria.ts | 3 + .../data-repository-criteria.ts | 5 + .../dataset-profile-criteria.ts | 5 + .../core/query/dataset/dataset-criteria.ts | 9 + .../src/app/core/query/dmp/dmp-criteria.ts | 8 + .../query/dmp/dmp-invitation-user-criteria.ts | 5 + .../core/query/dmp/dmp-profile-criteria.ts | 5 + .../explore-dataset-criteria.ts | 10 + .../external-dataset-criteria.ts | 5 + .../core/query/project/project-criteria.ts | 8 + .../core/query/registry/registry-criteria.ts | 5 + .../src/app/core/query/request-item.ts | 3 + .../query/researcher/researcher-criteria.ts | 5 + .../core/query/service/service-criteria.ts | 5 + .../src/app/core/query/tag/tag-criteria.ts | 5 + .../src/app/core/query/user/user-criteria.ts | 7 + .../app/core/services/auth/auth.service.ts | 150 + .../core/services/culture/culture-service.ts | 84 + .../services/dashboard/dashboard.service.ts | 25 + .../dataset-profile.service.ts | 44 + .../dataset-wizard/dataset-wizard.service.ts | 59 + .../core/services/dataset/dataset.service.ts | 36 + .../services/dmp/dmp-invitation.service.ts | 32 + .../core/services/dmp/dmp-profile.service.ts | 38 + .../src/app/core/services/dmp/dmp.service.ts | 80 + .../extternal-data-repository.service.ts | 19 + .../dataset/external-dataset.service.ts | 38 + .../external-sources-configuration.service.ts | 22 + .../external-sources.service.ts | 72 + .../registry/external-registry.service.ts | 18 + .../researcher/external-researcher.service.ts | 19 + .../service/external-service.service.ts | 19 + .../help-content/cached-content-item.ts | 6 + .../help-content/help-content.service.ts | 55 + .../core/services/http/base-http.service.ts | 88 + .../core/services/logging/logging-service.ts | 69 + .../notification/ui-notification-service.ts | 60 + .../progress-indication-service.ts | 37 + .../project/project-file-upload.service.ts | 21 + .../core/services/project/project.service.ts | 50 + .../services/search-bar/search-bar.service.ts | 22 + .../services/timezone/timezone-service.ts | 38 + .../app/core/services/user/user.service.ts | 45 + .../utilities/collection-utils.service.ts | 96 + .../services/utilities/enum-utils.service.ts | 83 + .../services/utilities/type-utils.service.ts | 6 + .../compositefield-form.component.html | 77 - .../compositefield-form.component.ts | 59 - .../dataset-profile.module.ts | 107 - .../dataset-profile.router.ts | 20 - ...taset-profile-admin-listing.component.html | 59 - ...dataset-profile-admin-listing.component.ts | 159 - .../field-form/field-form.component.html | 104 - .../field-form/field-form.component.ts | 56 - .../form/form.component.html | 72 - .../form/form.component.scss | 3 - .../form/form.component.ts | 156 - .../page-form/page-component.html | 9 - .../page-form/page-component.ts | 19 - .../dataset-profile-previewer.component.ts | 38 - .../rule-component/rule.component.html | 23 - .../rule-component/rule.component.ts | 17 - .../section-form/section-form.component.html | 127 - .../section-form/section-form.component.scss | 3 - .../section-form/section-form.component.ts | 66 - .../dataset-public-listing.component.html | 91 - .../dataset-public-listing.component.ts | 153 - ...itory-referenced-model-helper.component.ts | 40 - ...taset-referenced-model-helper.component.ts | 40 - ...istry-referenced-model-helper.component.ts | 40 - ...vices-referenced-model-helper.component.ts | 40 - .../dataset-wizard.component.html | 251 -- .../dataset-wizard.component.ts | 544 ---- .../src/app/datasets/dataset.module.ts | 102 - .../src/app/datasets/dataset.routes.ts | 64 - .../editor/dataset-editor.component.html | 23 - .../editor/dataset-editor.component.scss | 38 - .../editor/dataset-editor.component.ts | 117 - .../listing/dataset-listing.component.html | 97 - .../listing/dataset-listing.component.ts | 170 - .../dmp-profile-editor.component.html | 68 - .../dmp-profile-editor.component.scss | 39 - .../dmp-profile-editor.component.ts | 182 -- .../dmp-profile-listing.component.html | 44 - .../dmp-profile-listing.component.ts | 143 - .../app/dmp-profiles/dmp-profile.module.ts | 57 - .../app/dmp-profiles/dmp-profile.routes.ts | 10 - dmp-frontend/src/app/dmps/dmps.module.ts | 113 - dmp-frontend/src/app/dmps/dmps.routes.ts | 67 - .../app/dmps/editor/dmp-editor.component.html | 149 - .../app/dmps/editor/dmp-editor.component.ts | 432 --- .../dmp-finalise-dialog.component.html | 31 - .../dmp-finalise-dialog.component.ts | 105 - .../dynamic-dmp-field-resolver.component.html | 15 - .../dynamic-dmp-field-resolver.component.ts | 40 - .../dynamic-field-project.component.ts | 84 - .../dynamic-fields-project.component.ts | 33 - .../dmps/listing/dmp-listing.component.html | 91 - .../dmps/listing/dmp-listing.component.scss | 35 - .../app/dmps/listing/dmp-listing.component.ts | 204 -- .../app/dmps/wizard/dmp-wizard.component.html | 19 - .../app/dmps/wizard/dmp-wizard.component.ts | 93 - .../editor/dmp-wizard-editor.component.html | 72 - .../editor/dmp-wizard-editor.component.ts | 194 -- .../dataset-wizard-listing.component.scss | 35 - .../dataset-wizard-listing.component.ts | 81 - .../autocomplete-remote.component.ts | 59 - ...amic-field-boolean-decision.component.html | 5 - ...ynamic-field-boolean-decision.component.ts | 20 - .../dynamic-field-checkbox.html | 1 - .../dynamic-field-checkbox.ts | 20 - .../dynamic-field-dropdown.css | 3 - .../dynamic-field-dropdown.html | 6 - .../dynamic-field-dropdown.ts | 28 - .../dynamic-field-radiobox.component.css | 9 - .../dynamic-field-radiobox.component.html | 9 - .../dynamic-field-radiobox.component.ts | 21 - .../dynamic-form-field.component.css | 2 - .../dynamic-form-field.component.html | 146 - .../dynamic-form-field.component.ts | 68 - .../dynamic-form-composite-field.html | 47 - .../dynamic-form-composite-field.ts | 43 - .../dynamic-form-group.component.css | 22 - .../dynamic-form-group.component.html | 20 - .../dynamic-form-group.component.spec.ts | 25 - .../dynamic-form-group.component.ts | 41 - .../dynamic-form-section.html | 43 - .../dynamic-form-section.ts | 57 - .../src/app/form/dynamic-form.module.ts | 110 - .../dynamic-form/dynamic-form.component.html | 39 - .../dynamic-form/dynamic-form.component.ts | 135 - .../form/fields/dropdown/field-dropdown.css | 1 - .../form/fields/dropdown/field-dropdown.html | 3 - .../form/fields/dropdown/field-dropdown.ts | 9 - ...m-pending-questions-display.component.html | 4 - ...orm-pending-questions-display.component.ts | 52 - .../app/form/pagination/pagination-service.ts | 18 - .../pprogress-bar/progress-bar.component.html | 5 - .../pprogress-bar/progress-bar.component.ts | 69 - .../table-of-content-field.component.ts | 23 - .../table-of-content-fieldset.component.ts | 26 - .../table-of-content-group.component.ts | 30 - .../table-of-content-section.component.ts | 28 - .../table-of-contents.component.ts | 27 - .../src/app/homepage/homepage.component.html | 85 - .../src/app/homepage/homepage.component.scss | 59 - .../src/app/homepage/homepage.component.ts | 133 - .../auto-complete-custom-validator.ts | 13 + .../auto-complete/auto-complete-group.ts | 4 + .../auto-complete/auto-complete.module.ts | 24 + .../multiple-auto-complete-configuration.ts | 23 + .../multiple-auto-complete.component.html | 28 + .../multiple-auto-complete.component.scss | 22 + .../multiple-auto-complete.component.ts | 273 ++ .../single-auto-complete-configuration.ts | 25 + .../single-auto-complete.component.html | 24 + .../single-auto-complete.component.scss | 13 + .../single/single-auto-complete.component.ts | 219 ++ .../confirmation-dialog.component.html | 10 + .../confirmation-dialog.component.scss | 5 + .../confirmation-dialog.component.ts | 24 + .../confirmation-dialog.module.ts | 13 + .../notification/notification.component.html | 1 + .../notification/notification.component.scss | 15 + .../notification/notification.component.ts | 54 + .../notification/notification.module.ts | 26 + .../popup/popup-notification.component.html | 5 + .../popup/popup-notification.component.ts | 16 + .../snack-bar-notification.component.html | 0 .../snack-bar-notification.component.ts | 15 + .../library/url-listing/url-listing-item.ts | 6 + .../url-listing/url-listing.component.html | 0 .../url-listing/url-listing.component.ts | 26 + .../library/url-listing/url-listing.module.ts | 20 + dmp-frontend/src/app/models/BaseModel.ts | 4 - dmp-frontend/src/app/models/CompositeField.ts | 76 - .../app/models/DataField/AutocompleteData.ts | 32 - .../models/DataField/BooleanDecisionData.ts | 16 - .../src/app/models/DataField/CheckBoxData.ts | 16 - .../src/app/models/DataField/DataField.ts | 16 - .../src/app/models/DataField/FreeTextData.ts | 16 - .../src/app/models/DataField/RadioBoxData.ts | 29 - .../src/app/models/DataField/TextArea.ts | 16 - .../src/app/models/DataField/WordListData.ts | 32 - .../models/DatasetProfileDefinitionModel.ts | 40 - dmp-frontend/src/app/models/DefaultValue.ts | 24 - dmp-frontend/src/app/models/Field.ts | 101 - dmp-frontend/src/app/models/FieldGroup.ts | 55 - dmp-frontend/src/app/models/Multiplicity.ts | 23 - dmp-frontend/src/app/models/Page.ts | 30 - dmp-frontend/src/app/models/Rule.ts | 18 - dmp-frontend/src/app/models/Section.ts | 68 - dmp-frontend/src/app/models/Validation.ts | 21 - .../auto-complete/AutocompleteLookupItem.ts | 6 - .../src/app/models/common/ListingItem.ts | 20 - .../src/app/models/common/ValidationTypes.ts | 4 - .../src/app/models/criteria/BaseCriteria.ts | 6 - .../models/criteria/BaseCriteriaErrorModel.ts | 3 - .../src/app/models/criteria/RequestItem.ts | 6 - .../DataManagementPlanCriteria.ts | 8 - .../DataManagementPlanCriteriaErrorModel.ts | 5 - .../data-repository/DataRepositoryCriteria.ts | 4 - .../dataset-profile/DatasetProfileCriteria.ts | 4 - .../criteria/dataset/DatasetCriteria.ts | 9 - .../dataset/DatasetCriteriaErrorModel.ts | 5 - .../DataManagementPlanProfileCriteria.ts | 4 - ...ManagementPlanProfileCriteriaErrorModel.ts | 4 - .../ExetrnalDatasetCriteriaErrorModel.ts | 4 - .../ExternalDatasetCriteria.ts | 4 - .../invitation/UserInvitationCriteria.ts | 4 - .../criteria/project/ProjectCriteria.ts | 8 - .../project/ProjectCriteriaErrorModel.ts | 6 - .../criteria/registry/RegistryCriteria.ts | 4 - .../researchers/ResearcherCriteria.ts | 5 - .../criteria/services/ServicesCriteria.ts | 4 - .../app/models/criteria/tags/TagsCriteria.ts | 6 - .../app/models/criteria/users/UserCriteria.ts | 9 - .../criteria/users/UserCriteriaErrorModel.ts | 6 - .../dashboard/DashboardStatisticsModel.ts | 15 - .../src/app/models/dashboard/SearchBarItem.ts | 11 - .../DataManagementPlanProfile.ts | 27 - .../DataManagementPlanProfileListingModel.ts | 7 - .../DataManagementPlanProfileModel.ts | 42 - .../DataManagementProfileField.ts | 43 - .../DataManagementPlanListingModel.ts | 29 - .../DataManagementPlanModel.ts | 105 - .../data-managemnt-plans/DynamicField.ts | 38 - .../DynamicFieldDependency.ts | 21 - .../app/models/data-table/ColumnOrderings.ts | 3 - .../app/models/data-table/DataTableRequest.ts | 15 - .../dataRepositories/DataRepositoryModel.ts | 43 - .../dataset-wizard/DatasetWizardModel.ts | 60 - .../DatasetProfileModelAdmin.ts | 43 - .../datasetProfileAdmin/DefaultValue.ts | 24 - .../app/models/datasetProfileAdmin/Field.ts | 82 - .../models/datasetProfileAdmin/FieldSet.ts | 51 - .../datasetProfileAdmin/Multiplicity.ts | 23 - .../app/models/datasetProfileAdmin/Page.ts | 32 - .../app/models/datasetProfileAdmin/Rule.ts | 34 - .../app/models/datasetProfileAdmin/Section.ts | 70 - .../models/datasetProfileAdmin/ViewStyle.ts | 24 - .../models/datasetProfileAdmin/Visibility.ts | 37 - .../datasetprofile/DatasetProfileModel.ts | 32 - .../models/datasets/DatasetListingModel.ts | 35 - .../src/app/models/datasets/DatasetModel.ts | 69 - .../models/datasets/DatasetProfileModel.ts | 13 - .../app/models/datasets/DatasetWizardModel.ts | 142 - .../src/app/models/dmpUsers/DmpUsersModel.ts | 15 - .../src/app/models/error/BaseErrorModel.ts | 3 - .../external-dataset/ExternalDatasetModel.ts | 49 - .../ExternalSourcesConfiguration.ts | 9 - .../ExternalSourcesItemModel.ts | 5 - .../ExternalSourcesUrlModel.ts | 4 - .../facet-search/FacetSearchCriteriaModel.ts | 11 - .../src/app/models/files/ContentFile.ts | 16 - .../app/models/http/BaseHttpResponseModel.ts | 5 - .../app/models/interfaces/FormGenerator.ts | 4 - .../src/app/models/interfaces/Serializable.ts | 3 - .../src/app/models/invitation/Invitation.ts | 17 - .../src/app/models/invitation/User.ts | 25 - .../src/app/models/login/Credential.ts | 4 - .../src/app/models/login/LoginInfo.ts | 14 - .../src/app/models/login/Principal.ts | 35 - .../models/organisation/OrganisationModel.ts | 17 - .../src/app/models/profile/ProfileModel.ts | 18 - .../models/projects/ProjectListingModel.ts | 34 - .../src/app/models/projects/ProjectModel.ts | 80 - .../src/app/models/registers/RegisterModel.ts | 43 - .../app/models/researcher/ResearcherModel.ts | 29 - .../src/app/models/services/ServiceModel.ts | 41 - dmp-frontend/src/app/models/tags/TagModel.ts | 27 - .../src/app/models/users/UserErrorModel.ts | 6 - .../src/app/models/users/UserListingModel.ts | 16 - dmp-frontend/src/app/not-found.component.ts | 6 - .../editor/project-editor.component.html | 105 - .../editor/project-editor.component.scss | 21 - .../editor/project-editor.component.ts | 208 -- .../listing/project-listing.component.html | 72 - .../listing/project-listing.component.scss | 31 - .../listing/project-listing.component.ts | 151 - .../src/app/projects/project.routes.ts | 31 - .../src/app/projects/projects.module.ts | 68 - .../src/app/services/auth/auth.service.ts | 150 - .../breadcrumb/breadcrumb-resolver.service.ts | 85 - .../services/dashboard/dashboard.service.ts | 37 - .../datamanagement-profile.service.ts | 43 - .../data-management-plan.service.ts | 85 - .../datarepository/datarepository.service.ts | 27 - .../app/services/dataset-profile.service.ts | 31 - .../dataset-wizard/dataset-wizard.service.ts | 66 - .../app/services/dataset/dataset.service.ts | 47 - .../datasetProfileAfmin.service.ts | 51 - .../external-dataset.service.ts | 47 - .../external-sources-configuration.service.ts | 28 - .../external-sources.service.ts | 74 - .../files/project-file-uploader.service.ts | 30 - .../help-content/CachedContentItem.ts | 6 - .../help-content/help-content.service.ts | 55 - .../services/invitation/invitation.service.ts | 37 - .../app/services/language/language.service.ts | 6 +- .../app/services/project/project.service.ts | 57 - .../services/registries/registry.service.ts | 26 - .../researchers/researchers.service.ts | 26 - .../dmp-editor-resolver.service.ts | 34 - .../dmp-group-resolver.service.ts | 35 - .../project-resolver.service.ts | 34 - .../services/services-data.service.ts | 27 - .../user-reference-data.service.ts | 56 - .../add-researchers.component.ts | 40 - .../AutoCompleteConfiguration.ts | 14 - .../auto-complete.component.html | 12 - .../auto-complete.component.scss | 16 - .../auto-complete/auto-complete.component.ts | 131 - .../multiple-auto-complete-configuration.ts | 20 - .../multiple-auto-complete.component.html | 20 - .../multiple-auto-complete.component.scss | 14 - .../multiple-auto-complete.component.ts | 165 - .../single-auto-complete-configuration.ts | 20 - .../single-auto-complete.component.html | 15 - .../single-auto-complete.component.scss | 17 - .../single/single-auto-complete.component.ts | 120 - .../available-profiles.component.ts | 52 - .../breadcrumb/breadcrumb.component.html | 12 - .../breadcrumb/breadcrumb.component.scss | 8 - .../breadcrumb/breadcrumb.component.ts | 40 - .../breadcrumb/definition/breadcrumb-item.ts | 9 - .../criteria/base/base-criteria.component.ts | 104 - .../dmp-criteria.component.html | 23 - .../dmp-criteria.component.ts | 85 - .../dmp-profile-criteria.component.html | 13 - .../dmp-profile-criteria.component.ts | 58 - .../dataset-profile.component.ts | 45 - .../datasets/datasets-criteria.component.html | 45 - .../datasets/datasets-criteria.component.ts | 81 - .../projects/projects-criteria.component.html | 37 - .../projects/projects-criteria.component.ts | 55 - .../users/users-criteria.component.html | 19 - .../users/users-criteria.component.scss | 10 - .../users/users-criteria.component.ts | 87 - .../external-item-listing.component.html | 15 - .../external-item-listing.component.ts | 67 - .../external-item.component.html | 4 - .../external-item/external-item.component.ts | 46 - .../facet-search-section.component.ts | 92 - .../facets/facet-search.component.html | 75 - .../facets/facet-search.component.ts | 180 -- .../figurecard/figurecard.component.ts | 41 - .../components/file-uploader/FileUploader.ts | 6 - .../file-uploader.component.html | 11 - .../file-uploader/file-uploader.component.ts | 60 - .../invitation-accepted.component.html | 0 .../invitation-accepted.component.ts | 31 - .../invitation/invitation.component.html | 24 - .../invitation/invitation.component.scss | 0 .../invitation/invitation.component.ts | 70 - .../navigation/navigation.component.html | 57 - .../navigation/navigation.component.scss | 54 - .../navigation/navigation.component.ts | 131 - .../snack-bar-notification.component.ts | 27 - .../search-bar/search-bar.component.html | 0 .../search-bar/search-bar.component.scss | 0 .../search-bar/search-bar.component.ts | 17 - .../search-bar/types/search-bar-type.ts | 5 - .../components/url-listing/UrlListingItem.ts | 14 - .../url-listing/url-listing.component.ts | 30 - .../user-dialog/user-dialog.component.scss | 0 .../user-dialog/user-dialog.component.ts | 55 - .../autocomplete/autocomplete-component.html | 34 - .../autocomplete/autocomplete-component.ts | 29 - .../booleanDecision-component.html | 10 - .../booleanDecision-component.ts | 21 - .../checkbox/checkbox-component.html | 11 - .../checkbox/checkbox-component.ts | 21 - .../combobox/combobox-component.html | 17 - .../combobox/combobox-component.ts | 26 - .../freetext/freetext-component.html | 10 - .../freetext/freetext-component.ts | 22 - .../radiobox/radiobox-component.html | 34 - .../radiobox/radiobox-component.ts | 36 - .../textarea/textarea-component.html | 11 - .../textarea/textarea-component.ts | 23 - .../wordlist/wordlist-component.html | 35 - .../wordlist/wordlist-component.scss | 3 - .../wordlist/wordlist-component.ts | 36 - .../src/app/shared/guards/auth.guard.ts | 18 - .../help-content/help-content.component.ts | 65 - .../app/shared/material/material.module.ts | 97 - dmp-frontend/src/app/shared/shared.module.ts | 102 - .../src/app/ui/about/about.component.html | 32 + .../about}/about.component.scss | 0 .../src/app/ui/about/about.component.ts | 18 + dmp-frontend/src/app/ui/about/about.module.ts | 14 + .../src/app/ui/about/about.routing.ts | 16 + .../admin/default-value-editor-model.ts | 23 + .../auto-complete-field-data-editor-model.ts | 32 + ...oolean-decision-field-data-editor-model.ts | 18 + .../check-box-field-data-editor-model.ts | 18 + .../field-data/field-data-editor-model.ts | 16 + .../field-data-option-editor-model.ts | 21 + .../free-text-field-data-editor-model.ts | 18 + .../radio-box-field-data-editor-model.ts | 30 + .../text-area-field-data-editor-model.ts | 18 + .../word-list-field-data-editor-model.ts | 34 + .../admin/field-editor-model.ts | 76 + .../admin/field-set-editor-model.ts | 52 + .../admin/multiplicity-editor-model.ts | 22 + .../admin/page-editor-model.ts | 31 + .../admin/rule-editor-model.ts | 32 + .../admin/section-editor-model.ts | 58 + .../admin/view-style-editor-model.ts | 23 + .../admin/visibility-editor-model.ts | 36 + .../dataset-profile/dataset-profile.module.ts | 52 + .../dataset-profile.routing.ts | 29 + ...file-editor-composite-field.component.html | 55 + ...ile-editor-composite-field.component.scss} | 0 ...rofile-editor-composite-field.component.ts | 59 + ...-editor-auto-complete-field.component.html | 20 + ...editor-auto-complete-field.component.scss} | 0 ...le-editor-auto-complete-field.component.ts | 20 + ...itor-boolean-decision-field.component.html | 8 + ...tor-boolean-decision-field.component.scss} | 0 ...editor-boolean-decision-field.component.ts | 19 + ...ofile-editor-checkbox-field.component.html | 8 + ...file-editor-checkbox-field.component.scss} | 0 ...profile-editor-checkbox-field.component.ts | 18 + ...file-editor-combo-box-field.component.html | 10 + ...ile-editor-combo-box-field.component.scss} | 0 ...rofile-editor-combo-box-field.component.ts | 29 + ...file-editor-free-text-field.component.html | 8 + ...ile-editor-free-text-field.component.scss} | 0 ...rofile-editor-free-text-field.component.ts | 18 + ...file-editor-radio-box-field.component.html | 22 + ...ile-editor-radio-box-field.component.scss} | 0 ...rofile-editor-radio-box-field.component.ts | 25 + ...file-editor-text-area-field.component.html | 8 + ...ile-editor-text-area-field.component.scss} | 0 ...rofile-editor-text-area-field.component.ts | 18 + ...file-editor-word-list-field.component.html | 22 + ...ile-editor-word-list-field.component.scss} | 0 ...rofile-editor-word-list-field.component.ts | 26 + ...ataset-profile-editor-field.component.html | 49 + ...taset-profile-editor-field.component.scss} | 0 .../dataset-profile-editor-field.component.ts | 53 + ...dataset-profile-editor-page.component.html | 11 + ...dataset-profile-editor-page.component.scss | 7 + .../dataset-profile-editor-page.component.ts | 16 + ...dataset-profile-editor-rule.component.html | 18 + ...ataset-profile-editor-rule.component.scss} | 0 .../dataset-profile-editor-rule.component.ts | 21 + ...aset-profile-editor-section.component.html | 58 + ...aset-profile-editor-section.component.scss | 5 + ...ataset-profile-editor-section.component.ts | 68 + .../editor/dataset-profile-editor-model.ts | 41 + .../dataset-profile-editor.component.html | 42 + .../dataset-profile-editor.component.scss | 5 + .../dataset-profile-editor.component.ts | 173 + .../criteria}/dataset-profile.component.html | 0 .../criteria}/dataset-profile.component.scss | 0 .../criteria/dataset-profile.component.ts | 41 + .../dataset-profile-listing.component.html | 59 + .../dataset-profile-listing.component.scss} | 0 .../dataset-profile-listing.component.ts | 148 + .../dataset-profile-preview.component.html} | 0 .../dataset-profile-preview.component.scss} | 0 .../dataset-profile-preview.component.ts | 35 + .../admin/dmp-profile/dmp-profile.module.ts | 25 + .../admin/dmp-profile/dmp-profile.routing.ts | 17 + .../editor/dmp-profile-editor.component.html | 68 + .../editor/dmp-profile-editor.component.scss | 6 + .../editor/dmp-profile-editor.component.ts | 185 ++ .../editor/dmp-profile-editor.model.ts | 90 + .../dmp-profile-criteria.component.html | 10 + .../dmp-profile-criteria.component.scss | 0 .../dmp-profile-criteria.component.ts | 47 + .../dmp-profile-listing.component.html | 40 + .../dmp-profile-listing.component.scss | 26 + .../listing/dmp-profile-listing.component.ts | 132 + .../criteria/user-criteria.component.html | 14 + .../criteria/user-criteria.component.scss | 2 + .../criteria/user-criteria.component.ts | 85 + .../user-role-editor.component.html | 0 .../user-role-editor.component.scss} | 0 .../role-editor/user-role-editor.component.ts | 166 + .../user/listing/user-listing.component.html | 39 + .../user/listing/user-listing.component.scss | 14 + .../user/listing/user-listing.component.ts | 127 + .../src/app/ui/admin/user/user.module.ts | 24 + .../src/app/ui/admin/user/user.routing.ts | 14 + .../admin-login/admin-login.component.html | 0 .../admin-login/admin-login.component.scss | 0 .../auth/admin-login/admin-login.component.ts | 52 + .../ui/auth/admin-login/admin-login.module.ts | 17 + .../auth/admin-login/admin-login.routing.ts | 16 + .../b2access/b2access-login.component.html | 0 .../b2access/b2access-login.component.ts | 53 + .../auth}/login/img/b2access.png | Bin .../auth}/login/img/b2access_medium.png | Bin .../auth}/login/img/b2access_small.png | Bin .../linkedin-login.component.html | 0 .../linkedin-login.component.ts | 49 + .../app/ui/auth/login/login.component.html | 28 + .../auth}/login/login.component.scss | 0 .../src/app/ui/auth/login/login.component.ts | 156 + .../src/app/ui/auth/login/login.module.ts | 23 + .../src/app/ui/auth/login/login.routing.ts | 17 + .../twitter-login.component.html | 0 .../twitter-login/twitter-login.component.ts | 58 + .../ui/auth/login/utilities/login.service.ts | 55 + .../dashboard/card/card.component.html} | 0 .../dashboard/card/card.component.scss} | 0 .../app/ui/dashboard/card/card.component.ts | 41 + .../app/ui/dashboard/dashboard.component.html | 85 + .../app/ui/dashboard/dashboard.component.scss | 61 + .../app/ui/dashboard/dashboard.component.ts | 124 + .../src/app/ui/dashboard/dashboard.module.ts | 19 + .../src/app/ui/dashboard/dashboard.routing.ts | 13 + .../recent-activity.component.html | 67 + .../recent-activity.component.scss | 0 .../recent-activity.component.ts | 53 + .../dataset-editor.component.html | 17 + .../dataset-editor.component.scss | 1 + .../dataset-editor.component.ts | 23 + .../dataset-wizard-editor.model.ts | 325 ++ .../dataset-wizard.component.html | 92 + .../dataset-wizard.component.scss | 0 .../dataset-wizard.component.ts | 411 +++ ...-external-references-editor.component.html | 162 + ...-external-references-editor.component.scss | 1 + ...et-external-references-editor.component.ts | 233 ++ ...a-repository-dialog-editor.component.html} | 0 ...a-repository-dialog-editor.component.scss} | 0 ...data-repository-dialog-editor.component.ts | 35 + ...rnal-dataset-dialog-editor.component.html} | 0 ...rnal-dataset-dialog-editor.component.scss} | 0 ...xternal-dataset-dialog-editor.component.ts | 35 + ...nal-registry-dialog-editor.component.html} | 0 ...nal-registry-dialog-editor.component.scss} | 0 ...ternal-registry-dialog-editor.component.ts | 35 + ...rnal-service-dialog-editor.component.html} | 0 ...rnal-service-dialog-editor.component.scss} | 0 ...xternal-service-dialog-editor.component.ts | 34 + .../src/app/ui/dataset/dataset.module.ts | 49 + .../src/app/ui/dataset/dataset.routing.ts | 63 + .../criteria/dataset-criteria.component.html | 26 + .../criteria/dataset-criteria.component.scss} | 0 .../criteria/dataset-criteria.component.ts | 74 + .../listing/dataset-listing.component.html | 93 + .../listing/dataset-listing.component.scss | 0 .../listing/dataset-listing.component.ts | 156 + dmp-frontend/src/app/ui/dmp/dmp.module.ts | 53 + dmp-frontend/src/app/ui/dmp/dmp.routing.ts | 73 + .../add-researcher.component.html} | 0 .../add-researcher.component.ts | 36 + .../add-researcher/add-researcher.model.ts | 29 + .../available-profiles.component.html | 0 .../available-profiles.component.ts | 49 + .../ui/dmp/editor/dmp-editor.component.html | 144 + .../dmp}/editor/dmp-editor.component.scss | 0 .../app/ui/dmp/editor/dmp-editor.component.ts | 428 +++ .../src/app/ui/dmp/editor/dmp-editor.model.ts | 149 + .../dmp-finalize-dialog.component.html | 31 + .../dmp-finalize-dialog.component.scss} | 0 .../dmp-finalize-dialog.component.ts | 104 + .../dynamic-dmp-field-resolver.component.html | 15 + ...dynamic-dmp-field-resolver.component.scss} | 0 .../dynamic-dmp-field-resolver.component.ts | 39 + .../dynamic-field-project.component.html | 0 .../dynamic-field-project.component.scss} | 0 .../dynamic-field-project.component.ts | 85 + .../dynamic-fields-project.component.html | 0 .../dynamic-fields-project.component.scss} | 0 .../dynamic-fields-project.component.ts | 32 + .../dmp-invitation-accepted.component.html} | 0 .../dmp-invitation-accepted.component.ts | 31 + .../invitation/dmp-invitation.component.html | 13 + .../invitation/dmp-invitation.component.scss} | 0 .../invitation/dmp-invitation.component.ts | 76 + .../criteria/dmp-criteria.component.html | 19 + .../criteria}/dmp-criteria.component.scss | 0 .../criteria/dmp-criteria.component.ts | 81 + .../ui/dmp/listing/dmp-listing.component.html | 88 + .../ui/dmp/listing/dmp-listing.component.scss | 26 + .../ui/dmp/listing/dmp-listing.component.ts | 192 ++ .../ui/dmp/wizard/dmp-wizard-editor.model.ts | 149 + .../ui/dmp/wizard/dmp-wizard.component.html | 19 + .../dmp}/wizard/dmp-wizard.component.scss | 0 .../app/ui/dmp/wizard/dmp-wizard.component.ts | 93 + .../editor/dmp-wizard-editor.component.html | 63 + .../editor/dmp-wizard-editor.component.scss | 0 .../editor/dmp-wizard-editor.component.ts | 190 ++ ...dmp-wizard-dataset-listing.component.html} | 0 ...dmp-wizard-dataset-listing.component.scss} | 0 .../dmp-wizard-dataset-listing.component.ts | 80 + .../explore-dataset-listing.component.html | 85 + .../explore-dataset-listing.component.scss} | 0 .../explore-dataset-listing.component.ts | 147 + .../explore-dataset/explore-dataset.module.ts | 23 + .../explore-dataset.routing.ts | 19 + ...xplore-dataset-filter-item.component.html} | 0 ...xplore-dataset-filter-item.component.scss} | 0 .../explore-dataset-filter-item.component.ts | 92 + .../explore-dataset-filters.component.html | 59 + .../explore-dataset-filters.component.scss} | 0 .../explore-dataset-filters.component.ts | 182 ++ .../misc/breadcrumb/breadcrumb.component.html | 10 + .../misc/breadcrumb/breadcrumb.component.scss | 17 + .../misc/breadcrumb/breadcrumb.component.ts | 39 + .../ui/misc/breadcrumb/breadcrumb.module.ts | 20 + .../definition/IBreadCrumbComponent.ts | 0 .../breadcrumb/definition/breadcrumb-item.ts | 8 + .../breadcrumb/service/breadcrumb.service.ts | 85 + .../misc/criteria/base-criteria.component.ts | 99 + .../form-composite-field.component.html | 45 + .../form-composite-field.component.scss} | 0 .../form-composite-field.component.ts | 39 + .../form-field/form-field.component.html | 55 + .../form-field/form-field.component.scss | 9 + .../form-field/form-field.component.ts | 40 + .../form-progress-indication.component.html | 3 + .../form-progress-indication.component.ts | 67 + .../form-section/form-section.component.html | 43 + .../form-section/form-section.component.scss} | 0 .../form-section/form-section.component.ts | 54 + .../dataset-description-form.component.html | 20 + .../dataset-description-form.component.scss} | 0 .../dataset-description-form.component.ts | 125 + .../dataset-description-form.model.ts | 295 ++ .../dataset-description-form.module.ts | 33 + .../autocomplete-remote.component.css | 0 .../autocomplete-remote.component.html | 0 .../autocomplete-remote.component.ts | 53 + .../form-focus/form-focus.service.ts | 35 + ...m-pending-questions-display.component.html | 4 + ...-pending-questions-display.component.scss} | 0 ...orm-pending-questions-display.component.ts | 45 + .../mark-for-consideration.service.ts | 22 + .../base-table-of-content.component.ts | 0 .../table-of-content-field.component.html | 0 .../table-of-content-field.component.ts | 19 + .../table-of-content-fieldset.component.html | 0 .../table-of-content-fieldset.component.ts | 19 + .../table-of-content-group.component.html} | 0 .../table-of-content-group.component.ts | 24 + .../table-of-content-section.component.html | 0 .../table-of-content-section.component.ts | 23 + .../table-of-contents.component.html | 0 .../table-of-contents.component.ts | 19 + .../tableOfContents/toc.component.css | 0 .../models/visibility-rule-source.ts} | 0 .../models/visibility-rule.ts | 6 + .../models/visibility-rules-context.ts | 35 + .../visibility-rules.service.ts | 152 + .../external-sources.module.ts | 20 + .../external-item-listing.component.html | 19 + .../external-item-listing.component.scss | 0 .../external-item-listing.component.ts | 46 + .../help-content/help-content.component.ts | 66 + .../misc/help-content/help-content.module.ts | 14 + .../misc/navigation/navigation.component.html | 55 + .../misc/navigation/navigation.component.scss | 33 + .../misc/navigation/navigation.component.ts | 130 + .../ui/misc/navigation/navigation.module.ts | 21 + .../user-dialog/user-dialog.component.html | 0 .../user-dialog/user-dialog.component.ts | 49 + .../unauthorized/unauthorized.component.html | 0 .../unauthorized/unauthorized.component.ts | 35 + .../misc/unauthorized/unauthorized.module.ts | 15 + .../misc/unauthorized/unauthorized.routes.ts | 16 + .../editor/project-editor.component.html | 104 + .../editor/project-editor.component.scss | 20 + .../editor/project-editor.component.ts | 203 ++ .../ui/project/editor/project-editor.model.ts | 74 + .../criteria/project-criteria.component.html | 33 + .../criteria/project-criteria.component.scss} | 0 .../criteria/project-criteria.component.ts | 49 + .../listing/project-listing.component.html | 68 + .../listing/project-listing.component.scss | 25 + .../listing/project-listing.component.ts | 142 + .../src/app/ui/project/project.module.ts | 25 + .../src/app/ui/project/project.routing.ts | 34 + .../user-profile/user-profile.component.html | 89 + .../user-profile}/user-profile.component.scss | 0 .../ui/user-profile/user-profile.component.ts | 135 + .../ui/user-profile/user-profile.module.ts | 19 + .../ui/user-profile/user-profile.routing.ts | 19 + .../unauthorized.component.js.map | 1 - .../unauthorized/unauthorized.component.ts | 35 - .../unauthorized/unauthorized.module.js.map | 1 - .../app/unauthorized/unauthorized.module.ts | 27 - .../unauthorized/unauthorized.routes.js.map | 1 - .../app/unauthorized/unauthorized.routes.ts | 9 - .../admin-login/admin-login.component.ts | 35 - .../src/app/user-management/login.module.ts | 45 - .../src/app/user-management/login.routes.ts | 14 - .../b2access/b2access-login.component.ts | 29 - .../linkedin-login.component.ts | 29 - .../login/login.component.html | 48 - .../user-management/login/login.component.ts | 75 - .../twitter-login/twitter-login.component.ts | 27 - .../user-management/utilties/LoginOptions.ts | 9 - .../utilties/LoginProviderConfiguration.ts | 23 - .../utilties/LoginServiceConfiguration.ts | 16 - .../user-management/utilties/login-service.ts | 250 -- .../app/users/activity/RecentActivityTypes.ts | 5 - .../activity/recent-activity.component.html | 67 - .../activity/recent-activity.component.ts | 55 - .../roles/user-role-editor.component.scss | 3 - .../roles/user-role-editor.component.ts | 167 - .../app/users/components/users.component.html | 41 - .../app/users/components/users.component.scss | 12 - .../app/users/components/users.component.ts | 132 - .../users/profile/user-profile.component.html | 90 - .../users/profile/user-profile.component.ts | 139 - dmp-frontend/src/app/users/users.module.ts | 66 - dmp-frontend/src/app/users/users.routes.ts | 8 - .../src/app/utilities/JsonSerializer.ts | 22 - .../src/app/utilities/UrlUtilities.ts | 17 - .../base-http.service.ts | 133 - .../cite-http.module.ts | 25 - .../app/utilities/culture/culture-service.ts | 76 - .../utilities/culture/models/culture-info.ts | 5 - .../culture/pipes/TimezoneInfoDisplayPipe.ts | 12 - .../form-focus-service/form-focus.service.ts | 36 - .../src/app/utilities/forms/FormGenerator.ts | 6 - .../mark-for-consideration.service.ts | 22 - .../app/utilities/types/ApiResponseCode.ts | 4 - dmp-frontend/src/app/utilities/utilities.ts | 51 - .../validators/BackendErrorValidator.ts | 9 - .../utilities/validators/ValidationContext.ts | 20 - .../visibility-rules/models/VisibilityRule.ts | 5 - .../models/VisibilityRulesContext.ts | 32 - .../visibility-rules.service.ts | 148 - .../welcomepage/welcomepage.component.html | 1 - .../app/welcomepage/welcomepage.component.ts | 30 - dmp-frontend/src/assets/i18n/en.json | 603 ++++ dmp-frontend/src/assets/i18n/gr.json | 21 + dmp-frontend/src/assets/lang/en.json | 28 +- .../localization/available-cultures.json | 2816 +++++++++++++++++ dmp-frontend/src/blue-theme.scss | 2 + .../src/environments/environment.prod.ts | 11 +- .../src/environments/environment.staging.ts | 13 +- dmp-frontend/src/environments/environment.ts | 24 +- dmp-frontend/src/styles.scss | 2 +- 863 files changed, 19949 insertions(+), 17007 deletions(-) create mode 100644 dmp-backend/108131ae-d07a-4e8c-8f75-8c8e33fe9974.xml create mode 100644 dmp-backend/7b1bdf71-945e-40db-b8fb-1b2d313fbebe.xml create mode 100644 dmp-backend/be3facf6-0eb9-4668-99d6-f99215ccec1b.xml delete mode 100644 dmp-frontend/src/app/about/about.module.ts delete mode 100644 dmp-frontend/src/app/about/about.routes.ts delete mode 100644 dmp-frontend/src/app/about/components/about.component.html delete mode 100644 dmp-frontend/src/app/about/components/about.component.ts create mode 100644 dmp-frontend/src/app/common/date/moment-utc-date-adapter.ts create mode 100644 dmp-frontend/src/app/common/forms/common-forms.module.ts create mode 100644 dmp-frontend/src/app/common/forms/validation/custom-validator.ts create mode 100644 dmp-frontend/src/app/common/forms/validation/error-model/validation-error-model.ts create mode 100644 dmp-frontend/src/app/common/forms/validation/validation-context.ts create mode 100644 dmp-frontend/src/app/common/http/base-http-params.ts create mode 100644 dmp-frontend/src/app/common/http/common-http.module.ts create mode 100644 dmp-frontend/src/app/common/http/interceptor-context.ts create mode 100644 dmp-frontend/src/app/common/http/interceptors/auth-token.interceptor.ts create mode 100644 dmp-frontend/src/app/common/http/interceptors/base.interceptor.ts create mode 100644 dmp-frontend/src/app/common/http/interceptors/interceptor-type.ts create mode 100644 dmp-frontend/src/app/common/http/interceptors/json.interceptor.ts create mode 100644 dmp-frontend/src/app/common/http/interceptors/locale.interceptor.ts create mode 100644 dmp-frontend/src/app/common/http/interceptors/progress-indication.interceptor.ts create mode 100644 dmp-frontend/src/app/common/http/interceptors/request-timing.interceptor.ts create mode 100644 dmp-frontend/src/app/common/http/interceptors/response-payload.interceptor.ts create mode 100644 dmp-frontend/src/app/common/http/interceptors/unauthorized-response.interceptor.ts create mode 100644 dmp-frontend/src/app/common/material/material.module.ts create mode 100644 dmp-frontend/src/app/common/types/guid.ts create mode 100644 dmp-frontend/src/app/common/types/json/json-serializer.ts rename dmp-frontend/src/app/{models/Serializable.ts => common/types/json/serializable.ts} (100%) rename dmp-frontend/src/app/{models/helpers/Pair.ts => common/types/pair.ts} (100%) create mode 100644 dmp-frontend/src/app/common/ui/common-ui.module.ts create mode 100644 dmp-frontend/src/app/core/auth-guard.service.ts rename dmp-frontend/src/app/{utilities/types/ApiMessageCode.ts => core/common/enum/api-message-code.ts} (100%) create mode 100644 dmp-frontend/src/app/core/common/enum/app-role.ts create mode 100644 dmp-frontend/src/app/core/common/enum/auth-provider.ts create mode 100644 dmp-frontend/src/app/core/common/enum/dataset-profile-combo-box-type.ts create mode 100644 dmp-frontend/src/app/core/common/enum/dataset-profile-field-view-style.ts create mode 100644 dmp-frontend/src/app/core/common/enum/dataset-status.ts create mode 100644 dmp-frontend/src/app/core/common/enum/dmp-profile-field-type.ts create mode 100644 dmp-frontend/src/app/core/common/enum/dmp-profile-type.ts create mode 100644 dmp-frontend/src/app/core/common/enum/dmp-status.ts create mode 100644 dmp-frontend/src/app/core/common/enum/external-dataset-type.ts rename dmp-frontend/src/app/{models/projects/ProjectStateType.ts => core/common/enum/project-state-type.ts} (100%) create mode 100644 dmp-frontend/src/app/core/common/enum/project-type.ts create mode 100644 dmp-frontend/src/app/core/common/enum/recent-activity-type.ts rename dmp-frontend/src/app/{models/Status.ts => core/common/enum/status.ts} (100%) create mode 100644 dmp-frontend/src/app/core/common/enum/validation-type.ts create mode 100644 dmp-frontend/src/app/core/core-service.module.ts create mode 100644 dmp-frontend/src/app/core/formatting.module.ts create mode 100644 dmp-frontend/src/app/core/model/admin/dataset-profile/dataset-profile.ts create mode 100644 dmp-frontend/src/app/core/model/auth/credential.ts create mode 100644 dmp-frontend/src/app/core/model/auth/login-info.ts create mode 100644 dmp-frontend/src/app/core/model/auth/principal.ts create mode 100644 dmp-frontend/src/app/core/model/base-form-model.ts create mode 100644 dmp-frontend/src/app/core/model/culture-info.ts create mode 100644 dmp-frontend/src/app/core/model/dashboard/dashboard-statistics-model.ts create mode 100644 dmp-frontend/src/app/core/model/dashboard/search-bar-item.ts create mode 100644 dmp-frontend/src/app/core/model/data-repository/data-repository.ts create mode 100644 dmp-frontend/src/app/core/model/data-table/column-ordering.ts rename dmp-frontend/src/app/{models/data-table/DataTableData.ts => core/model/data-table/data-table-data.ts} (100%) create mode 100644 dmp-frontend/src/app/core/model/data-table/data-table-request.ts create mode 100644 dmp-frontend/src/app/core/model/dataset-profile-definition/composite-field.ts create mode 100644 dmp-frontend/src/app/core/model/dataset-profile-definition/dataset-profile-definition.ts create mode 100644 dmp-frontend/src/app/core/model/dataset-profile-definition/default-value.ts create mode 100644 dmp-frontend/src/app/core/model/dataset-profile-definition/field-data/field-data.ts create mode 100644 dmp-frontend/src/app/core/model/dataset-profile-definition/field-group.ts create mode 100644 dmp-frontend/src/app/core/model/dataset-profile-definition/field.ts create mode 100644 dmp-frontend/src/app/core/model/dataset-profile-definition/multiplicity.ts create mode 100644 dmp-frontend/src/app/core/model/dataset-profile-definition/page.ts create mode 100644 dmp-frontend/src/app/core/model/dataset-profile-definition/rule.ts create mode 100644 dmp-frontend/src/app/core/model/dataset-profile-definition/section.ts create mode 100644 dmp-frontend/src/app/core/model/dataset-profile-definition/view-style.ts create mode 100644 dmp-frontend/src/app/core/model/dataset/dataset-listing.ts create mode 100644 dmp-frontend/src/app/core/model/dataset/dataset-profile.ts create mode 100644 dmp-frontend/src/app/core/model/dataset/dataset-wizard.ts create mode 100644 dmp-frontend/src/app/core/model/dataset/dataset.ts create mode 100644 dmp-frontend/src/app/core/model/dmp-profile/dmp-profile-field.ts create mode 100644 dmp-frontend/src/app/core/model/dmp-profile/dmp-profile-listing.ts create mode 100644 dmp-frontend/src/app/core/model/dmp-profile/dmp-profile.ts create mode 100644 dmp-frontend/src/app/core/model/dmp/dmp-dynamic-field-dependency.ts create mode 100644 dmp-frontend/src/app/core/model/dmp/dmp-dynamic-field.ts create mode 100644 dmp-frontend/src/app/core/model/dmp/dmp-listing.ts create mode 100644 dmp-frontend/src/app/core/model/dmp/dmp.ts create mode 100644 dmp-frontend/src/app/core/model/dmp/invitation/dmp-invitation-user.ts create mode 100644 dmp-frontend/src/app/core/model/dmp/invitation/dmp-invitation.ts create mode 100644 dmp-frontend/src/app/core/model/external-dataset/external-dataset.ts create mode 100644 dmp-frontend/src/app/core/model/external-sources/external-source-item.ts create mode 100644 dmp-frontend/src/app/core/model/external-sources/external-source-url.ts create mode 100644 dmp-frontend/src/app/core/model/external-sources/external-sources-configuration.ts rename dmp-frontend/src/app/{models => core/model}/help-content/active-topic-questions.ts (100%) rename dmp-frontend/src/app/{models => core/model}/help-content/page-help-content.ts (100%) rename dmp-frontend/src/app/{models => core/model}/help-content/page.ts (100%) rename dmp-frontend/src/app/{models => core/model}/help-content/question.ts (100%) rename dmp-frontend/src/app/{models => core/model}/help-content/topic.ts (100%) create mode 100644 dmp-frontend/src/app/core/model/organisation/organization.ts create mode 100644 dmp-frontend/src/app/core/model/project/project-listing.ts create mode 100644 dmp-frontend/src/app/core/model/project/project.ts create mode 100644 dmp-frontend/src/app/core/model/registry/registry.ts create mode 100644 dmp-frontend/src/app/core/model/researcher/researcher.ts create mode 100644 dmp-frontend/src/app/core/model/service/service.ts create mode 100644 dmp-frontend/src/app/core/model/tag/tag.ts create mode 100644 dmp-frontend/src/app/core/model/user/user-listing.ts create mode 100644 dmp-frontend/src/app/core/model/user/user.ts create mode 100644 dmp-frontend/src/app/core/pipes/culture-info-display.pipe.ts create mode 100644 dmp-frontend/src/app/core/pipes/date-format.pipe.ts create mode 100644 dmp-frontend/src/app/core/pipes/date-time-format.pipe.ts rename dmp-frontend/src/app/{shared/pipes/ngforlimit/ngforlimit.pipe.ts => core/pipes/ng-for-limit.pipe.ts} (100%) create mode 100644 dmp-frontend/src/app/core/pipes/pipe.service.ts create mode 100644 dmp-frontend/src/app/core/pipes/timezone-info-display.pipe.ts create mode 100644 dmp-frontend/src/app/core/query/base-criteria.ts create mode 100644 dmp-frontend/src/app/core/query/data-repository/data-repository-criteria.ts create mode 100644 dmp-frontend/src/app/core/query/dataset-profile/dataset-profile-criteria.ts create mode 100644 dmp-frontend/src/app/core/query/dataset/dataset-criteria.ts create mode 100644 dmp-frontend/src/app/core/query/dmp/dmp-criteria.ts create mode 100644 dmp-frontend/src/app/core/query/dmp/dmp-invitation-user-criteria.ts create mode 100644 dmp-frontend/src/app/core/query/dmp/dmp-profile-criteria.ts create mode 100644 dmp-frontend/src/app/core/query/explore-dataset/explore-dataset-criteria.ts create mode 100644 dmp-frontend/src/app/core/query/external-dataset/external-dataset-criteria.ts create mode 100644 dmp-frontend/src/app/core/query/project/project-criteria.ts create mode 100644 dmp-frontend/src/app/core/query/registry/registry-criteria.ts create mode 100644 dmp-frontend/src/app/core/query/request-item.ts create mode 100644 dmp-frontend/src/app/core/query/researcher/researcher-criteria.ts create mode 100644 dmp-frontend/src/app/core/query/service/service-criteria.ts create mode 100644 dmp-frontend/src/app/core/query/tag/tag-criteria.ts create mode 100644 dmp-frontend/src/app/core/query/user/user-criteria.ts create mode 100644 dmp-frontend/src/app/core/services/auth/auth.service.ts create mode 100644 dmp-frontend/src/app/core/services/culture/culture-service.ts create mode 100644 dmp-frontend/src/app/core/services/dashboard/dashboard.service.ts create mode 100644 dmp-frontend/src/app/core/services/dataset-profile/dataset-profile.service.ts create mode 100644 dmp-frontend/src/app/core/services/dataset-wizard/dataset-wizard.service.ts create mode 100644 dmp-frontend/src/app/core/services/dataset/dataset.service.ts create mode 100644 dmp-frontend/src/app/core/services/dmp/dmp-invitation.service.ts create mode 100644 dmp-frontend/src/app/core/services/dmp/dmp-profile.service.ts create mode 100644 dmp-frontend/src/app/core/services/dmp/dmp.service.ts create mode 100644 dmp-frontend/src/app/core/services/external-sources/data-repository/extternal-data-repository.service.ts create mode 100644 dmp-frontend/src/app/core/services/external-sources/dataset/external-dataset.service.ts create mode 100644 dmp-frontend/src/app/core/services/external-sources/external-sources-configuration.service.ts create mode 100644 dmp-frontend/src/app/core/services/external-sources/external-sources.service.ts create mode 100644 dmp-frontend/src/app/core/services/external-sources/registry/external-registry.service.ts create mode 100644 dmp-frontend/src/app/core/services/external-sources/researcher/external-researcher.service.ts create mode 100644 dmp-frontend/src/app/core/services/external-sources/service/external-service.service.ts create mode 100644 dmp-frontend/src/app/core/services/help-content/cached-content-item.ts create mode 100644 dmp-frontend/src/app/core/services/help-content/help-content.service.ts create mode 100644 dmp-frontend/src/app/core/services/http/base-http.service.ts create mode 100644 dmp-frontend/src/app/core/services/logging/logging-service.ts create mode 100644 dmp-frontend/src/app/core/services/notification/ui-notification-service.ts create mode 100644 dmp-frontend/src/app/core/services/progress-indication/progress-indication-service.ts create mode 100644 dmp-frontend/src/app/core/services/project/project-file-upload.service.ts create mode 100644 dmp-frontend/src/app/core/services/project/project.service.ts create mode 100644 dmp-frontend/src/app/core/services/search-bar/search-bar.service.ts create mode 100644 dmp-frontend/src/app/core/services/timezone/timezone-service.ts create mode 100644 dmp-frontend/src/app/core/services/user/user.service.ts create mode 100644 dmp-frontend/src/app/core/services/utilities/collection-utils.service.ts create mode 100644 dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts create mode 100644 dmp-frontend/src/app/core/services/utilities/type-utils.service.ts delete mode 100644 dmp-frontend/src/app/dataset-profile-form/compositefield-form/compositefield-form.component.html delete mode 100644 dmp-frontend/src/app/dataset-profile-form/compositefield-form/compositefield-form.component.ts delete mode 100644 dmp-frontend/src/app/dataset-profile-form/dataset-profile.module.ts delete mode 100644 dmp-frontend/src/app/dataset-profile-form/dataset-profile.router.ts delete mode 100644 dmp-frontend/src/app/dataset-profile-form/datasets-admin-listing/dataset-profile-admin-listing.component.html delete mode 100644 dmp-frontend/src/app/dataset-profile-form/datasets-admin-listing/dataset-profile-admin-listing.component.ts delete mode 100644 dmp-frontend/src/app/dataset-profile-form/field-form/field-form.component.html delete mode 100644 dmp-frontend/src/app/dataset-profile-form/field-form/field-form.component.ts delete mode 100644 dmp-frontend/src/app/dataset-profile-form/form/form.component.html delete mode 100644 dmp-frontend/src/app/dataset-profile-form/form/form.component.scss delete mode 100644 dmp-frontend/src/app/dataset-profile-form/form/form.component.ts delete mode 100644 dmp-frontend/src/app/dataset-profile-form/page-form/page-component.html delete mode 100644 dmp-frontend/src/app/dataset-profile-form/page-form/page-component.ts delete mode 100644 dmp-frontend/src/app/dataset-profile-form/previewer/dataset-profile-previewer.component.ts delete mode 100644 dmp-frontend/src/app/dataset-profile-form/rule-component/rule.component.html delete mode 100644 dmp-frontend/src/app/dataset-profile-form/rule-component/rule.component.ts delete mode 100644 dmp-frontend/src/app/dataset-profile-form/section-form/section-form.component.html delete mode 100644 dmp-frontend/src/app/dataset-profile-form/section-form/section-form.component.scss delete mode 100644 dmp-frontend/src/app/dataset-profile-form/section-form/section-form.component.ts delete mode 100644 dmp-frontend/src/app/datasets/dataset-public/dataset-public-listing.component.html delete mode 100644 dmp-frontend/src/app/datasets/dataset-public/dataset-public-listing.component.ts delete mode 100644 dmp-frontend/src/app/datasets/dataset-referenced-models-helper/datarepository/datarepository-referenced-model-helper.component.ts delete mode 100644 dmp-frontend/src/app/datasets/dataset-referenced-models-helper/externalDataset/externaldataset-referenced-model-helper.component.ts delete mode 100644 dmp-frontend/src/app/datasets/dataset-referenced-models-helper/registry/registry-referenced-model-helper.component.ts delete mode 100644 dmp-frontend/src/app/datasets/dataset-referenced-models-helper/services/services-referenced-model-helper.component.ts delete mode 100644 dmp-frontend/src/app/datasets/dataset-wizard/dataset-wizard.component.html delete mode 100644 dmp-frontend/src/app/datasets/dataset-wizard/dataset-wizard.component.ts delete mode 100644 dmp-frontend/src/app/datasets/dataset.module.ts delete mode 100644 dmp-frontend/src/app/datasets/dataset.routes.ts delete mode 100644 dmp-frontend/src/app/datasets/editor/dataset-editor.component.html delete mode 100644 dmp-frontend/src/app/datasets/editor/dataset-editor.component.scss delete mode 100644 dmp-frontend/src/app/datasets/editor/dataset-editor.component.ts delete mode 100644 dmp-frontend/src/app/datasets/listing/dataset-listing.component.html delete mode 100644 dmp-frontend/src/app/datasets/listing/dataset-listing.component.ts delete mode 100644 dmp-frontend/src/app/dmp-profiles/dmp-profile-editor/dmp-profile-editor.component.html delete mode 100644 dmp-frontend/src/app/dmp-profiles/dmp-profile-editor/dmp-profile-editor.component.scss delete mode 100644 dmp-frontend/src/app/dmp-profiles/dmp-profile-editor/dmp-profile-editor.component.ts delete mode 100644 dmp-frontend/src/app/dmp-profiles/dmp-profile-listing/dmp-profile-listing.component.html delete mode 100644 dmp-frontend/src/app/dmp-profiles/dmp-profile-listing/dmp-profile-listing.component.ts delete mode 100644 dmp-frontend/src/app/dmp-profiles/dmp-profile.module.ts delete mode 100644 dmp-frontend/src/app/dmp-profiles/dmp-profile.routes.ts delete mode 100644 dmp-frontend/src/app/dmps/dmps.module.ts delete mode 100644 dmp-frontend/src/app/dmps/dmps.routes.ts delete mode 100644 dmp-frontend/src/app/dmps/editor/dmp-editor.component.html delete mode 100644 dmp-frontend/src/app/dmps/editor/dmp-editor.component.ts delete mode 100644 dmp-frontend/src/app/dmps/editor/dmp-finalise-dialog/dmp-finalise-dialog.component.html delete mode 100644 dmp-frontend/src/app/dmps/editor/dmp-finalise-dialog/dmp-finalise-dialog.component.ts delete mode 100644 dmp-frontend/src/app/dmps/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.html delete mode 100644 dmp-frontend/src/app/dmps/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.ts delete mode 100644 dmp-frontend/src/app/dmps/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.ts delete mode 100644 dmp-frontend/src/app/dmps/editor/dynamic-fields-project/dynamic-fields-project.component.ts delete mode 100644 dmp-frontend/src/app/dmps/listing/dmp-listing.component.html delete mode 100644 dmp-frontend/src/app/dmps/listing/dmp-listing.component.scss delete mode 100644 dmp-frontend/src/app/dmps/listing/dmp-listing.component.ts delete mode 100644 dmp-frontend/src/app/dmps/wizard/dmp-wizard.component.html delete mode 100644 dmp-frontend/src/app/dmps/wizard/dmp-wizard.component.ts delete mode 100644 dmp-frontend/src/app/dmps/wizard/editor/dmp-wizard-editor.component.html delete mode 100644 dmp-frontend/src/app/dmps/wizard/editor/dmp-wizard-editor.component.ts delete mode 100644 dmp-frontend/src/app/dmps/wizard/listing/dataset-wizard-listing.component.scss delete mode 100644 dmp-frontend/src/app/dmps/wizard/listing/dataset-wizard-listing.component.ts delete mode 100644 dmp-frontend/src/app/form/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.ts delete mode 100644 dmp-frontend/src/app/form/dynamic-fields/dynamic-field-boolean-decision/dynamic-field-boolean-decision.component.html delete mode 100644 dmp-frontend/src/app/form/dynamic-fields/dynamic-field-boolean-decision/dynamic-field-boolean-decision.component.ts delete mode 100644 dmp-frontend/src/app/form/dynamic-fields/dynamic-field-checkbox/dynamic-field-checkbox.html delete mode 100644 dmp-frontend/src/app/form/dynamic-fields/dynamic-field-checkbox/dynamic-field-checkbox.ts delete mode 100644 dmp-frontend/src/app/form/dynamic-fields/dynamic-field-dropdown/dynamic-field-dropdown.css delete mode 100644 dmp-frontend/src/app/form/dynamic-fields/dynamic-field-dropdown/dynamic-field-dropdown.html delete mode 100644 dmp-frontend/src/app/form/dynamic-fields/dynamic-field-dropdown/dynamic-field-dropdown.ts delete mode 100644 dmp-frontend/src/app/form/dynamic-fields/dynamic-field-radiobox/dynamic-field-radiobox.component.css delete mode 100644 dmp-frontend/src/app/form/dynamic-fields/dynamic-field-radiobox/dynamic-field-radiobox.component.html delete mode 100644 dmp-frontend/src/app/form/dynamic-fields/dynamic-field-radiobox/dynamic-field-radiobox.component.ts delete mode 100644 dmp-frontend/src/app/form/dynamic-fields/dynamic-form-field.component.css delete mode 100644 dmp-frontend/src/app/form/dynamic-fields/dynamic-form-field.component.html delete mode 100644 dmp-frontend/src/app/form/dynamic-fields/dynamic-form-field.component.ts delete mode 100644 dmp-frontend/src/app/form/dynamic-form-composite-field/dynamic-form-composite-field.html delete mode 100644 dmp-frontend/src/app/form/dynamic-form-composite-field/dynamic-form-composite-field.ts delete mode 100644 dmp-frontend/src/app/form/dynamic-form-group/dynamic-form-group.component.css delete mode 100644 dmp-frontend/src/app/form/dynamic-form-group/dynamic-form-group.component.html delete mode 100644 dmp-frontend/src/app/form/dynamic-form-group/dynamic-form-group.component.spec.ts delete mode 100644 dmp-frontend/src/app/form/dynamic-form-group/dynamic-form-group.component.ts delete mode 100644 dmp-frontend/src/app/form/dynamic-form-section/dynamic-form-section.html delete mode 100644 dmp-frontend/src/app/form/dynamic-form-section/dynamic-form-section.ts delete mode 100644 dmp-frontend/src/app/form/dynamic-form.module.ts delete mode 100644 dmp-frontend/src/app/form/dynamic-form/dynamic-form.component.html delete mode 100644 dmp-frontend/src/app/form/dynamic-form/dynamic-form.component.ts delete mode 100644 dmp-frontend/src/app/form/fields/dropdown/field-dropdown.css delete mode 100644 dmp-frontend/src/app/form/fields/dropdown/field-dropdown.html delete mode 100644 dmp-frontend/src/app/form/fields/dropdown/field-dropdown.ts delete mode 100644 dmp-frontend/src/app/form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.html delete mode 100644 dmp-frontend/src/app/form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.ts delete mode 100644 dmp-frontend/src/app/form/pagination/pagination-service.ts delete mode 100644 dmp-frontend/src/app/form/pprogress-bar/progress-bar.component.html delete mode 100644 dmp-frontend/src/app/form/pprogress-bar/progress-bar.component.ts delete mode 100644 dmp-frontend/src/app/form/tableOfContents/table-of-content-field/table-of-content-field.component.ts delete mode 100644 dmp-frontend/src/app/form/tableOfContents/table-of-content-fieldset/table-of-content-fieldset.component.ts delete mode 100644 dmp-frontend/src/app/form/tableOfContents/table-of-content-group/table-of-content-group.component.ts delete mode 100644 dmp-frontend/src/app/form/tableOfContents/table-of-content-section/table-of-content-section.component.ts delete mode 100644 dmp-frontend/src/app/form/tableOfContents/table-of-contents.component.ts delete mode 100644 dmp-frontend/src/app/homepage/homepage.component.html delete mode 100644 dmp-frontend/src/app/homepage/homepage.component.scss delete mode 100644 dmp-frontend/src/app/homepage/homepage.component.ts create mode 100644 dmp-frontend/src/app/library/auto-complete/auto-complete-custom-validator.ts create mode 100644 dmp-frontend/src/app/library/auto-complete/auto-complete-group.ts create mode 100644 dmp-frontend/src/app/library/auto-complete/auto-complete.module.ts create mode 100644 dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete-configuration.ts create mode 100644 dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.html create mode 100644 dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.scss create mode 100644 dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.ts create mode 100644 dmp-frontend/src/app/library/auto-complete/single/single-auto-complete-configuration.ts create mode 100644 dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.html create mode 100644 dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.scss create mode 100644 dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.ts create mode 100644 dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.html create mode 100644 dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.scss create mode 100644 dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.ts create mode 100644 dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.module.ts create mode 100644 dmp-frontend/src/app/library/notification/notification.component.html create mode 100644 dmp-frontend/src/app/library/notification/notification.component.scss create mode 100644 dmp-frontend/src/app/library/notification/notification.component.ts create mode 100644 dmp-frontend/src/app/library/notification/notification.module.ts create mode 100644 dmp-frontend/src/app/library/notification/popup/popup-notification.component.html create mode 100644 dmp-frontend/src/app/library/notification/popup/popup-notification.component.ts rename dmp-frontend/src/app/{shared/components/notificaiton => library/notification/snack-bar}/snack-bar-notification.component.html (100%) create mode 100644 dmp-frontend/src/app/library/notification/snack-bar/snack-bar-notification.component.ts create mode 100644 dmp-frontend/src/app/library/url-listing/url-listing-item.ts rename dmp-frontend/src/app/{shared/components => library}/url-listing/url-listing.component.html (100%) create mode 100644 dmp-frontend/src/app/library/url-listing/url-listing.component.ts create mode 100644 dmp-frontend/src/app/library/url-listing/url-listing.module.ts delete mode 100644 dmp-frontend/src/app/models/BaseModel.ts delete mode 100644 dmp-frontend/src/app/models/CompositeField.ts delete mode 100644 dmp-frontend/src/app/models/DataField/AutocompleteData.ts delete mode 100644 dmp-frontend/src/app/models/DataField/BooleanDecisionData.ts delete mode 100644 dmp-frontend/src/app/models/DataField/CheckBoxData.ts delete mode 100644 dmp-frontend/src/app/models/DataField/DataField.ts delete mode 100644 dmp-frontend/src/app/models/DataField/FreeTextData.ts delete mode 100644 dmp-frontend/src/app/models/DataField/RadioBoxData.ts delete mode 100644 dmp-frontend/src/app/models/DataField/TextArea.ts delete mode 100644 dmp-frontend/src/app/models/DataField/WordListData.ts delete mode 100644 dmp-frontend/src/app/models/DatasetProfileDefinitionModel.ts delete mode 100644 dmp-frontend/src/app/models/DefaultValue.ts delete mode 100644 dmp-frontend/src/app/models/Field.ts delete mode 100644 dmp-frontend/src/app/models/FieldGroup.ts delete mode 100644 dmp-frontend/src/app/models/Multiplicity.ts delete mode 100644 dmp-frontend/src/app/models/Page.ts delete mode 100644 dmp-frontend/src/app/models/Rule.ts delete mode 100644 dmp-frontend/src/app/models/Section.ts delete mode 100644 dmp-frontend/src/app/models/Validation.ts delete mode 100644 dmp-frontend/src/app/models/auto-complete/AutocompleteLookupItem.ts delete mode 100644 dmp-frontend/src/app/models/common/ListingItem.ts delete mode 100644 dmp-frontend/src/app/models/common/ValidationTypes.ts delete mode 100644 dmp-frontend/src/app/models/criteria/BaseCriteria.ts delete mode 100644 dmp-frontend/src/app/models/criteria/BaseCriteriaErrorModel.ts delete mode 100644 dmp-frontend/src/app/models/criteria/RequestItem.ts delete mode 100644 dmp-frontend/src/app/models/criteria/data-management-plan/DataManagementPlanCriteria.ts delete mode 100644 dmp-frontend/src/app/models/criteria/data-management-plan/DataManagementPlanCriteriaErrorModel.ts delete mode 100644 dmp-frontend/src/app/models/criteria/data-repository/DataRepositoryCriteria.ts delete mode 100644 dmp-frontend/src/app/models/criteria/dataset-profile/DatasetProfileCriteria.ts delete mode 100644 dmp-frontend/src/app/models/criteria/dataset/DatasetCriteria.ts delete mode 100644 dmp-frontend/src/app/models/criteria/dataset/DatasetCriteriaErrorModel.ts delete mode 100644 dmp-frontend/src/app/models/criteria/dmp-profile/DataManagementPlanProfileCriteria.ts delete mode 100644 dmp-frontend/src/app/models/criteria/dmp-profile/DataManagementPlanProfileCriteriaErrorModel.ts delete mode 100644 dmp-frontend/src/app/models/criteria/external-dataset/ExetrnalDatasetCriteriaErrorModel.ts delete mode 100644 dmp-frontend/src/app/models/criteria/external-dataset/ExternalDatasetCriteria.ts delete mode 100644 dmp-frontend/src/app/models/criteria/invitation/UserInvitationCriteria.ts delete mode 100644 dmp-frontend/src/app/models/criteria/project/ProjectCriteria.ts delete mode 100644 dmp-frontend/src/app/models/criteria/project/ProjectCriteriaErrorModel.ts delete mode 100644 dmp-frontend/src/app/models/criteria/registry/RegistryCriteria.ts delete mode 100644 dmp-frontend/src/app/models/criteria/researchers/ResearcherCriteria.ts delete mode 100644 dmp-frontend/src/app/models/criteria/services/ServicesCriteria.ts delete mode 100644 dmp-frontend/src/app/models/criteria/tags/TagsCriteria.ts delete mode 100644 dmp-frontend/src/app/models/criteria/users/UserCriteria.ts delete mode 100644 dmp-frontend/src/app/models/criteria/users/UserCriteriaErrorModel.ts delete mode 100644 dmp-frontend/src/app/models/dashboard/DashboardStatisticsModel.ts delete mode 100644 dmp-frontend/src/app/models/dashboard/SearchBarItem.ts delete mode 100644 dmp-frontend/src/app/models/data-management-plan-profile/DataManagementPlanProfile.ts delete mode 100644 dmp-frontend/src/app/models/data-management-plan-profile/DataManagementPlanProfileListingModel.ts delete mode 100644 dmp-frontend/src/app/models/data-management-plan-profile/DataManagementPlanProfileModel.ts delete mode 100644 dmp-frontend/src/app/models/data-management-plan-profile/DataManagementProfileField.ts delete mode 100644 dmp-frontend/src/app/models/data-managemnt-plans/DataManagementPlanListingModel.ts delete mode 100644 dmp-frontend/src/app/models/data-managemnt-plans/DataManagementPlanModel.ts delete mode 100644 dmp-frontend/src/app/models/data-managemnt-plans/DynamicField.ts delete mode 100644 dmp-frontend/src/app/models/data-managemnt-plans/DynamicFieldDependency.ts delete mode 100644 dmp-frontend/src/app/models/data-table/ColumnOrderings.ts delete mode 100644 dmp-frontend/src/app/models/data-table/DataTableRequest.ts delete mode 100644 dmp-frontend/src/app/models/dataRepositories/DataRepositoryModel.ts delete mode 100644 dmp-frontend/src/app/models/dataset-wizard/DatasetWizardModel.ts delete mode 100644 dmp-frontend/src/app/models/datasetProfileAdmin/DatasetProfileModelAdmin.ts delete mode 100644 dmp-frontend/src/app/models/datasetProfileAdmin/DefaultValue.ts delete mode 100644 dmp-frontend/src/app/models/datasetProfileAdmin/Field.ts delete mode 100644 dmp-frontend/src/app/models/datasetProfileAdmin/FieldSet.ts delete mode 100644 dmp-frontend/src/app/models/datasetProfileAdmin/Multiplicity.ts delete mode 100644 dmp-frontend/src/app/models/datasetProfileAdmin/Page.ts delete mode 100644 dmp-frontend/src/app/models/datasetProfileAdmin/Rule.ts delete mode 100644 dmp-frontend/src/app/models/datasetProfileAdmin/Section.ts delete mode 100644 dmp-frontend/src/app/models/datasetProfileAdmin/ViewStyle.ts delete mode 100644 dmp-frontend/src/app/models/datasetProfileAdmin/Visibility.ts delete mode 100644 dmp-frontend/src/app/models/datasetprofile/DatasetProfileModel.ts delete mode 100644 dmp-frontend/src/app/models/datasets/DatasetListingModel.ts delete mode 100644 dmp-frontend/src/app/models/datasets/DatasetModel.ts delete mode 100644 dmp-frontend/src/app/models/datasets/DatasetProfileModel.ts delete mode 100644 dmp-frontend/src/app/models/datasets/DatasetWizardModel.ts delete mode 100644 dmp-frontend/src/app/models/dmpUsers/DmpUsersModel.ts delete mode 100644 dmp-frontend/src/app/models/error/BaseErrorModel.ts delete mode 100644 dmp-frontend/src/app/models/external-dataset/ExternalDatasetModel.ts delete mode 100644 dmp-frontend/src/app/models/external-sources/ExternalSourcesConfiguration.ts delete mode 100644 dmp-frontend/src/app/models/external-sources/ExternalSourcesItemModel.ts delete mode 100644 dmp-frontend/src/app/models/external-sources/ExternalSourcesUrlModel.ts delete mode 100644 dmp-frontend/src/app/models/facet-search/FacetSearchCriteriaModel.ts delete mode 100644 dmp-frontend/src/app/models/files/ContentFile.ts delete mode 100644 dmp-frontend/src/app/models/http/BaseHttpResponseModel.ts delete mode 100644 dmp-frontend/src/app/models/interfaces/FormGenerator.ts delete mode 100644 dmp-frontend/src/app/models/interfaces/Serializable.ts delete mode 100644 dmp-frontend/src/app/models/invitation/Invitation.ts delete mode 100644 dmp-frontend/src/app/models/invitation/User.ts delete mode 100644 dmp-frontend/src/app/models/login/Credential.ts delete mode 100644 dmp-frontend/src/app/models/login/LoginInfo.ts delete mode 100644 dmp-frontend/src/app/models/login/Principal.ts delete mode 100644 dmp-frontend/src/app/models/organisation/OrganisationModel.ts delete mode 100644 dmp-frontend/src/app/models/profile/ProfileModel.ts delete mode 100644 dmp-frontend/src/app/models/projects/ProjectListingModel.ts delete mode 100644 dmp-frontend/src/app/models/projects/ProjectModel.ts delete mode 100644 dmp-frontend/src/app/models/registers/RegisterModel.ts delete mode 100644 dmp-frontend/src/app/models/researcher/ResearcherModel.ts delete mode 100644 dmp-frontend/src/app/models/services/ServiceModel.ts delete mode 100644 dmp-frontend/src/app/models/tags/TagModel.ts delete mode 100644 dmp-frontend/src/app/models/users/UserErrorModel.ts delete mode 100644 dmp-frontend/src/app/models/users/UserListingModel.ts delete mode 100644 dmp-frontend/src/app/not-found.component.ts delete mode 100644 dmp-frontend/src/app/projects/editor/project-editor.component.html delete mode 100644 dmp-frontend/src/app/projects/editor/project-editor.component.scss delete mode 100644 dmp-frontend/src/app/projects/editor/project-editor.component.ts delete mode 100644 dmp-frontend/src/app/projects/listing/project-listing.component.html delete mode 100644 dmp-frontend/src/app/projects/listing/project-listing.component.scss delete mode 100644 dmp-frontend/src/app/projects/listing/project-listing.component.ts delete mode 100644 dmp-frontend/src/app/projects/project.routes.ts delete mode 100644 dmp-frontend/src/app/projects/projects.module.ts delete mode 100644 dmp-frontend/src/app/services/auth/auth.service.ts delete mode 100644 dmp-frontend/src/app/services/breadcrumb/breadcrumb-resolver.service.ts delete mode 100644 dmp-frontend/src/app/services/dashboard/dashboard.service.ts delete mode 100644 dmp-frontend/src/app/services/data-management-plan-profile/datamanagement-profile.service.ts delete mode 100644 dmp-frontend/src/app/services/data-management-plan/data-management-plan.service.ts delete mode 100644 dmp-frontend/src/app/services/datarepository/datarepository.service.ts delete mode 100644 dmp-frontend/src/app/services/dataset-profile.service.ts delete mode 100644 dmp-frontend/src/app/services/dataset-wizard/dataset-wizard.service.ts delete mode 100644 dmp-frontend/src/app/services/dataset/dataset.service.ts delete mode 100644 dmp-frontend/src/app/services/datasetProfileAdmin/datasetProfileAfmin.service.ts delete mode 100644 dmp-frontend/src/app/services/external-dataset/external-dataset.service.ts delete mode 100644 dmp-frontend/src/app/services/external-sources/external-sources-configuration.service.ts delete mode 100644 dmp-frontend/src/app/services/external-sources/external-sources.service.ts delete mode 100644 dmp-frontend/src/app/services/files/project-file-uploader.service.ts delete mode 100644 dmp-frontend/src/app/services/help-content/CachedContentItem.ts delete mode 100644 dmp-frontend/src/app/services/help-content/help-content.service.ts delete mode 100644 dmp-frontend/src/app/services/invitation/invitation.service.ts delete mode 100644 dmp-frontend/src/app/services/project/project.service.ts delete mode 100644 dmp-frontend/src/app/services/registries/registry.service.ts delete mode 100644 dmp-frontend/src/app/services/researchers/researchers.service.ts delete mode 100644 dmp-frontend/src/app/services/route-resolvers/dmp-editor-resolver.service.ts delete mode 100644 dmp-frontend/src/app/services/route-resolvers/dmp-group-resolver.service.ts delete mode 100644 dmp-frontend/src/app/services/route-resolvers/project-resolver.service.ts delete mode 100644 dmp-frontend/src/app/services/services/services-data.service.ts delete mode 100644 dmp-frontend/src/app/services/user-reference/user-reference-data.service.ts delete mode 100644 dmp-frontend/src/app/shared/components/add-researchers/add-researchers.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/auto-complete/AutoCompleteConfiguration.ts delete mode 100644 dmp-frontend/src/app/shared/components/auto-complete/auto-complete.component.html delete mode 100644 dmp-frontend/src/app/shared/components/auto-complete/auto-complete.component.scss delete mode 100644 dmp-frontend/src/app/shared/components/auto-complete/auto-complete.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/autocompletes/multiple/multiple-auto-complete-configuration.ts delete mode 100644 dmp-frontend/src/app/shared/components/autocompletes/multiple/multiple-auto-complete.component.html delete mode 100644 dmp-frontend/src/app/shared/components/autocompletes/multiple/multiple-auto-complete.component.scss delete mode 100644 dmp-frontend/src/app/shared/components/autocompletes/multiple/multiple-auto-complete.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/autocompletes/single/single-auto-complete-configuration.ts delete mode 100644 dmp-frontend/src/app/shared/components/autocompletes/single/single-auto-complete.component.html delete mode 100644 dmp-frontend/src/app/shared/components/autocompletes/single/single-auto-complete.component.scss delete mode 100644 dmp-frontend/src/app/shared/components/autocompletes/single/single-auto-complete.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/available-profiles/available-profiles.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/breadcrumb/breadcrumb.component.html delete mode 100644 dmp-frontend/src/app/shared/components/breadcrumb/breadcrumb.component.scss delete mode 100644 dmp-frontend/src/app/shared/components/breadcrumb/breadcrumb.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/breadcrumb/definition/breadcrumb-item.ts delete mode 100644 dmp-frontend/src/app/shared/components/criteria/base/base-criteria.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/criteria/data-management-plan/dmp-criteria.component.html delete mode 100644 dmp-frontend/src/app/shared/components/criteria/data-management-plan/dmp-criteria.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/criteria/datamanagementplanprofile/dmp-profile-criteria.component.html delete mode 100644 dmp-frontend/src/app/shared/components/criteria/datamanagementplanprofile/dmp-profile-criteria.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/criteria/dataset-profile/dataset-profile.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/criteria/datasets/datasets-criteria.component.html delete mode 100644 dmp-frontend/src/app/shared/components/criteria/datasets/datasets-criteria.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/criteria/projects/projects-criteria.component.html delete mode 100644 dmp-frontend/src/app/shared/components/criteria/projects/projects-criteria.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/criteria/users/users-criteria.component.html delete mode 100644 dmp-frontend/src/app/shared/components/criteria/users/users-criteria.component.scss delete mode 100644 dmp-frontend/src/app/shared/components/criteria/users/users-criteria.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/external-items/external-item-listing/external-item-listing.component.html delete mode 100644 dmp-frontend/src/app/shared/components/external-items/external-item-listing/external-item-listing.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/external-items/external-item/external-item.component.html delete mode 100644 dmp-frontend/src/app/shared/components/external-items/external-item/external-item.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/facets/facet-search-component/facet-search-section.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/facets/facet-search.component.html delete mode 100644 dmp-frontend/src/app/shared/components/facets/facet-search.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/figurecard/figurecard.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/file-uploader/FileUploader.ts delete mode 100644 dmp-frontend/src/app/shared/components/file-uploader/file-uploader.component.html delete mode 100644 dmp-frontend/src/app/shared/components/file-uploader/file-uploader.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/invitation-accepted/invitation-accepted.component.html delete mode 100644 dmp-frontend/src/app/shared/components/invitation-accepted/invitation-accepted.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/invitation/invitation.component.html delete mode 100644 dmp-frontend/src/app/shared/components/invitation/invitation.component.scss delete mode 100644 dmp-frontend/src/app/shared/components/invitation/invitation.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/navigation/navigation.component.html delete mode 100644 dmp-frontend/src/app/shared/components/navigation/navigation.component.scss delete mode 100644 dmp-frontend/src/app/shared/components/navigation/navigation.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/notificaiton/snack-bar-notification.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/search-bar/search-bar.component.html delete mode 100644 dmp-frontend/src/app/shared/components/search-bar/search-bar.component.scss delete mode 100644 dmp-frontend/src/app/shared/components/search-bar/search-bar.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/search-bar/types/search-bar-type.ts delete mode 100644 dmp-frontend/src/app/shared/components/url-listing/UrlListingItem.ts delete mode 100644 dmp-frontend/src/app/shared/components/url-listing/url-listing.component.ts delete mode 100644 dmp-frontend/src/app/shared/components/user-dialog/user-dialog.component.scss delete mode 100644 dmp-frontend/src/app/shared/components/user-dialog/user-dialog.component.ts delete mode 100644 dmp-frontend/src/app/shared/componentsAdmin/autocomplete/autocomplete-component.html delete mode 100644 dmp-frontend/src/app/shared/componentsAdmin/autocomplete/autocomplete-component.ts delete mode 100644 dmp-frontend/src/app/shared/componentsAdmin/booleanDecision/booleanDecision-component.html delete mode 100644 dmp-frontend/src/app/shared/componentsAdmin/booleanDecision/booleanDecision-component.ts delete mode 100644 dmp-frontend/src/app/shared/componentsAdmin/checkbox/checkbox-component.html delete mode 100644 dmp-frontend/src/app/shared/componentsAdmin/checkbox/checkbox-component.ts delete mode 100644 dmp-frontend/src/app/shared/componentsAdmin/combobox/combobox-component.html delete mode 100644 dmp-frontend/src/app/shared/componentsAdmin/combobox/combobox-component.ts delete mode 100644 dmp-frontend/src/app/shared/componentsAdmin/freetext/freetext-component.html delete mode 100644 dmp-frontend/src/app/shared/componentsAdmin/freetext/freetext-component.ts delete mode 100644 dmp-frontend/src/app/shared/componentsAdmin/radiobox/radiobox-component.html delete mode 100644 dmp-frontend/src/app/shared/componentsAdmin/radiobox/radiobox-component.ts delete mode 100644 dmp-frontend/src/app/shared/componentsAdmin/textarea/textarea-component.html delete mode 100644 dmp-frontend/src/app/shared/componentsAdmin/textarea/textarea-component.ts delete mode 100644 dmp-frontend/src/app/shared/componentsAdmin/wordlist/wordlist-component.html delete mode 100644 dmp-frontend/src/app/shared/componentsAdmin/wordlist/wordlist-component.scss delete mode 100644 dmp-frontend/src/app/shared/componentsAdmin/wordlist/wordlist-component.ts delete mode 100644 dmp-frontend/src/app/shared/guards/auth.guard.ts delete mode 100644 dmp-frontend/src/app/shared/help-content/help-content.component.ts delete mode 100644 dmp-frontend/src/app/shared/material/material.module.ts delete mode 100644 dmp-frontend/src/app/shared/shared.module.ts create mode 100644 dmp-frontend/src/app/ui/about/about.component.html rename dmp-frontend/src/app/{about/components => ui/about}/about.component.scss (100%) create mode 100644 dmp-frontend/src/app/ui/about/about.component.ts create mode 100644 dmp-frontend/src/app/ui/about/about.module.ts create mode 100644 dmp-frontend/src/app/ui/about/about.routing.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/default-value-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/auto-complete-field-data-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/boolean-decision-field-data-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/check-box-field-data-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/field-data-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/field-data-option-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/free-text-field-data-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/radio-box-field-data-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/text-area-field-data-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/word-list-field-data-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-set-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/multiplicity-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/page-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/rule-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/section-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/view-style-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/admin/visibility-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.routing.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.html rename dmp-frontend/src/app/{dataset-profile-form/compositefield-form/compositefield-form.component.scss => ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/auto-complete/dataset-profile-editor-auto-complete-field.component.html rename dmp-frontend/src/app/{dataset-profile-form/page-form/page-component.scss => ui/admin/dataset-profile/editor/components/field-type/auto-complete/dataset-profile-editor-auto-complete-field.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/auto-complete/dataset-profile-editor-auto-complete-field.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/boolean-decision/dataset-profile-editor-boolean-decision-field.component.html rename dmp-frontend/src/app/{dataset-profile-form/rule-component/rule.component.scss => ui/admin/dataset-profile/editor/components/field-type/boolean-decision/dataset-profile-editor-boolean-decision-field.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/boolean-decision/dataset-profile-editor-boolean-decision-field.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/checkbox/dataset-profile-editor-checkbox-field.component.html rename dmp-frontend/src/app/{shared/componentsAdmin/autocomplete/autocomplete-component.scss => ui/admin/dataset-profile/editor/components/field-type/checkbox/dataset-profile-editor-checkbox-field.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/checkbox/dataset-profile-editor-checkbox-field.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component.html rename dmp-frontend/src/app/{shared/componentsAdmin/booleanDecision/booleanDecision-component.scss => ui/admin/dataset-profile/editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/free-text/dataset-profile-editor-free-text-field.component.html rename dmp-frontend/src/app/{shared/componentsAdmin/checkbox/checkbox-component.scss => ui/admin/dataset-profile/editor/components/field-type/free-text/dataset-profile-editor-free-text-field.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/free-text/dataset-profile-editor-free-text-field.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/radio-box/dataset-profile-editor-radio-box-field.component.html rename dmp-frontend/src/app/{shared/componentsAdmin/combobox/combobox-component.scss => ui/admin/dataset-profile/editor/components/field-type/radio-box/dataset-profile-editor-radio-box-field.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/radio-box/dataset-profile-editor-radio-box-field.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/textarea/dataset-profile-editor-text-area-field.component.html rename dmp-frontend/src/app/{shared/componentsAdmin/freetext/freetext-component.scss => ui/admin/dataset-profile/editor/components/field-type/textarea/dataset-profile-editor-text-area-field.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/textarea/dataset-profile-editor-text-area-field.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/word-list/dataset-profile-editor-word-list-field.component.html rename dmp-frontend/src/app/{shared/componentsAdmin/radiobox/radiobox-component.scss => ui/admin/dataset-profile/editor/components/field-type/word-list/dataset-profile-editor-word-list-field.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/word-list/dataset-profile-editor-word-list-field.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.html rename dmp-frontend/src/app/{dataset-profile-form/field-form/field-form.component.scss => ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/page/dataset-profile-editor-page.component.html create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/page/dataset-profile-editor-page.component.scss create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/page/dataset-profile-editor-page.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/rule/dataset-profile-editor-rule.component.html rename dmp-frontend/src/app/{shared/componentsAdmin/textarea/textarea-component.scss => ui/admin/dataset-profile/editor/components/rule/dataset-profile-editor-rule.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/rule/dataset-profile-editor-rule.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component.html create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component.scss create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor-model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.html create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.scss create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts rename dmp-frontend/src/app/{shared/components/criteria/dataset-profile => ui/admin/dataset-profile/listing/criteria}/dataset-profile.component.html (100%) rename dmp-frontend/src/app/{shared/components/criteria/dataset-profile => ui/admin/dataset-profile/listing/criteria}/dataset-profile.component.scss (100%) create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.html rename dmp-frontend/src/app/{dataset-profile-form/datasets-admin-listing/dataset-profile-admin-listing.component.scss => ui/admin/dataset-profile/listing/dataset-profile-listing.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.ts rename dmp-frontend/src/app/{dataset-profile-form/previewer/dataset-profile-previewer.component.html => ui/admin/dataset-profile/preview/dataset-profile-preview.component.html} (100%) rename dmp-frontend/src/app/{dataset-profile-form/previewer/dataset-profile-previewer.component.scss => ui/admin/dataset-profile/preview/dataset-profile-preview.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/admin/dataset-profile/preview/dataset-profile-preview.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.module.ts create mode 100644 dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.routing.ts create mode 100644 dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.html create mode 100644 dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.scss create mode 100644 dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.model.ts create mode 100644 dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.html rename dmp-frontend/src/app/{shared/components/criteria/datamanagementplanprofile => ui/admin/dmp-profile/listing/criteria}/dmp-profile-criteria.component.scss (100%) create mode 100644 dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.html create mode 100644 dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.scss create mode 100644 dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/user/listing/criteria/user-criteria.component.html create mode 100644 dmp-frontend/src/app/ui/admin/user/listing/criteria/user-criteria.component.scss create mode 100644 dmp-frontend/src/app/ui/admin/user/listing/criteria/user-criteria.component.ts rename dmp-frontend/src/app/{users/components/roles => ui/admin/user/listing/role-editor}/user-role-editor.component.html (100%) rename dmp-frontend/src/app/{datasets/dataset-referenced-models-helper/datarepository/datarepository-referenced-model-helper.component.scss => ui/admin/user/listing/role-editor/user-role-editor.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/user/listing/user-listing.component.html create mode 100644 dmp-frontend/src/app/ui/admin/user/listing/user-listing.component.scss create mode 100644 dmp-frontend/src/app/ui/admin/user/listing/user-listing.component.ts create mode 100644 dmp-frontend/src/app/ui/admin/user/user.module.ts create mode 100644 dmp-frontend/src/app/ui/admin/user/user.routing.ts rename dmp-frontend/src/app/{user-management => ui/auth}/admin-login/admin-login.component.html (100%) rename dmp-frontend/src/app/{user-management => ui/auth}/admin-login/admin-login.component.scss (100%) create mode 100644 dmp-frontend/src/app/ui/auth/admin-login/admin-login.component.ts create mode 100644 dmp-frontend/src/app/ui/auth/admin-login/admin-login.module.ts create mode 100644 dmp-frontend/src/app/ui/auth/admin-login/admin-login.routing.ts rename dmp-frontend/src/app/{user-management => ui/auth}/login/b2access/b2access-login.component.html (100%) create mode 100644 dmp-frontend/src/app/ui/auth/login/b2access/b2access-login.component.ts rename dmp-frontend/src/app/{user-management => ui/auth}/login/img/b2access.png (100%) rename dmp-frontend/src/app/{user-management => ui/auth}/login/img/b2access_medium.png (100%) rename dmp-frontend/src/app/{user-management => ui/auth}/login/img/b2access_small.png (100%) rename dmp-frontend/src/app/{user-management => ui/auth}/login/linkedin-login/linkedin-login.component.html (100%) create mode 100644 dmp-frontend/src/app/ui/auth/login/linkedin-login/linkedin-login.component.ts create mode 100644 dmp-frontend/src/app/ui/auth/login/login.component.html rename dmp-frontend/src/app/{user-management => ui/auth}/login/login.component.scss (100%) create mode 100644 dmp-frontend/src/app/ui/auth/login/login.component.ts create mode 100644 dmp-frontend/src/app/ui/auth/login/login.module.ts create mode 100644 dmp-frontend/src/app/ui/auth/login/login.routing.ts rename dmp-frontend/src/app/{user-management => ui/auth}/login/twitter-login/twitter-login.component.html (100%) create mode 100644 dmp-frontend/src/app/ui/auth/login/twitter-login/twitter-login.component.ts create mode 100644 dmp-frontend/src/app/ui/auth/login/utilities/login.service.ts rename dmp-frontend/src/app/{shared/components/figurecard/figurecard.component.html => ui/dashboard/card/card.component.html} (100%) rename dmp-frontend/src/app/{shared/components/figurecard/figurecard.component.scss => ui/dashboard/card/card.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/dashboard/card/card.component.ts create mode 100644 dmp-frontend/src/app/ui/dashboard/dashboard.component.html create mode 100644 dmp-frontend/src/app/ui/dashboard/dashboard.component.scss create mode 100644 dmp-frontend/src/app/ui/dashboard/dashboard.component.ts create mode 100644 dmp-frontend/src/app/ui/dashboard/dashboard.module.ts create mode 100644 dmp-frontend/src/app/ui/dashboard/dashboard.routing.ts create mode 100644 dmp-frontend/src/app/ui/dashboard/recent-activity/recent-activity.component.html rename dmp-frontend/src/app/{users/activity => ui/dashboard/recent-activity}/recent-activity.component.scss (100%) create mode 100644 dmp-frontend/src/app/ui/dashboard/recent-activity/recent-activity.component.ts create mode 100644 dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-editor/dataset-editor.component.html create mode 100644 dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-editor/dataset-editor.component.scss create mode 100644 dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-editor/dataset-editor.component.ts create mode 100644 dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard-editor.model.ts create mode 100644 dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.html rename dmp-frontend/src/app/{datasets => ui/dataset}/dataset-wizard/dataset-wizard.component.scss (100%) create mode 100644 dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.ts create mode 100644 dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/dataset-external-references-editor.component.html create mode 100644 dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/dataset-external-references-editor.component.scss create mode 100644 dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/dataset-external-references-editor.component.ts rename dmp-frontend/src/app/{datasets/dataset-referenced-models-helper/datarepository/datarepository-referenced-model-helper.component.html => ui/dataset/dataset-wizard/external-references/editors/data-repository/dataset-external-data-repository-dialog-editor.component.html} (100%) rename dmp-frontend/src/app/{datasets/dataset-referenced-models-helper/externalDataset/externaldataset-referenced-model-helper.component.scss => ui/dataset/dataset-wizard/external-references/editors/data-repository/dataset-external-data-repository-dialog-editor.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/data-repository/dataset-external-data-repository-dialog-editor.component.ts rename dmp-frontend/src/app/{datasets/dataset-referenced-models-helper/externalDataset/externaldataset-referenced-model-helper.component.html => ui/dataset/dataset-wizard/external-references/editors/external-dataset/dataset-external-dataset-dialog-editor.component.html} (100%) rename dmp-frontend/src/app/{datasets/dataset-referenced-models-helper/registry/registry-referenced-model-helper.component.scss => ui/dataset/dataset-wizard/external-references/editors/external-dataset/dataset-external-dataset-dialog-editor.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/external-dataset/dataset-external-dataset-dialog-editor.component.ts rename dmp-frontend/src/app/{datasets/dataset-referenced-models-helper/registry/registry-referenced-model-helper.component.html => ui/dataset/dataset-wizard/external-references/editors/registry/dataset-external-registry-dialog-editor.component.html} (100%) rename dmp-frontend/src/app/{datasets/dataset-referenced-models-helper/services/services-referenced-model-helper.component.scss => ui/dataset/dataset-wizard/external-references/editors/registry/dataset-external-registry-dialog-editor.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/registry/dataset-external-registry-dialog-editor.component.ts rename dmp-frontend/src/app/{datasets/dataset-referenced-models-helper/services/services-referenced-model-helper.component.html => ui/dataset/dataset-wizard/external-references/editors/service/dataset-external-service-dialog-editor.component.html} (100%) rename dmp-frontend/src/app/{dmps/editor/dmp-finalise-dialog/dmp-finalise-dialog.component.scss => ui/dataset/dataset-wizard/external-references/editors/service/dataset-external-service-dialog-editor.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/service/dataset-external-service-dialog-editor.component.ts create mode 100644 dmp-frontend/src/app/ui/dataset/dataset.module.ts create mode 100644 dmp-frontend/src/app/ui/dataset/dataset.routing.ts create mode 100644 dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria.component.html rename dmp-frontend/src/app/{shared/components/criteria/datasets/datasets-criteria.component.scss => ui/dataset/listing/criteria/dataset-criteria.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria.component.ts create mode 100644 dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.html rename dmp-frontend/src/app/{datasets => ui/dataset}/listing/dataset-listing.component.scss (100%) create mode 100644 dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.ts create mode 100644 dmp-frontend/src/app/ui/dmp/dmp.module.ts create mode 100644 dmp-frontend/src/app/ui/dmp/dmp.routing.ts rename dmp-frontend/src/app/{shared/components/add-researchers/add-researchers.component.html => ui/dmp/editor/add-researcher/add-researcher.component.html} (100%) create mode 100644 dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.ts create mode 100644 dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.model.ts rename dmp-frontend/src/app/{shared/components => ui/dmp/editor}/available-profiles/available-profiles.component.html (100%) create mode 100644 dmp-frontend/src/app/ui/dmp/editor/available-profiles/available-profiles.component.ts create mode 100644 dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.html rename dmp-frontend/src/app/{dmps => ui/dmp}/editor/dmp-editor.component.scss (100%) create mode 100644 dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts create mode 100644 dmp-frontend/src/app/ui/dmp/editor/dmp-editor.model.ts create mode 100644 dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.html rename dmp-frontend/src/app/{dmps/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.scss => ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.ts create mode 100644 dmp-frontend/src/app/ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.html rename dmp-frontend/src/app/{dmps/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.scss => ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.ts rename dmp-frontend/src/app/{dmps => ui/dmp}/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.html (100%) rename dmp-frontend/src/app/{dmps/editor/dynamic-fields-project/dynamic-fields-project.component.scss => ui/dmp/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/dmp/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.ts rename dmp-frontend/src/app/{dmps => ui/dmp}/editor/dynamic-fields-project/dynamic-fields-project.component.html (100%) rename dmp-frontend/src/app/{form/dynamic-fields/dynamic-field-boolean-decision/dynamic-field-boolean-decision.component.css => ui/dmp/editor/dynamic-fields-project/dynamic-fields-project.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/dmp/editor/dynamic-fields-project/dynamic-fields-project.component.ts rename dmp-frontend/src/app/{form/dynamic-fields/dynamic-field-checkbox/dynamic-field-checkbox.css => ui/dmp/invitation/accepted/dmp-invitation-accepted.component.html} (100%) create mode 100644 dmp-frontend/src/app/ui/dmp/invitation/accepted/dmp-invitation-accepted.component.ts create mode 100644 dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation.component.html rename dmp-frontend/src/app/{form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.scss => ui/dmp/invitation/dmp-invitation.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation.component.ts create mode 100644 dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.html rename dmp-frontend/src/app/{shared/components/criteria/data-management-plan => ui/dmp/listing/criteria}/dmp-criteria.component.scss (100%) create mode 100644 dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.ts create mode 100644 dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.html create mode 100644 dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.scss create mode 100644 dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts create mode 100644 dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard-editor.model.ts create mode 100644 dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard.component.html rename dmp-frontend/src/app/{dmps => ui/dmp}/wizard/dmp-wizard.component.scss (100%) create mode 100644 dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard.component.ts create mode 100644 dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.html rename dmp-frontend/src/app/{dmps => ui/dmp}/wizard/editor/dmp-wizard-editor.component.scss (100%) create mode 100644 dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.ts rename dmp-frontend/src/app/{dmps/wizard/listing/dataset-wizard-listing.component.html => ui/dmp/wizard/listing/dmp-wizard-dataset-listing.component.html} (100%) rename dmp-frontend/src/app/{dmp-profiles/dmp-profile-listing/dmp-profile-listing.component.scss => ui/dmp/wizard/listing/dmp-wizard-dataset-listing.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/dmp/wizard/listing/dmp-wizard-dataset-listing.component.ts create mode 100644 dmp-frontend/src/app/ui/explore-dataset/explore-dataset-listing.component.html rename dmp-frontend/src/app/{datasets/dataset-public/dataset-public-listing.component.scss => ui/explore-dataset/explore-dataset-listing.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/explore-dataset/explore-dataset-listing.component.ts create mode 100644 dmp-frontend/src/app/ui/explore-dataset/explore-dataset.module.ts create mode 100644 dmp-frontend/src/app/ui/explore-dataset/explore-dataset.routing.ts rename dmp-frontend/src/app/{shared/components/facets/facet-search-component/facet-search-section.component.html => ui/explore-dataset/filters/explore-dataset-filter-item/explore-dataset-filter-item.component.html} (100%) rename dmp-frontend/src/app/{shared/components/facets/facet-search-component/facet-search-section.component.scss => ui/explore-dataset/filters/explore-dataset-filter-item/explore-dataset-filter-item.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filter-item/explore-dataset-filter-item.component.ts create mode 100644 dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.html rename dmp-frontend/src/app/{shared/components/facets/facet-search.component.scss => ui/explore-dataset/filters/explore-dataset-filters.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.ts create mode 100644 dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.component.html create mode 100644 dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.component.scss create mode 100644 dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.component.ts create mode 100644 dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.module.ts rename dmp-frontend/src/app/{shared/components => ui/misc}/breadcrumb/definition/IBreadCrumbComponent.ts (100%) create mode 100644 dmp-frontend/src/app/ui/misc/breadcrumb/definition/breadcrumb-item.ts create mode 100644 dmp-frontend/src/app/ui/misc/breadcrumb/service/breadcrumb.service.ts create mode 100644 dmp-frontend/src/app/ui/misc/criteria/base-criteria.component.ts create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-composite-field/form-composite-field.component.html rename dmp-frontend/src/app/{form/dynamic-form-composite-field/dynamic-form-composite-field.css => ui/misc/dataset-description-form/components/form-composite-field/form-composite-field.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-composite-field/form-composite-field.component.ts create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.html create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.scss create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.ts create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.html create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.ts create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section.component.html rename dmp-frontend/src/app/{form/dynamic-form-section/dynamic-form-section.scss => ui/misc/dataset-description-form/components/form-section/form-section.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section.component.ts create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.html rename dmp-frontend/src/app/{form/dynamic-form/dynamic-form.component.scss => ui/misc/dataset-description-form/dataset-description-form.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.ts create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.model.ts create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.module.ts rename dmp-frontend/src/app/{form => ui/misc/dataset-description-form}/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.css (100%) rename dmp-frontend/src/app/{form => ui/misc/dataset-description-form}/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.html (100%) create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.ts create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/form-focus/form-focus.service.ts create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.html rename dmp-frontend/src/app/{form/tableOfContents/table-of-content-group/table-of-content-group.component.html => ui/misc/dataset-description-form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.ts create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/mark-for-consideration/mark-for-consideration.service.ts rename dmp-frontend/src/app/{form => ui/misc/dataset-description-form}/tableOfContents/base-table-of-content.component.ts (100%) rename dmp-frontend/src/app/{form => ui/misc/dataset-description-form}/tableOfContents/table-of-content-field/table-of-content-field.component.html (100%) create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-field/table-of-content-field.component.ts rename dmp-frontend/src/app/{form => ui/misc/dataset-description-form}/tableOfContents/table-of-content-fieldset/table-of-content-fieldset.component.html (100%) create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-fieldset/table-of-content-fieldset.component.ts rename dmp-frontend/src/app/{shared/components/criteria/projects/projects-criteria.component.scss => ui/misc/dataset-description-form/tableOfContents/table-of-content-group/table-of-content-group.component.html} (100%) create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-group/table-of-content-group.component.ts rename dmp-frontend/src/app/{form => ui/misc/dataset-description-form}/tableOfContents/table-of-content-section/table-of-content-section.component.html (100%) create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-section/table-of-content-section.component.ts rename dmp-frontend/src/app/{form => ui/misc/dataset-description-form}/tableOfContents/table-of-contents.component.html (100%) create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-contents.component.ts rename dmp-frontend/src/app/{form => ui/misc/dataset-description-form}/tableOfContents/toc.component.css (100%) rename dmp-frontend/src/app/{utilities/visibility-rules/models/VisibilityRuleSource.ts => ui/misc/dataset-description-form/visibility-rules/models/visibility-rule-source.ts} (100%) create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/models/visibility-rule.ts create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/models/visibility-rules-context.ts create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/visibility-rules.service.ts create mode 100644 dmp-frontend/src/app/ui/misc/external-sources/external-sources.module.ts create mode 100644 dmp-frontend/src/app/ui/misc/external-sources/listing/external-item-listing.component.html rename dmp-frontend/src/app/{shared/components/external-items/external-item-listing => ui/misc/external-sources/listing}/external-item-listing.component.scss (100%) create mode 100644 dmp-frontend/src/app/ui/misc/external-sources/listing/external-item-listing.component.ts create mode 100644 dmp-frontend/src/app/ui/misc/help-content/help-content.component.ts create mode 100644 dmp-frontend/src/app/ui/misc/help-content/help-content.module.ts create mode 100644 dmp-frontend/src/app/ui/misc/navigation/navigation.component.html create mode 100644 dmp-frontend/src/app/ui/misc/navigation/navigation.component.scss create mode 100644 dmp-frontend/src/app/ui/misc/navigation/navigation.component.ts create mode 100644 dmp-frontend/src/app/ui/misc/navigation/navigation.module.ts rename dmp-frontend/src/app/{shared/components => ui/misc/navigation}/user-dialog/user-dialog.component.html (100%) create mode 100644 dmp-frontend/src/app/ui/misc/navigation/user-dialog/user-dialog.component.ts rename dmp-frontend/src/app/{ => ui/misc}/unauthorized/unauthorized.component.html (100%) create mode 100644 dmp-frontend/src/app/ui/misc/unauthorized/unauthorized.component.ts create mode 100644 dmp-frontend/src/app/ui/misc/unauthorized/unauthorized.module.ts create mode 100644 dmp-frontend/src/app/ui/misc/unauthorized/unauthorized.routes.ts create mode 100644 dmp-frontend/src/app/ui/project/editor/project-editor.component.html create mode 100644 dmp-frontend/src/app/ui/project/editor/project-editor.component.scss create mode 100644 dmp-frontend/src/app/ui/project/editor/project-editor.component.ts create mode 100644 dmp-frontend/src/app/ui/project/editor/project-editor.model.ts create mode 100644 dmp-frontend/src/app/ui/project/listing/criteria/project-criteria.component.html rename dmp-frontend/src/app/{shared/components/external-items/external-item/external-item.component.scss => ui/project/listing/criteria/project-criteria.component.scss} (100%) create mode 100644 dmp-frontend/src/app/ui/project/listing/criteria/project-criteria.component.ts create mode 100644 dmp-frontend/src/app/ui/project/listing/project-listing.component.html create mode 100644 dmp-frontend/src/app/ui/project/listing/project-listing.component.scss create mode 100644 dmp-frontend/src/app/ui/project/listing/project-listing.component.ts create mode 100644 dmp-frontend/src/app/ui/project/project.module.ts create mode 100644 dmp-frontend/src/app/ui/project/project.routing.ts create mode 100644 dmp-frontend/src/app/ui/user-profile/user-profile.component.html rename dmp-frontend/src/app/{users/profile => ui/user-profile}/user-profile.component.scss (100%) create mode 100644 dmp-frontend/src/app/ui/user-profile/user-profile.component.ts create mode 100644 dmp-frontend/src/app/ui/user-profile/user-profile.module.ts create mode 100644 dmp-frontend/src/app/ui/user-profile/user-profile.routing.ts delete mode 100644 dmp-frontend/src/app/unauthorized/unauthorized.component.js.map delete mode 100644 dmp-frontend/src/app/unauthorized/unauthorized.component.ts delete mode 100644 dmp-frontend/src/app/unauthorized/unauthorized.module.js.map delete mode 100644 dmp-frontend/src/app/unauthorized/unauthorized.module.ts delete mode 100644 dmp-frontend/src/app/unauthorized/unauthorized.routes.js.map delete mode 100644 dmp-frontend/src/app/unauthorized/unauthorized.routes.ts delete mode 100644 dmp-frontend/src/app/user-management/admin-login/admin-login.component.ts delete mode 100644 dmp-frontend/src/app/user-management/login.module.ts delete mode 100644 dmp-frontend/src/app/user-management/login.routes.ts delete mode 100644 dmp-frontend/src/app/user-management/login/b2access/b2access-login.component.ts delete mode 100644 dmp-frontend/src/app/user-management/login/linkedin-login/linkedin-login.component.ts delete mode 100644 dmp-frontend/src/app/user-management/login/login.component.html delete mode 100644 dmp-frontend/src/app/user-management/login/login.component.ts delete mode 100644 dmp-frontend/src/app/user-management/login/twitter-login/twitter-login.component.ts delete mode 100644 dmp-frontend/src/app/user-management/utilties/LoginOptions.ts delete mode 100644 dmp-frontend/src/app/user-management/utilties/LoginProviderConfiguration.ts delete mode 100644 dmp-frontend/src/app/user-management/utilties/LoginServiceConfiguration.ts delete mode 100644 dmp-frontend/src/app/user-management/utilties/login-service.ts delete mode 100644 dmp-frontend/src/app/users/activity/RecentActivityTypes.ts delete mode 100644 dmp-frontend/src/app/users/activity/recent-activity.component.html delete mode 100644 dmp-frontend/src/app/users/activity/recent-activity.component.ts delete mode 100644 dmp-frontend/src/app/users/components/roles/user-role-editor.component.scss delete mode 100644 dmp-frontend/src/app/users/components/roles/user-role-editor.component.ts delete mode 100644 dmp-frontend/src/app/users/components/users.component.html delete mode 100644 dmp-frontend/src/app/users/components/users.component.scss delete mode 100644 dmp-frontend/src/app/users/components/users.component.ts delete mode 100644 dmp-frontend/src/app/users/profile/user-profile.component.html delete mode 100644 dmp-frontend/src/app/users/profile/user-profile.component.ts delete mode 100644 dmp-frontend/src/app/users/users.module.ts delete mode 100644 dmp-frontend/src/app/users/users.routes.ts delete mode 100644 dmp-frontend/src/app/utilities/JsonSerializer.ts delete mode 100644 dmp-frontend/src/app/utilities/UrlUtilities.ts delete mode 100644 dmp-frontend/src/app/utilities/cite-http-service-module/base-http.service.ts delete mode 100644 dmp-frontend/src/app/utilities/cite-http-service-module/cite-http.module.ts delete mode 100644 dmp-frontend/src/app/utilities/culture/culture-service.ts delete mode 100644 dmp-frontend/src/app/utilities/culture/models/culture-info.ts delete mode 100644 dmp-frontend/src/app/utilities/culture/pipes/TimezoneInfoDisplayPipe.ts delete mode 100644 dmp-frontend/src/app/utilities/form-focus-service/form-focus.service.ts delete mode 100644 dmp-frontend/src/app/utilities/forms/FormGenerator.ts delete mode 100644 dmp-frontend/src/app/utilities/mark-for-considerations/mark-for-consideration.service.ts delete mode 100644 dmp-frontend/src/app/utilities/types/ApiResponseCode.ts delete mode 100644 dmp-frontend/src/app/utilities/utilities.ts delete mode 100644 dmp-frontend/src/app/utilities/validators/BackendErrorValidator.ts delete mode 100644 dmp-frontend/src/app/utilities/validators/ValidationContext.ts delete mode 100644 dmp-frontend/src/app/utilities/visibility-rules/models/VisibilityRule.ts delete mode 100644 dmp-frontend/src/app/utilities/visibility-rules/models/VisibilityRulesContext.ts delete mode 100644 dmp-frontend/src/app/utilities/visibility-rules/visibility-rules.service.ts delete mode 100644 dmp-frontend/src/app/welcomepage/welcomepage.component.html delete mode 100644 dmp-frontend/src/app/welcomepage/welcomepage.component.ts create mode 100644 dmp-frontend/src/assets/i18n/en.json create mode 100644 dmp-frontend/src/assets/i18n/gr.json create mode 100644 dmp-frontend/src/assets/localization/available-cultures.json diff --git a/dmp-backend/108131ae-d07a-4e8c-8f75-8c8e33fe9974.xml b/dmp-backend/108131ae-d07a-4e8c-8f75-8c8e33fe9974.xml new file mode 100644 index 000000000..b046de687 --- /dev/null +++ b/dmp-backend/108131ae-d07a-4e8c-8f75-8c8e33fe9974.xml @@ -0,0 +1 @@ +
Will you use metadata to describe the data?Will your metadata use standardised vocabularies? Will you make the metadata available free-of-charge?Will your metadata be harvestable?Will you use a naming conventions for your data?Will you provide clear version numbers for your data?Will you provide persistent identifiers for your data?Persistent identifiers Will you provide searchable metadata for your data?Will you use standardised formats for some or all of your data?Are the file formats you will use open?Please describe which data are not in an open format and why?Please describe which data are not in an open format and why? Do supported open-source tools exist for accessing the data? Please describe which data require proprietary tools to access the data? Please describe which data require proprietary tools to access the data?Will you provide metadata describing the quality of the data?
Are there ethical or legal issues that can impact sharing the data?ReasonWill all your data be openly accessible?How will the data be made available? Is the storage sufficiently secure for the data and does the storage provide backup and recovery procedures?ReasonReason Will you provide methods and tools to access the data?Will you also make auxiliary data that may be of interest to researchers available?Reason
Will you use a standard vocabulary for your data types?Will you provide a mapping to more commonly used ontologies? Will you provide a mapping to more commonly used ontologies?
When do you plan to make your data available for reuse?Please specify how long after the project has ended the data will be made available?Please describe the reason the data will not be made available.What internationally recognised licence will you use for your data?Do you have documented procedures for quality assurance of your data?Will you provide any support for data reuse?How long do you intend to support data reuse?Please specify why the data will be unsupported for reuse.
How will the cost of making your data findable, accessible, interoperable and reusable be covered?Will you identify a data manager to manage your data, if not who will be responsible for the management of your data?Identify the people or roles that will be responsible for the management of the project dataHow do you intend to ensure data reuse after your project finishes?
What do you plan to do with research data of limited usePlease describe why the data will be kept on insecure, unmanaged storage
Do you make use of other procedures for data management?Please provide links to documentation on these other procedures.
\ No newline at end of file diff --git a/dmp-backend/7b1bdf71-945e-40db-b8fb-1b2d313fbebe.xml b/dmp-backend/7b1bdf71-945e-40db-b8fb-1b2d313fbebe.xml new file mode 100644 index 000000000..14140ad44 --- /dev/null +++ b/dmp-backend/7b1bdf71-945e-40db-b8fb-1b2d313fbebe.xml @@ -0,0 +1 @@ +DMP DemodfgdfgOpenAIREplus \ No newline at end of file diff --git a/dmp-backend/be3facf6-0eb9-4668-99d6-f99215ccec1b.xml b/dmp-backend/be3facf6-0eb9-4668-99d6-f99215ccec1b.xml new file mode 100644 index 000000000..b046de687 --- /dev/null +++ b/dmp-backend/be3facf6-0eb9-4668-99d6-f99215ccec1b.xml @@ -0,0 +1 @@ +
Will you use metadata to describe the data?Will your metadata use standardised vocabularies? Will you make the metadata available free-of-charge?Will your metadata be harvestable?Will you use a naming conventions for your data?Will you provide clear version numbers for your data?Will you provide persistent identifiers for your data?Persistent identifiers Will you provide searchable metadata for your data?Will you use standardised formats for some or all of your data?Are the file formats you will use open?Please describe which data are not in an open format and why?Please describe which data are not in an open format and why? Do supported open-source tools exist for accessing the data? Please describe which data require proprietary tools to access the data? Please describe which data require proprietary tools to access the data?Will you provide metadata describing the quality of the data?
Are there ethical or legal issues that can impact sharing the data?ReasonWill all your data be openly accessible?How will the data be made available? Is the storage sufficiently secure for the data and does the storage provide backup and recovery procedures?ReasonReason Will you provide methods and tools to access the data?Will you also make auxiliary data that may be of interest to researchers available?Reason
Will you use a standard vocabulary for your data types?Will you provide a mapping to more commonly used ontologies? Will you provide a mapping to more commonly used ontologies?
When do you plan to make your data available for reuse?Please specify how long after the project has ended the data will be made available?Please describe the reason the data will not be made available.What internationally recognised licence will you use for your data?Do you have documented procedures for quality assurance of your data?Will you provide any support for data reuse?How long do you intend to support data reuse?Please specify why the data will be unsupported for reuse.
How will the cost of making your data findable, accessible, interoperable and reusable be covered?Will you identify a data manager to manage your data, if not who will be responsible for the management of your data?Identify the people or roles that will be responsible for the management of the project dataHow do you intend to ensure data reuse after your project finishes?
What do you plan to do with research data of limited usePlease describe why the data will be kept on insecure, unmanaged storage
Do you make use of other procedures for data management?Please provide links to documentation on these other procedures.
\ No newline at end of file diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/WebMVCConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/WebMVCConfiguration.java index 79607ba35..91fb7babc 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/WebMVCConfiguration.java +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/WebMVCConfiguration.java @@ -37,5 +37,4 @@ public class WebMVCConfiguration extends WebMvcConfigurerAdapter { public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new RequestInterceptor(this.apiContext.getHelpersService().getLoggerService())); } - } diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationDevelImpl.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationDevelImpl.java index 5b4f06be3..62306332c 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationDevelImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationDevelImpl.java @@ -48,7 +48,7 @@ public class DynamicProjectConfigurationDevelImpl implements DynamicProjectConfi JAXBContext jaxbContext = JAXBContext.newInstance(Configuration.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - is = new URL("file:///"+current + "/dmp-backend/web/src/main/resources/ProjectConfiguration.xml").openStream(); + is = new URL("file:///"+current + "/web/src/main/resources/ProjectConfiguration.xml").openStream(); this.configuration = (Configuration) jaxbUnmarshaller.unmarshal(is); } catch (Exception ex) { ex.printStackTrace(); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DevelConfigLoader.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DevelConfigLoader.java index 5873073e2..4af836fbd 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DevelConfigLoader.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DevelConfigLoader.java @@ -31,7 +31,7 @@ public class DevelConfigLoader implements ConfigLoader { JAXBContext jaxbContext = JAXBContext.newInstance(ExternalUrls.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - is = new URL("file:///"+current+"/dmp-backend/web/src/main/resources/ExternalUrls.xml").openStream(); + is = new URL("file:///"+current+"/web/src/main/resources/ExternalUrls.xml").openStream(); externalUrls = (ExternalUrls) jaxbUnmarshaller.unmarshal(is); } catch (Exception ex) { diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/security/validators/facebook/FacebookTokenValidator.java b/dmp-backend/web/src/main/java/eu/eudat/logic/security/validators/facebook/FacebookTokenValidator.java index ae3a733ce..cc797cec4 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/security/validators/facebook/FacebookTokenValidator.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/security/validators/facebook/FacebookTokenValidator.java @@ -47,7 +47,7 @@ public class FacebookTokenValidator implements TokenValidator { user.setEmail(profile.getEmail()); user.setId(profile.getId()); - user.setIsVerified(profile.isVerified()); + //user.setIsVerified(profile.isVerified()); user.setName(profile.getName()); user.setProvider(TokenValidatorFactoryImpl.LoginProvider.FACEBOOK); String url = (String)((Map )((Map )profile.getExtraData().get("picture")).get("data")).get("url"); diff --git a/dmp-backend/web/src/main/resources/application-devel.properties b/dmp-backend/web/src/main/resources/application-devel.properties index d48869f2f..8c13e6b1a 100644 --- a/dmp-backend/web/src/main/resources/application-devel.properties +++ b/dmp-backend/web/src/main/resources/application-devel.properties @@ -1,9 +1,9 @@ dmp.domain = http://localhost:4200 ####################PERSISTENCE OVERRIDES CONFIGURATIONS########## -database.url= -database.username= -database.password= +database.url=jdbc:postgresql://dbserver02.local.cite.gr:5432/dmptool +database.username=dmtadm +database.password=t00L4DM@18! spring.datasource.maxIdle: 2 spring.datasource.max-active: 4 spring.datasource.max-wait: 10000 diff --git a/dmp-backend/web/src/main/resources/application-production.properties b/dmp-backend/web/src/main/resources/application-production.properties index 3b9f2423d..46e81dae7 100644 --- a/dmp-backend/web/src/main/resources/application-production.properties +++ b/dmp-backend/web/src/main/resources/application-production.properties @@ -1,9 +1,9 @@ dmp.domain = https://opendmp.eu ####################PERSISTENCE OVERRIDES CONFIGURATIONS########## -database.url= -database.username= -database.password= +production.database.url=jdbc:postgresql://dl009.madgik.di.uoa.gr:5432/dmptool +production.database.username=dmpdbad +production.database.password=kWd4DmPd8@08!2 ####################ELASTIIC SEARCH TAGS OVERRIDES CONFIGURATIONS########## elasticsearch.host = tags-elastic-search @@ -22,7 +22,7 @@ configuration.h2020template=/tmp/h2020.docx ####################SPRING MAIL CONFIGURATIONS################# spring.mail.default-encoding=UTF-8 -spring.mail.host= +spring.mail.host=dit-gate.di.uoa.gr spring.mail.username= spring.mail.password= spring.mail.port=25 @@ -32,26 +32,26 @@ spring.mail.properties.mail.smtp.auth=false spring.mail.properties.mail.smtp.starttls.enable=true #############FACEBOOK LOGIN CONFIGURATIONS######### -facebook.login.clientId= -facebook.login.clientSecret= -facebook.login.namespace= +facebook.login.clientId=613977555670785 +facebook.login.clientSecret=b656eb30077454dea7b3cfd03b6e4310 +facebook.login.namespace=opendmp #############GOOGLE LOGIN CONFIGURATIONS######### -google.login.clientId= +google.login.clientId=596924546661-83nhl986pnrpug5h624i5kptuao03dcd.apps.googleusercontent.com #############LINKEDIN LOGIN CONFIGURATIONS######### -linkedin.login.clientId= -linkedin.login.clientSecret= +linkedin.login.clientId=86w8xorrsdzjud +linkedin.login.clientSecret=I9t9cjUgDNehcIIi linkedin.login.redirect_uri=https://opendmp.eu/login/linkedin #############TWITTER LOGIN CONFIGURATIONS######### -twitter.login.clientId= -twitter.login.clientSecret= +twitter.login.clientId=FBU0tH4J1wgmtJOuBOg0lKkmi +twitter.login.clientSecret=vDUUabrT8NYgAMKdA0ixWH8QQfjTqclXUPMb15LujgqBgg0Xsf twitter.login.redirect_uri=https://opendmp.eu/login/twitter #############B2 ACCESS CONFIGURATIONS######### b2access.externallogin.user_info_url=https://b2access-integration.fz-juelich.de:443/oauth2/userinfo b2access.externallogin.access_token_url=https://b2access-integration.fz-juelich.de:443/oauth2/token b2access.externallogin.redirect_uri=https://opendmp.eu/api/oauth/authorized/b2access -b2access.externallogin.clientid= -b2access.externallogin.clientSecret= \ No newline at end of file +b2access.externallogin.clientid=eudatdmptool +b2access.externallogin.clientSecret=A3b*1*92 \ No newline at end of file diff --git a/dmp-backend/web/src/main/resources/application-staging.properties b/dmp-backend/web/src/main/resources/application-staging.properties index f949b514c..15a1be7f8 100644 --- a/dmp-backend/web/src/main/resources/application-staging.properties +++ b/dmp-backend/web/src/main/resources/application-staging.properties @@ -1,9 +1,9 @@ dmp.domain = https://devel.opendmp.eu ####################PERSISTENCE OVERRIDES CONFIGURATIONS########## -database.url= -database.username= -database.password= +database.url=jdbc:postgresql://develdb1.madgik.di.uoa.gr:5432/dmptool +database.username=dmptool +database.password=dmpt00lu$r ####################ELASTIIC SEARCH TAGS OVERRIDES CONFIGURATIONS########## elasticsearch.host = tags-elastic-search @@ -22,33 +22,33 @@ configuration.h2020template=/tmp/h2020.docx ####################SPRING MAIL CONFIGURATIONS################# spring.mail.default-encoding=UTF-8 -spring.mail.host= +spring.mail.host=dit-gate.di.uoa.gr spring.mail.port=25 spring.mail.protocol=smtp spring.mail.test-connection=false spring.mail.properties.mail.smtp.auth=false #############FACEBOOK LOGIN CONFIGURATIONS######### -facebook.login.clientId= -facebook.login.clientSecret= -facebook.login.namespace= +facebook.login.clientId=613977555670785 +facebook.login.clientSecret=b656eb30077454dea7b3cfd03b6e4310 +facebook.login.namespace=opendmp #############GOOGLE LOGIN CONFIGURATIONS######### -google.login.clientId= +google.login.clientId=596924546661-83nhl986pnrpug5h624i5kptuao03dcd.apps.googleusercontent.com #############LINKEDIN LOGIN CONFIGURATIONS######### -linkedin.login.clientId= -linkedin.login.clientSecret= +linkedin.login.clientId=86w8xorrsdzjud +linkedin.login.clientSecret=I9t9cjUgDNehcIIi linkedin.login.redirect_uri=https://devel.opendmp.eu/login/linkedin #############TWITTER LOGIN CONFIGURATIONS######### -twitter.login.clientId= -twitter.login.clientSecret= +twitter.login.clientId=FBU0tH4J1wgmtJOuBOg0lKkmi +twitter.login.clientSecret=vDUUabrT8NYgAMKdA0ixWH8QQfjTqclXUPMb15LujgqBgg0Xsf twitter.login.redirect_uri=https://devel.opendmp.eu/login/twitter #############B2 ACCESS CONFIGURATIONS######### b2access.externallogin.user_info_url=https://b2access-integration.fz-juelich.de:443/oauth2/userinfo b2access.externallogin.access_token_url=https://b2access-integration.fz-juelich.de:443/oauth2/token b2access.externallogin.redirect_uri=https://devel.opendmp.eu/api/oauth/authorized/b2access -b2access.externallogin.clientid= -b2access.externallogin.clientSecret= \ No newline at end of file +b2access.externallogin.clientid=eudatdmptool +b2access.externallogin.clientSecret=A3b*1*92 \ No newline at end of file diff --git a/dmp-backend/web/src/main/resources/application.properties b/dmp-backend/web/src/main/resources/application.properties index ce1d4c41a..b1aab715d 100644 --- a/dmp-backend/web/src/main/resources/application.properties +++ b/dmp-backend/web/src/main/resources/application.properties @@ -8,15 +8,15 @@ eu.eudat.logic.proxy.allowed.host=https://eestore.paas2.uninett.no ####################INVITATION MAIL CONFIGURATIONS############## ####################GENERIC MAIL CONFIGURATIONS################# mail.subject=Invitation to DMP Plan {dmpname} -mail.from= +mail.from=citesagrdev@gmail.com ####################SPRING MAIL CONFIGURATIONS################# spring.mail.default-encoding=UTF-8 -spring.mail.host= -spring.mail.username= -spring.mail.password= -spring.mail.port= -spring.mail.protocol= +spring.mail.host=smtp.gmail.com +spring.mail.username=citesagrdev@gmail.com +spring.mail.password=w3l0v3CITe +spring.mail.port=587 +spring.mail.protocol=smtp spring.mail.test-connection=false spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true @@ -28,29 +28,29 @@ autouser.root.password=root autouser.root.username=root #############FACEBOOK LOGIN CONFIGURATIONS######### -facebook.login.clientId= -facebook.login.clientSecret= -facebook.login.namespace= +facebook.login.clientId=110586756143149 +facebook.login.clientSecret=522a847f05c873d0222c85109e24f55a +facebook.login.namespace=eudat #############GOOGLE LOGIN CONFIGURATIONS######### -google.login.clientId= +google.login.clientId=524432312250-sc9qsmtmbvlv05r44onl6l93ia3k9deo.apps.googleusercontent.com #############LINKEDIN LOGIN CONFIGURATIONS######### -linkedin.login.clientId= -linkedin.login.clientSecret= +linkedin.login.clientId=86bl8vfk77clh9 +linkedin.login.clientSecret=2OCO9e3wKylW05Tt linkedin.login.redirect_uri=http://opendmp.eu/login/linkedin #############TWITTER LOGIN CONFIGURATIONS######### -twitter.login.clientId= -twitter.login.clientSecret= +twitter.login.clientId=HiR4hQH9HNubKC5iKQy0l4mAZ +twitter.login.clientSecret=9KZHgkqUO2QFnELSL14jeUvfUacWX23rqD8OW8X0xoRDXOSfKH twitter.login.redirect_uri=http://opendmp.eu/login/twitter #############B2 ACCESS CONFIGURATIONS######### b2access.externallogin.user_info_url=https://b2access-integration.fz-juelich.de:443/oauth2/userinfo b2access.externallogin.access_token_url=https://b2access-integration.fz-juelich.de:443/oauth2/token b2access.externallogin.redirect_uri=http://opendmp.eu/api/oauth/authorized/b2access -b2access.externallogin.clientid= -b2access.externallogin.clientSecret= +b2access.externallogin.clientid=eudatdmptool +b2access.externallogin.clientSecret=A3b*1*92 #############FILE STORAGE CONFIGURATIONS######### files.storage.temp = temp diff --git a/dmp-frontend/src/app/about/about.module.ts b/dmp-frontend/src/app/about/about.module.ts deleted file mode 100644 index 3d2ee1a61..000000000 --- a/dmp-frontend/src/app/about/about.module.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { BaseHttpService } from '../utilities/cite-http-service-module/base-http.service'; -import { HttpClient, HttpClientModule } from '@angular/common/http'; -import { TranslateLoader } from '@ngx-translate/core'; -import { TranslateModule } from '@ngx-translate/core'; -import { SharedModule } from '../shared/shared.module'; -import { FormsModule } from '@angular/forms'; -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { TranslateService } from '@ngx-translate/core'; -import { TranslateHttpLoader } from '@ngx-translate/http-loader'; -import { AboutRoutes } from './about.routes'; -import { AboutComponent } from './components/about.component'; - -@NgModule({ - imports: [ - CommonModule, - FormsModule, - SharedModule, - HttpClientModule, - AboutRoutes, - TranslateModule.forRoot({ - loader: { - provide: TranslateLoader, - useFactory: HttpLoaderFactory, - deps: [HttpClient] - } - }), - ], - - declarations: [ - AboutComponent - ], - - exports: [ - AboutComponent - ], - providers: [ - BaseHttpService - ] -}) - -export class AboutModule { - constructor(private translate: TranslateService) { - translate.setDefaultLang('en'); - translate.use('en'); - } -} - -export function HttpLoaderFactory(httpClient: HttpClient) { - return new TranslateHttpLoader(httpClient, 'assets/lang/', '.json'); -} diff --git a/dmp-frontend/src/app/about/about.routes.ts b/dmp-frontend/src/app/about/about.routes.ts deleted file mode 100644 index 02fde24c3..000000000 --- a/dmp-frontend/src/app/about/about.routes.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { AboutComponent } from './components/about.component'; -import { Routes, RouterModule } from '@angular/router'; - -const routes: Routes = [ - { path: '', component: AboutComponent }, -]; - -export const AboutRoutes = RouterModule.forChild(routes); diff --git a/dmp-frontend/src/app/about/components/about.component.html b/dmp-frontend/src/app/about/components/about.component.html deleted file mode 100644 index 6636e9d49..000000000 --- a/dmp-frontend/src/app/about/components/about.component.html +++ /dev/null @@ -1,32 +0,0 @@ -
-
-
-

{{ 'ABOUT.TITLE' | translate}}

-
-
-
-
-

{{ 'ABOUT.MAIN-CONTENT'| translate}}

-
-
-
-
-

{{ 'ABOUT.CONTRIBUTORS'| translate}}

-
-
-
-
- -
-
- -
- -
- -
-
- -
-
-
\ No newline at end of file diff --git a/dmp-frontend/src/app/about/components/about.component.ts b/dmp-frontend/src/app/about/components/about.component.ts deleted file mode 100644 index 586736b5a..000000000 --- a/dmp-frontend/src/app/about/components/about.component.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Component, ViewEncapsulation, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; - -@Component({ - selector: 'app-about', - templateUrl: './about.component.html', - styleUrls: ['./about.component.scss'], - providers: [], - encapsulation: ViewEncapsulation.None -}) -export class AboutComponent implements OnInit { - - constructor() { - - } - - ngOnInit() { - } - -} - diff --git a/dmp-frontend/src/app/app-routing.module.ts b/dmp-frontend/src/app/app-routing.module.ts index c7e7d0e6f..7c8ff7c18 100644 --- a/dmp-frontend/src/app/app-routing.module.ts +++ b/dmp-frontend/src/app/app-routing.module.ts @@ -1,116 +1,103 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; -import { HomepageComponent } from './homepage/homepage.component'; -import { AuthGuard } from './shared/guards/auth.guard'; -import { WelcomepageComponent } from './welcomepage/welcomepage.component'; -import { B2AccessLoginComponent } from './user-management/login/b2access/b2access-login.component'; const appRoutes: Routes = [ - { - path: 'datasets', - loadChildren: './datasets/dataset.module#DatasetModule', - data: { - breadcrumb: true - }, - //canActivate: [AuthGuard] - }, - { - path: 'about', - loadChildren: './about/about.module#AboutModule', - data: { - breadcrumb: true - }, - canActivate: [AuthGuard] - }, - { - path: 'projects', - loadChildren: './projects/projects.module#ProjectsModule', - data: { - breadcrumb: true - }, - canActivate: [AuthGuard] - }, - { - path: 'dmps', - loadChildren: './dmps/dmps.module#DataManagementPlanModule', - data: { - breadcrumb: true - }, - canActivate: [AuthGuard] - }, - { - path: 'dmp-profiles', - loadChildren: './dmp-profiles/dmp-profile.module#DataManagamentPlanProfileModule', - data: { - breadcrumb: true - }, - canActivate: [AuthGuard] - }, - { - path: 'dataset-profile', - loadChildren: './dataset-profile-form/dataset-profile.module#DatasetProfileModule', - data: { - breadcrumb: true - }, - canActivate: [AuthGuard] - }, - { - path: 'home', - component: HomepageComponent, - data: { - breadcrumb: false - }, - canActivate: [AuthGuard] - }, { path: '', - redirectTo: '/welcome', + redirectTo: '/home', data: { breadcrumbs: false }, pathMatch: 'full' }, + { + path: 'explore', + loadChildren: './ui/explore-dataset/explore-dataset.module#ExploreDatasetModule', + data: { + breadcrumb: true + } + }, + { + path: 'datasets', + loadChildren: './ui/dataset/dataset.module#DatasetModule', + data: { + breadcrumb: true + } + }, + { + path: 'about', + loadChildren: './ui/about/about.module#AboutModule', + data: { + breadcrumb: true + } + }, + { + path: 'projects', + loadChildren: './ui/project/project.module#ProjectModule', + data: { + breadcrumb: true + } + }, + { + path: 'plans', + loadChildren: './ui/dmp/dmp.module#DmpModule', + data: { + breadcrumb: true + } + }, + { + path: 'dmp-profiles', + loadChildren: './ui/admin/dmp-profile/dmp-profile.module#DmpProfileModule', + data: { + breadcrumb: true + } + }, + { + path: 'dataset-profiles', + loadChildren: './ui/admin/dataset-profile/dataset-profile.module#DatasetProfileModule', + data: { + breadcrumb: true + } + }, + { + path: 'home', + loadChildren: './ui/dashboard/dashboard.module#DashboardModule', + data: { + breadcrumb: true + } + }, { path: 'unauthorized', - loadChildren: './unauthorized/unauthorized.module#UnauthorizedModule', + loadChildren: './ui/misc/unauthorized/unauthorized.module#UnauthorizedModule', data: { breadcrumb: true }, }, { path: 'users', - loadChildren: './users/users.module#UsersModule', + loadChildren: './ui/admin/user/user.module#UserModule', data: { breadcrumb: true }, }, { - path: 'welcome', - component: WelcomepageComponent, + path: 'login', + loadChildren: './ui/auth/login/login.module#LoginModule', data: { - breadcrumb: false + breadcrumb: true }, }, - { - path: 'api/oauth/authorized/b2access', - component: B2AccessLoginComponent, - data: { - }, - } + // { + // path: 'api/oauth/authorized/b2access', + // component: B2AccessLoginComponent, + // data: { + // }, + // } ]; @NgModule({ - imports: [ - RouterModule.forRoot( - appRoutes - , { - useHash: false - } - ) - ], - exports: [ - RouterModule - ] + imports: [RouterModule.forRoot(appRoutes)], + exports: [RouterModule], }) export class AppRoutingModule { } diff --git a/dmp-frontend/src/app/app.component.scss b/dmp-frontend/src/app/app.component.scss index 66b04b0f7..685fdd3b2 100644 --- a/dmp-frontend/src/app/app.component.scss +++ b/dmp-frontend/src/app/app.component.scss @@ -1,15 +1,12 @@ -.example-container { - background: rgb(250, 248, 248); -} - .fixed { - position: fixed; - top: 0; /* Sets the sticky toolbar to be on top */ + position: fixed; + top: 0; + /* Sets the sticky toolbar to be on top */ z-index: 1000; width: 100%; } -.main-container{ +.main-container { margin-top: 64px; padding-top: 10px; } diff --git a/dmp-frontend/src/app/app.component.ts b/dmp-frontend/src/app/app.component.ts index 90b32b12a..691f7651a 100644 --- a/dmp-frontend/src/app/app.component.ts +++ b/dmp-frontend/src/app/app.component.ts @@ -1,23 +1,20 @@ -import { Component, OnInit, ViewEncapsulation } from '@angular/core'; -import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, ActivatedRoute, NavigationExtras, NavigationEnd } from '@angular/router'; +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; -import { LanguageResolverService } from './services/language-resolver/language-resolver.service'; -import { BreadCrumbResolverService } from './services/breadcrumb/breadcrumb-resolver.service'; import { Observable } from 'rxjs'; -import { AuthService } from './services/auth/auth.service'; -import { CultureService } from './utilities/culture/culture-service'; import { environment } from '../environments/environment'; +import { AuthService } from './core/services/auth/auth.service'; +import { CultureService } from './core/services/culture/culture-service'; +import { BreadCrumbResolverService } from './ui/misc/breadcrumb/service/breadcrumb.service'; declare const gapi: any; - declare var $: any; + @Component({ selector: 'app-root', templateUrl: './app.component.html', - styleUrls: ['./app.component.scss'], - providers: [], - encapsulation: ViewEncapsulation.None + styleUrls: ['./app.component.scss'] }) export class AppComponent implements OnInit { @@ -30,7 +27,6 @@ export class AppComponent implements OnInit { private route: ActivatedRoute, private authentication: AuthService, private translate: TranslateService, - private languageService: LanguageResolverService, private breadCrumbResolverService: BreadCrumbResolverService, private cultureService: CultureService ) { @@ -68,7 +64,7 @@ export class AppComponent implements OnInit { } goToDMPs() { - this.router.navigate(['/dmps'], { queryParams: { /*refresh : Math.random() ,returnUrl: this.state.url*/ } }); + this.router.navigate(['/plans'], { queryParams: { /*refresh : Math.random() ,returnUrl: this.state.url*/ } }); } goToProjects() { diff --git a/dmp-frontend/src/app/app.module.ts b/dmp-frontend/src/app/app.module.ts index 6e548c553..2bdcd5e35 100644 --- a/dmp-frontend/src/app/app.module.ts +++ b/dmp-frontend/src/app/app.module.ts @@ -1,63 +1,36 @@ -import { CommonModule } from '@angular/common'; +import { OverlayModule } from '@angular/cdk/overlay'; import { HttpClient, HttpClientModule } from '@angular/common/http'; import { LOCALE_ID, NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { HttpModule } from '@angular/http'; -import { MAT_DATE_LOCALE } from '@angular/material'; +import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material'; +import { MatMomentDateModule, MAT_MOMENT_DATE_FORMATS } from '@angular/material-moment-adapter'; import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateHttpLoader } from '@ngx-translate/http-loader'; -import { environment } from '../environments/environment'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; -import { HomepageComponent } from './homepage/homepage.component'; -import { PageNotFoundComponent } from './not-found.component'; -import { AuthService } from './services/auth/auth.service'; -import { BreadCrumbResolverService } from './services/breadcrumb/breadcrumb-resolver.service'; -import { DashboardService } from './services/dashboard/dashboard.service'; -import { HelpContentService } from './services/help-content/help-content.service'; -import { LanguageResolverService } from './services/language-resolver/language-resolver.service'; -import { LanguageService } from './services/language/language.service'; -import { AuthGuard } from './shared/guards/auth.guard'; -import { AsideHelpContentComponent, HelpContentComponent } from './shared/help-content/help-content.component'; -import { MaterialModule } from './shared/material/material.module'; -import { SharedModule } from './shared/shared.module'; -import { LoginModule } from './user-management/login.module'; -import { B2AccessLoginComponent } from './user-management/login/b2access/b2access-login.component'; -import { LoginOptions } from './user-management/utilties/LoginOptions'; -import { RecentActivityComponent } from './users/activity/recent-activity.component'; -import { BaseHttpService } from './utilities/cite-http-service-module/base-http.service'; -import { BaseHttpModule } from './utilities/cite-http-service-module/cite-http.module'; -import { CultureService } from './utilities/culture/culture-service'; -import { UrlUtilities } from './utilities/UrlUtilities'; -import { WelcomepageComponent } from './welcomepage/welcomepage.component'; - - +import { MomentUtcDateAdapter } from './common/date/moment-utc-date-adapter'; +import { CommonHttpModule } from './common/http/common-http.module'; +import { CommonUiModule } from './common/ui/common-ui.module'; +import { CoreServiceModule } from './core/core-service.module'; +import { CultureService } from './core/services/culture/culture-service'; +import { NotificationModule } from './library/notification/notification.module'; +import { BreadcrumbModule } from './ui/misc/breadcrumb/breadcrumb.module'; +import { HelpContentModule } from './ui/misc/help-content/help-content.module'; +import { NavigationModule } from './ui/misc/navigation/navigation.module'; +// AoT requires an exported function for factories +export function HttpLoaderFactory(http: HttpClient) { + return new TranslateHttpLoader(http, 'assets/i18n/', '.json'); +} @NgModule({ - declarations: [ - AppComponent, - PageNotFoundComponent, - HomepageComponent, - RecentActivityComponent, - WelcomepageComponent, - HelpContentComponent, - AsideHelpContentComponent, - B2AccessLoginComponent, - ], imports: [ BrowserModule, - ReactiveFormsModule, - FormsModule, - HttpModule, - HttpClientModule, - BaseHttpModule.forRoot(), - - CommonModule, - AppRoutingModule, BrowserAnimationsModule, + CoreServiceModule.forRoot(), + AppRoutingModule, + CommonUiModule, TranslateModule.forRoot({ loader: { provide: TranslateLoader, @@ -65,66 +38,33 @@ import { WelcomepageComponent } from './welcomepage/welcomepage.component'; deps: [HttpClient] } }), - BrowserAnimationsModule, - MaterialModule, - SharedModule, - - LoginModule.forRoot({ - loginProviders: [ - LoginOptions.facebookOauth, - LoginOptions.googleOauth, - LoginOptions.linkedInOauth, - LoginOptions.twitterOauth, - LoginOptions.b2Access - ], - facebookConfiguration: { clientId: environment.loginProviders.facebookConfiguration.clientId }, - googleConfiguration: { clientId: environment.loginProviders.googleConfiguration.clientId }, - linkedInConfiguration: { - clientId: environment.loginProviders.linkedInConfiguration.clientId, - oauthUrl: environment.loginProviders.linkedInConfiguration.oauthUrl, - redirectUri: environment.loginProviders.linkedInConfiguration.redirectUri, - }, - twitterConfiguration: { - clientId: environment.loginProviders.twitterConfiguration.clientId, - oauthUrl: environment.loginProviders.twitterConfiguration.oauthUrl - }, - b2accessConfiguration: { - clientId: environment.loginProviders.b2accessConfiguration.clientId, - oauthUrl: environment.loginProviders.b2accessConfiguration.oauthUrl, - redirectUri: environment.loginProviders.b2accessConfiguration.redirectUri - } - }), - + HttpClientModule, + OverlayModule, + CommonHttpModule, + MatMomentDateModule, + //Ui + NotificationModule, + NavigationModule, + BreadcrumbModule, + HelpContentModule + ], + declarations: [ + AppComponent ], providers: [ - AuthGuard, - AuthService, - BaseHttpService, - UrlUtilities, - DashboardService, - HelpContentService, - LanguageService, - LanguageResolverService, - BreadCrumbResolverService, - CultureService, { provide: MAT_DATE_LOCALE, deps: [CultureService], - useFactory: (cultureService) => cultureService.getCurrentCulture() + useFactory: (cultureService) => cultureService.getCurrentCulture().name }, + { provide: MAT_DATE_FORMATS, useValue: MAT_MOMENT_DATE_FORMATS }, + { provide: DateAdapter, useClass: MomentUtcDateAdapter }, { provide: LOCALE_ID, deps: [CultureService], - useFactory: (cultureService) => cultureService.getCurrentCulture() + useFactory: (cultureService) => cultureService.getCurrentCulture().name }, ], bootstrap: [AppComponent] }) -export class AppModule { - constructor() { - } -} - -export function HttpLoaderFactory(httpClient: HttpClient) { - return new TranslateHttpLoader(httpClient, 'assets/lang/', '.json'); -} +export class AppModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/common/date/moment-utc-date-adapter.ts b/dmp-frontend/src/app/common/date/moment-utc-date-adapter.ts new file mode 100644 index 000000000..66903147f --- /dev/null +++ b/dmp-frontend/src/app/common/date/moment-utc-date-adapter.ts @@ -0,0 +1,44 @@ +import { Inject, Injectable, Optional } from '@angular/core'; +import { MAT_DATE_LOCALE } from '@angular/material'; +import { MomentDateAdapter } from '@angular/material-moment-adapter'; +import * as moment from 'moment'; +import { Moment } from 'moment'; + +@Injectable() +export class MomentUtcDateAdapter extends MomentDateAdapter { + + constructor(@Optional() @Inject(MAT_DATE_LOCALE) dateLocale: string) { + super(dateLocale); + } + + // selected from datepicker + createDate(year: number, month: number, date: number): Moment { + // Moment.js will create an invalid date if any of the components are out of bounds, but we + // explicitly check each case so we can throw more descriptive errors. + if (month < 0 || month > 11) { + throw Error(`Invalid month index "${month}". Month index has to be between 0 and 11.`); + } + + if (date < 1) { + throw Error(`Invalid date "${date}". Date has to be greater than 0.`); + } + + const result = moment.utc({ year, month, date }).locale(this.locale); + + // If the result isn't valid, the date must have been out of bounds for this month. + if (!result.isValid()) { + throw Error(`Invalid date "${date}" for month with index "${month}".`); + } + + return result; + } + + // manually writing on the textbox + parse(value: any, parseFormat: string | string[]): Moment | null { + const initialParse = super.parse(value, parseFormat); + if (!initialParse.isValid()) { return initialParse; } + + const result = moment.utc({ year: initialParse.year(), month: initialParse.month(), date: initialParse.date() }).locale(this.locale); + return result; + } +} diff --git a/dmp-frontend/src/app/common/forms/common-forms.module.ts b/dmp-frontend/src/app/common/forms/common-forms.module.ts new file mode 100644 index 000000000..13f128841 --- /dev/null +++ b/dmp-frontend/src/app/common/forms/common-forms.module.ts @@ -0,0 +1,14 @@ +import { NgModule } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; + +@NgModule({ + imports: [ + FormsModule, + ReactiveFormsModule, + ], + exports: [ + FormsModule, + ReactiveFormsModule, + ] +}) +export class CommonFormsModule { } diff --git a/dmp-frontend/src/app/common/forms/validation/custom-validator.ts b/dmp-frontend/src/app/common/forms/validation/custom-validator.ts new file mode 100644 index 000000000..ee70c8eaf --- /dev/null +++ b/dmp-frontend/src/app/common/forms/validation/custom-validator.ts @@ -0,0 +1,32 @@ +import { AbstractControl, FormGroup, ValidatorFn, Validators } from '@angular/forms'; +import { ValidationErrorModel } from './error-model/validation-error-model'; + +export function BackendErrorValidator(errorModel: ValidationErrorModel, propertyName: string): ValidatorFn { + return (control: AbstractControl): { [key: string]: any } => { + const error: String = errorModel.getError(propertyName); + return error ? { 'backendError': { message: error } } : null; + }; +} + +export function E164PhoneValidator(): ValidatorFn { + return Validators.pattern('^\\+?[1-9]\\d{1,14}$'); +} + +// Getter is required because the index of each element is not fixed (array does not always follow LIFO) +export function BackendArrayErrorValidator(errorModel: ValidationErrorModel, propertyNameGetter: () => string): ValidatorFn { + return (control: AbstractControl): { [key: string]: any } => { + const error: String = errorModel.getError(propertyNameGetter()); + return error ? { 'backendError': { message: error } } : null; + }; +} + +export function CustomErrorValidator(errorModel: ValidationErrorModel, propertyNames: string[]): ValidatorFn { + return (control: AbstractControl): { [key: string]: any } => { + const error: String = errorModel.getErrors(propertyNames); + return error ? { 'customError': { message: error } } : null; + }; +} + +export function PasswordMatchValidator(formGroup: FormGroup) { + return formGroup.get('password').value === formGroup.get('passwordConfirm').value ? null : { 'passwordMismatch': true }; +} diff --git a/dmp-frontend/src/app/common/forms/validation/error-model/validation-error-model.ts b/dmp-frontend/src/app/common/forms/validation/error-model/validation-error-model.ts new file mode 100644 index 000000000..21eec2772 --- /dev/null +++ b/dmp-frontend/src/app/common/forms/validation/error-model/validation-error-model.ts @@ -0,0 +1,90 @@ +import { Serializable } from '../../../types/json/serializable'; + +export class ValidationErrorModel implements Serializable { + public error: string; + private message: Array; + + public fromJSONObject(item: any): ValidationErrorModel { + this.error = item.error; + this.message = item.message; + return this; + } + + public getErrors(propertyNames: string[]): string { + const errors: string[] = []; + propertyNames.forEach(propertyName => { + const error = this.getError(propertyName); + if (error) { errors.push(error); } + }); + return errors.join(', '); + } + + public getError(propertyName: string): string { + let error: string; + if (this.message) { + for (const element of this.message) { + if (element.Key === propertyName) { + error = element.Value.join(', '); + break; + } + } + } + return error; + } + + // errors by array index + public getErrorForArray(arrayProperty: string, fieldProperty: string): Map { + const regExp = new RegExp(`^${arrayProperty}\\[([0-9]+)\\]\\.${fieldProperty}$`); // 1st group is index + const errors = new Map(); + if (this.message) { + this.message.forEach(element => { + const match = element.Key.match(regExp); + if (match && match.length >= 2) { + const index = Number.parseInt(match[1]); + errors.set(index, element.Value.join(', ')); + } + }); + } + return errors; + } + + public setError(propertyName: string, error: string) { + if (this.message) { + let exists = false; + for (const element of this.message) { + if (element.Key === propertyName) { + if (!element.Value.includes(error)) { element.Value.push(error); } + exists = true; + break; + } + } + if (!exists) { this.message.push({ Key: propertyName, Value: [error] }); } + } else { + this.message = [{ Key: propertyName, Value: [error] }]; + } + } + + public clear() { + this.error = undefined; + if (this.message) { + this.message.forEach(element => { + element.Value.splice(0); + }); + } + } + + public clearPart(prefix: string) { + if (this.message) { + this.message.forEach(element => { + if (element && element.Key && element.Key.startsWith(prefix)) { + element.Value.splice(0); + } + }); + } + } +} + +class ErrorMessageItem { + Key: string; + Value: Array = []; +} diff --git a/dmp-frontend/src/app/common/forms/validation/validation-context.ts b/dmp-frontend/src/app/common/forms/validation/validation-context.ts new file mode 100644 index 000000000..ab461b285 --- /dev/null +++ b/dmp-frontend/src/app/common/forms/validation/validation-context.ts @@ -0,0 +1,20 @@ +import { ValidatorFn } from '@angular/forms'; + +export class ValidationContext { + validation: Validation[] = []; + + getValidation(key: string): Validation { + for (let i = 0; i < this.validation.length; i++) { + if (this.validation[i].key === key) { + return this.validation[i]; + } + } + throw new Error('Key ' + key + ' Was Not Found In The Validation Context'); + } +} + +export class Validation { + key: string; + validators?: ValidatorFn[] = new Array(); + descendantValidations?: ValidationContext; +} diff --git a/dmp-frontend/src/app/common/http/base-http-params.ts b/dmp-frontend/src/app/common/http/base-http-params.ts new file mode 100644 index 000000000..323778da4 --- /dev/null +++ b/dmp-frontend/src/app/common/http/base-http-params.ts @@ -0,0 +1,6 @@ +import { HttpParams } from '@angular/common/http'; +import { InterceptorContext } from './interceptor-context'; + +export class BaseHttpParams extends HttpParams { + interceptorContext?: InterceptorContext; +} diff --git a/dmp-frontend/src/app/common/http/common-http.module.ts b/dmp-frontend/src/app/common/http/common-http.module.ts new file mode 100644 index 000000000..e1d4a1521 --- /dev/null +++ b/dmp-frontend/src/app/common/http/common-http.module.ts @@ -0,0 +1,54 @@ +import { HTTP_INTERCEPTORS } from '@angular/common/http'; +import { NgModule } from '@angular/core'; +import { AuthTokenInterceptor } from './interceptors/auth-token.interceptor'; +import { JsonInterceptor } from './interceptors/json.interceptor'; +import { LocaleInterceptor } from './interceptors/locale.interceptor'; +import { ProgressIndicationInterceptor } from './interceptors/progress-indication.interceptor'; +import { RequestTimingInterceptor } from './interceptors/request-timing.interceptor'; +import { ResponsePayloadInterceptor } from './interceptors/response-payload.interceptor'; +import { UnauthorizedResponseInterceptor } from './interceptors/unauthorized-response.interceptor'; + +@NgModule({ + imports: [ + ], + declarations: [ + ], + providers: [ + { + provide: HTTP_INTERCEPTORS, + useClass: AuthTokenInterceptor, + multi: true, + }, + { + provide: HTTP_INTERCEPTORS, + useClass: JsonInterceptor, + multi: true, + }, + { + provide: HTTP_INTERCEPTORS, + useClass: LocaleInterceptor, + multi: true, + }, + { + provide: HTTP_INTERCEPTORS, + useClass: UnauthorizedResponseInterceptor, + multi: true, + }, + { + provide: HTTP_INTERCEPTORS, + useClass: RequestTimingInterceptor, + multi: true, + }, + { + provide: HTTP_INTERCEPTORS, + useClass: ProgressIndicationInterceptor, + multi: true, + }, + { + provide: HTTP_INTERCEPTORS, + useClass: ResponsePayloadInterceptor, + multi: true, + } + ] +}) +export class CommonHttpModule { } diff --git a/dmp-frontend/src/app/common/http/interceptor-context.ts b/dmp-frontend/src/app/common/http/interceptor-context.ts new file mode 100644 index 000000000..5617fd847 --- /dev/null +++ b/dmp-frontend/src/app/common/http/interceptor-context.ts @@ -0,0 +1,10 @@ +import { InterceptorType } from './interceptors/interceptor-type'; + +export class InterceptorContext { + + // If an Interceptor is added here, it wont be used in this request context. + excludedInterceptors?: InterceptorType[] = []; + // If an Interceptor is added here, all requests including requests to external systems will be intercepted. + // By default only requests to the web application's services will be intercepted. + interceptAllRequests?: InterceptorType[] = []; +} diff --git a/dmp-frontend/src/app/common/http/interceptors/auth-token.interceptor.ts b/dmp-frontend/src/app/common/http/interceptors/auth-token.interceptor.ts new file mode 100644 index 000000000..3f37fd4ba --- /dev/null +++ b/dmp-frontend/src/app/common/http/interceptors/auth-token.interceptor.ts @@ -0,0 +1,26 @@ +import { HttpEvent, HttpHandler, HttpRequest } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { BaseInterceptor } from './base.interceptor'; +import { InterceptorType } from './interceptor-type'; +import { AuthService } from '../../../core/services/auth/auth.service'; + +@Injectable() +export class AuthTokenInterceptor extends BaseInterceptor { + + constructor( + private authService: AuthService) { super(); } + + get type(): InterceptorType { return InterceptorType.AuthToken; } + + interceptRequest(req: HttpRequest, next: HttpHandler): Observable> { + const authToken: string = this.authService.current() ? this.authService.current().token : null; + if (!authToken) { return next.handle(req); } + req = req.clone({ + setHeaders: { + AuthToken: authToken + } + }); + return next.handle(req); + } +} diff --git a/dmp-frontend/src/app/common/http/interceptors/base.interceptor.ts b/dmp-frontend/src/app/common/http/interceptors/base.interceptor.ts new file mode 100644 index 000000000..7918c5f0a --- /dev/null +++ b/dmp-frontend/src/app/common/http/interceptors/base.interceptor.ts @@ -0,0 +1,30 @@ +import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { BaseHttpParams } from '../base-http-params'; +import { InterceptorType } from './interceptor-type'; +import { environment } from '../../../../environments/environment'; + +export abstract class BaseInterceptor implements HttpInterceptor { + + constructor() { } + + abstract type: InterceptorType; + abstract interceptRequest(req: HttpRequest, next: HttpHandler): Observable>; + + intercept(req: HttpRequest, next: HttpHandler): Observable> { + if (this.isApplied(req)) { + return this.interceptRequest(req, next); + } + return next.handle(req); + } + + isApplied(req: HttpRequest): boolean { + + if (req.params instanceof BaseHttpParams && req.params.interceptorContext && Array.isArray(req.params.interceptorContext.excludedInterceptors) && req.params.interceptorContext.excludedInterceptors.includes(this.type)) { + return false; + } + + return (req.params instanceof BaseHttpParams && req.params.interceptorContext && Array.isArray(req.params.interceptorContext.interceptAllRequests) && req.params.interceptorContext.interceptAllRequests.includes(this.type)) + || req.url.startsWith(environment.Server); + } +} diff --git a/dmp-frontend/src/app/common/http/interceptors/interceptor-type.ts b/dmp-frontend/src/app/common/http/interceptors/interceptor-type.ts new file mode 100644 index 000000000..bba2dea1c --- /dev/null +++ b/dmp-frontend/src/app/common/http/interceptors/interceptor-type.ts @@ -0,0 +1,9 @@ +export enum InterceptorType { + AuthToken = 0, + JSONContentType = 1, + Locale = 2, + ProgressIndication = 3, + RequestTiming = 4, + UnauthorizedResponse = 5, + ResponsePayload = 5, +} diff --git a/dmp-frontend/src/app/common/http/interceptors/json.interceptor.ts b/dmp-frontend/src/app/common/http/interceptors/json.interceptor.ts new file mode 100644 index 000000000..c5bdfb4f0 --- /dev/null +++ b/dmp-frontend/src/app/common/http/interceptors/json.interceptor.ts @@ -0,0 +1,22 @@ +import { HttpEvent, HttpHandler, HttpRequest } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { BaseInterceptor } from './base.interceptor'; +import { InterceptorType } from './interceptor-type'; + +@Injectable() +export class JsonInterceptor extends BaseInterceptor { + + constructor( + ) { super(); } + + get type(): InterceptorType { return InterceptorType.JSONContentType; } + + interceptRequest(req: HttpRequest, next: HttpHandler): Observable> { + if (!req.headers.has('Content-Type')) { req = req.clone({ headers: req.headers.set('Content-Type', 'application/json') }); } + if (!req.headers.has('Accept')) { req = req.clone({ headers: req.headers.set('Accept', 'application/json') }); } + + return next.handle(req); + } + +} diff --git a/dmp-frontend/src/app/common/http/interceptors/locale.interceptor.ts b/dmp-frontend/src/app/common/http/interceptors/locale.interceptor.ts new file mode 100644 index 000000000..5df39499a --- /dev/null +++ b/dmp-frontend/src/app/common/http/interceptors/locale.interceptor.ts @@ -0,0 +1,20 @@ +import { HttpEvent, HttpHandler, HttpRequest } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { BaseInterceptor } from './base.interceptor'; +import { InterceptorType } from './interceptor-type'; + +@Injectable() +export class LocaleInterceptor extends BaseInterceptor { + + constructor( + private language: TranslateService) { super(); } + + get type(): InterceptorType { return InterceptorType.Locale; } + + interceptRequest(req: HttpRequest, next: HttpHandler): Observable> { + if (this.language.currentLang) { req = req.clone({ headers: req.headers.set('Accept-Language', this.language.currentLang) }); } + return next.handle(req); + } +} diff --git a/dmp-frontend/src/app/common/http/interceptors/progress-indication.interceptor.ts b/dmp-frontend/src/app/common/http/interceptors/progress-indication.interceptor.ts new file mode 100644 index 000000000..c472b1e12 --- /dev/null +++ b/dmp-frontend/src/app/common/http/interceptors/progress-indication.interceptor.ts @@ -0,0 +1,25 @@ +import { HttpEvent, HttpHandler, HttpRequest } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { finalize } from 'rxjs/operators'; +import { ProgressIndicationService } from '../../../core/services/progress-indication/progress-indication-service'; +import { BaseInterceptor } from './base.interceptor'; +import { InterceptorType } from './interceptor-type'; + +@Injectable() +export class ProgressIndicationInterceptor extends BaseInterceptor { + + constructor( + private progressIndicationService: ProgressIndicationService) { super(); } + + get type(): InterceptorType { return InterceptorType.ProgressIndication; } + + interceptRequest(req: HttpRequest, next: HttpHandler): Observable> { + this.progressIndicationService.show(); + return next + .handle(req).pipe( + finalize(() => { + this.progressIndicationService.dismiss(); + })); + } +} diff --git a/dmp-frontend/src/app/common/http/interceptors/request-timing.interceptor.ts b/dmp-frontend/src/app/common/http/interceptors/request-timing.interceptor.ts new file mode 100644 index 000000000..869674c69 --- /dev/null +++ b/dmp-frontend/src/app/common/http/interceptors/request-timing.interceptor.ts @@ -0,0 +1,32 @@ +import { HttpEvent, HttpHandler, HttpRequest, HttpResponse } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { tap } from 'rxjs/operators'; +import { LoggingService } from '../../../core/services/logging/logging-service'; +import { BaseInterceptor } from './base.interceptor'; +import { InterceptorType } from './interceptor-type'; + +@Injectable() +export class RequestTimingInterceptor extends BaseInterceptor { + + constructor( + private logger: LoggingService) { super(); } + + get type(): InterceptorType { return InterceptorType.RequestTiming; } + + interceptRequest(req: HttpRequest, next: HttpHandler): Observable> { + const started = Date.now(); + return next + .handle(req).pipe( + tap(event => { + if (event instanceof HttpResponse) { + const elapsed = Date.now() - started; + if (req.method === 'POST') { + this.logger.info(`POST Request at ${req.url} with params: ${req.serializeBody()} took ${elapsed} ms.`); + } else { + this.logger.info(`${req.method} Request at ${req.urlWithParams} took ${elapsed} ms.`); + } + } + })); + } +} diff --git a/dmp-frontend/src/app/common/http/interceptors/response-payload.interceptor.ts b/dmp-frontend/src/app/common/http/interceptors/response-payload.interceptor.ts new file mode 100644 index 000000000..125ac38ce --- /dev/null +++ b/dmp-frontend/src/app/common/http/interceptors/response-payload.interceptor.ts @@ -0,0 +1,41 @@ +import { HttpHandler, HttpHeaderResponse, HttpProgressEvent, HttpRequest, HttpResponse, HttpSentEvent, HttpUserEvent } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { MatSnackBar } from '@angular/material'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { BaseInterceptor } from './base.interceptor'; +import { InterceptorType } from './interceptor-type'; + +@Injectable() +export class ResponsePayloadInterceptor extends BaseInterceptor { + + constructor( + private snackBar: MatSnackBar + ) { super(); } + + get type(): InterceptorType { return InterceptorType.ResponsePayload; } + + interceptRequest(req: HttpRequest, next: HttpHandler): Observable | HttpUserEvent> { + + return next.handle(req).pipe( + map(response => { + // if (!(response instanceof HttpResponse) || (response instanceof Blob)) { return response; } + // if (response.status == 200) { + // if (response.body.statusCode === ApiMessageCode.SUCCESS_MESSAGE) { + // //throw new Error('Request failed'); + // // this.snackBar.openFromComponent(SnackBarNotificationComponent, { + // // data: { message: response['message'], language: null }, + // // duration: 3000, + // // }); + // return response.body.payload; + + // } else if (response.body.statusCode === ApiMessageCode.NO_MESSAGE) { + // return response.body.payload; + // } else { + // return response.body.payload; + // } + // } + return response; + })); + } +} diff --git a/dmp-frontend/src/app/common/http/interceptors/unauthorized-response.interceptor.ts b/dmp-frontend/src/app/common/http/interceptors/unauthorized-response.interceptor.ts new file mode 100644 index 000000000..612743c1f --- /dev/null +++ b/dmp-frontend/src/app/common/http/interceptors/unauthorized-response.interceptor.ts @@ -0,0 +1,75 @@ +import { HttpErrorResponse, HttpHandler, HttpHeaderResponse, HttpProgressEvent, HttpRequest, HttpResponse, HttpSentEvent, HttpUserEvent } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Router } from '@angular/router'; +import { Observable, throwError } from 'rxjs'; +import { catchError, mergeMap, tap } from 'rxjs/operators'; +import { AuthService } from '../../../core/services/auth/auth.service'; +import { BaseInterceptor } from './base.interceptor'; +import { InterceptorType } from './interceptor-type'; + +@Injectable() +export class UnauthorizedResponseInterceptor extends BaseInterceptor { + + constructor( + public router: Router, + private authService: AuthService, + ) { super(); } + + get type(): InterceptorType { return InterceptorType.UnauthorizedResponse; } + + private accountRefresh$: Observable = null; + + interceptRequest(req: HttpRequest, next: HttpHandler): Observable | HttpUserEvent> { + return next.handle(req).pipe( + catchError(error => { + if (error instanceof HttpErrorResponse) { + switch ((error).status) { + case 401: + return this.handle401Error(req, next); + default: + return throwError(error); + } + } else { + return throwError(error); + } + })); + } + + private handle401Error(req: HttpRequest, next: HttpHandler) { + if (!this.accountRefresh$) { + // this.accountRefresh$ = this.idpService.refreshToken().pipe( + // tap(account => { + // this.accountRefresh$ = null; + // if (!account) { throw throwError('missing_authentication_token'); } + // }), + // catchError(error => { + // this.logoutUser(); + // return throwError(error); + // })); + } + return this.accountRefresh$.pipe(mergeMap(account => this.repeatRequest(account, req, next))); + } + + private repeatRequest(account: Account, originalRequest: HttpRequest, next: HttpHandler) { + const newAuthenticationToken: String = this.authService.current().token; + const newRequest = originalRequest.clone({ + setHeaders: { + Authorization: `Bearer ${newAuthenticationToken}` + } + }); + return next.handle(newRequest); + } + + private logoutUser() { + //this.authService.clear(); + if (!this.isLoginRoute() && !this.isSignupRoute()) { this.router.navigate(['/unauthorized']); } + } + + private isLoginRoute(): boolean { + return this.router.isActive('login', false); + } + + private isSignupRoute(): boolean { + return this.router.isActive('signup-register', false) || this.router.isActive('signup-invitation', false); + } +} diff --git a/dmp-frontend/src/app/common/material/material.module.ts b/dmp-frontend/src/app/common/material/material.module.ts new file mode 100644 index 000000000..909d1ea8e --- /dev/null +++ b/dmp-frontend/src/app/common/material/material.module.ts @@ -0,0 +1,107 @@ +import { NgModule } from '@angular/core'; +import { + MatButtonModule, + MatToolbarModule, + MatIconModule, + MatCardModule, + MatGridListModule, + MatSnackBarModule, + MatSidenavModule, + MatListModule, + MatChipsModule, + MatFormFieldModule, + MatSelectModule, + MatOptionModule, + MatInputModule, + MatExpansionModule, + MatAutocompleteModule, + MatProgressSpinnerModule, + MatTabsModule, + MatDialogModule, + MatMenuModule, + MatRadioModule, + MatStepperModule, + MatTooltipModule, + MatProgressBarModule, + MatCheckboxModule, + MatDatepickerModule, + MatButtonToggleModule, + MatSliderModule, + MatSlideToggleModule, + MatTableModule, + MatPaginatorModule, + MatSortModule, +} from '@angular/material'; +import { CdkTableModule } from '@angular/cdk/table'; + +@NgModule({ + imports: [ + MatToolbarModule, + MatButtonModule, + MatIconModule, + MatCardModule, + MatGridListModule, + MatSnackBarModule, + MatSidenavModule, + MatListModule, + MatChipsModule, + MatFormFieldModule, + MatSelectModule, + MatOptionModule, + MatInputModule, + MatExpansionModule, + MatAutocompleteModule, + MatProgressSpinnerModule, + MatProgressBarModule, + MatTabsModule, + MatDialogModule, + MatMenuModule, + MatRadioModule, + MatStepperModule, + MatTooltipModule, + MatCheckboxModule, + MatDatepickerModule, + MatButtonToggleModule, + MatSliderModule, + MatSlideToggleModule, + MatTableModule, + MatPaginatorModule, + CdkTableModule, + MatSortModule, + ], + exports: [ + MatToolbarModule, + MatButtonModule, + MatIconModule, + MatCardModule, + MatGridListModule, + MatSnackBarModule, + MatSidenavModule, + MatListModule, + MatChipsModule, + MatFormFieldModule, + MatSelectModule, + MatOptionModule, + MatInputModule, + MatExpansionModule, + MatAutocompleteModule, + MatProgressSpinnerModule, + MatProgressBarModule, + MatTabsModule, + MatDialogModule, + MatMenuModule, + MatRadioModule, + MatStepperModule, + MatTooltipModule, + MatCheckboxModule, + MatDatepickerModule, + MatButtonToggleModule, + MatSliderModule, + MatSlideToggleModule, + MatTableModule, + MatPaginatorModule, + CdkTableModule, + MatSortModule, + ] +}) +export class MaterialModule { } diff --git a/dmp-frontend/src/app/common/types/guid.ts b/dmp-frontend/src/app/common/types/guid.ts new file mode 100644 index 000000000..8d1d67670 --- /dev/null +++ b/dmp-frontend/src/app/common/types/guid.ts @@ -0,0 +1,66 @@ +export class Guid { + + private constructor(guid: string) { + if (!guid) { throw new TypeError('Invalid argument; `value` has no value.'); } + + this.value = Guid.EMPTY; + + if (guid && Guid.isGuid(guid)) { + this.value = guid; + } + } + + public static validator = new RegExp('^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$', 'i'); + + public static EMPTY = '00000000-0000-0000-0000-000000000000'; + + private value: string; + + public static isGuid(guid: any) { + const value: string = guid.toString(); + return guid && (guid instanceof Guid || Guid.validator.test(value)); + } + + public static create(): Guid { + return new Guid([Guid.gen(2), Guid.gen(1), Guid.gen(1), Guid.gen(1), Guid.gen(3)].join('-')); + } + + public static createEmpty(): Guid { + return new Guid('emptyguid'); + } + + public static parse(guid: string): Guid { + return new Guid(guid); + } + + public static raw(): string { + return [Guid.gen(2), Guid.gen(1), Guid.gen(1), Guid.gen(1), Guid.gen(3)].join('-'); + } + + private static gen(count: number) { + let out = ''; + for (let i = 0; i < count; i++) { + // tslint:disable-next-line:no-bitwise + out += (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); + } + return out; + } + + public equals(other: Guid): boolean { + // Comparing string `value` against provided `guid` will auto-call + // toString on `guid` for comparison + return Guid.isGuid(other) && this.value === other.toString(); + } + + public isEmpty(): boolean { + return this.value === Guid.EMPTY; + } + + public toString(): string { + return this.value; + } + + public toJSON(): any { + return this.value; + } +} diff --git a/dmp-frontend/src/app/common/types/json/json-serializer.ts b/dmp-frontend/src/app/common/types/json/json-serializer.ts new file mode 100644 index 000000000..775a9c2de --- /dev/null +++ b/dmp-frontend/src/app/common/types/json/json-serializer.ts @@ -0,0 +1,14 @@ +import { Serializable } from './serializable'; + +export class JsonSerializer> { + constructor(private constructorOfT: { new(): T }) { + } + + public fromJSONArray(items: any[]): T[] { + return items.map(x => this.fromJSONObject(x)); + } + + public fromJSONObject(item: any): T { + return new this.constructorOfT().fromJSONObject(item); + } +} diff --git a/dmp-frontend/src/app/models/Serializable.ts b/dmp-frontend/src/app/common/types/json/serializable.ts similarity index 100% rename from dmp-frontend/src/app/models/Serializable.ts rename to dmp-frontend/src/app/common/types/json/serializable.ts diff --git a/dmp-frontend/src/app/models/helpers/Pair.ts b/dmp-frontend/src/app/common/types/pair.ts similarity index 100% rename from dmp-frontend/src/app/models/helpers/Pair.ts rename to dmp-frontend/src/app/common/types/pair.ts diff --git a/dmp-frontend/src/app/common/ui/common-ui.module.ts b/dmp-frontend/src/app/common/ui/common-ui.module.ts new file mode 100644 index 000000000..124c9957a --- /dev/null +++ b/dmp-frontend/src/app/common/ui/common-ui.module.ts @@ -0,0 +1,18 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { TranslateModule } from '@ngx-translate/core'; +import { MaterialModule } from '../material/material.module'; + +@NgModule({ + imports: [ + CommonModule, + MaterialModule, + TranslateModule + ], + exports: [ + CommonModule, + MaterialModule, + TranslateModule + ] +}) +export class CommonUiModule { } diff --git a/dmp-frontend/src/app/core/auth-guard.service.ts b/dmp-frontend/src/app/core/auth-guard.service.ts new file mode 100644 index 000000000..c9e179e49 --- /dev/null +++ b/dmp-frontend/src/app/core/auth-guard.service.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, CanActivate, CanLoad, Route, Router, RouterStateSnapshot } from '@angular/router'; +import { AuthService } from './services/auth/auth.service'; + +@Injectable() +export class AuthGuard implements CanActivate, CanLoad { + constructor(private auth: AuthService, private router: Router) { + } + + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { + const url: string = state.url; + if (!this.auth.current()) { + this.router.navigate(['/unauthorized'], { queryParams: { returnUrl: url } }); + return false; + } + return true; + } + + canLoad(route: Route): boolean { + const url = `/${route.path}`; + if (!this.auth.current()) { + this.router.navigate(['/unauthorized'], { queryParams: { returnUrl: url } }); + return false; + } + return true; + } +} diff --git a/dmp-frontend/src/app/utilities/types/ApiMessageCode.ts b/dmp-frontend/src/app/core/common/enum/api-message-code.ts similarity index 100% rename from dmp-frontend/src/app/utilities/types/ApiMessageCode.ts rename to dmp-frontend/src/app/core/common/enum/api-message-code.ts diff --git a/dmp-frontend/src/app/core/common/enum/app-role.ts b/dmp-frontend/src/app/core/common/enum/app-role.ts new file mode 100644 index 000000000..944067e78 --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/app-role.ts @@ -0,0 +1,5 @@ +export enum AppRole { + Admin = 2, + Manager = 1, + User = 0, +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/common/enum/auth-provider.ts b/dmp-frontend/src/app/core/common/enum/auth-provider.ts new file mode 100644 index 000000000..a6e87c9a1 --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/auth-provider.ts @@ -0,0 +1,7 @@ +export enum AuthProvider { + LinkedIn = 1, + Facebook = 2, + Twitter = 3, + Google = 4, + B2Access = 5 +} diff --git a/dmp-frontend/src/app/core/common/enum/dataset-profile-combo-box-type.ts b/dmp-frontend/src/app/core/common/enum/dataset-profile-combo-box-type.ts new file mode 100644 index 000000000..ba4b9afe2 --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/dataset-profile-combo-box-type.ts @@ -0,0 +1,4 @@ +export enum DatasetProfileComboBoxType { + Autocomplete = "autocomplete", + WordList = "wordlist" +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/common/enum/dataset-profile-field-view-style.ts b/dmp-frontend/src/app/core/common/enum/dataset-profile-field-view-style.ts new file mode 100644 index 000000000..318810246 --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/dataset-profile-field-view-style.ts @@ -0,0 +1,8 @@ +export enum DatasetProfileFieldViewStyle { + TextArea = "textarea", + BooleanDecision = "booleanDecision", + ComboBox = "combobox", + CheckBox = "checkBox", + FreeText = "freetext", + RadioBox = "radiobox" +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/common/enum/dataset-status.ts b/dmp-frontend/src/app/core/common/enum/dataset-status.ts new file mode 100644 index 000000000..7719a08e5 --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/dataset-status.ts @@ -0,0 +1,5 @@ +export enum DatasetStatus { + Draft = 0, + Finalized = 1, + Deleted = 99 +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/common/enum/dmp-profile-field-type.ts b/dmp-frontend/src/app/core/common/enum/dmp-profile-field-type.ts new file mode 100644 index 000000000..e8c4a27d2 --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/dmp-profile-field-type.ts @@ -0,0 +1,5 @@ +export enum DmpProfileFieldDataType { + Date = 0, + Number = 1, + Text = 2 +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/common/enum/dmp-profile-type.ts b/dmp-frontend/src/app/core/common/enum/dmp-profile-type.ts new file mode 100644 index 000000000..33ba71e7a --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/dmp-profile-type.ts @@ -0,0 +1,3 @@ +export enum DmpProfileType { + Input = 0 +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/common/enum/dmp-status.ts b/dmp-frontend/src/app/core/common/enum/dmp-status.ts new file mode 100644 index 000000000..d96227198 --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/dmp-status.ts @@ -0,0 +1,5 @@ +export enum DmpStatus { + Draft = 0, + Finalized = 1, + Deleted = 99 +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/common/enum/external-dataset-type.ts b/dmp-frontend/src/app/core/common/enum/external-dataset-type.ts new file mode 100644 index 000000000..5d990dda2 --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/external-dataset-type.ts @@ -0,0 +1,4 @@ +export enum ExternalDatasetType { + Source = 0, + Output = 1 +} \ No newline at end of file diff --git a/dmp-frontend/src/app/models/projects/ProjectStateType.ts b/dmp-frontend/src/app/core/common/enum/project-state-type.ts similarity index 100% rename from dmp-frontend/src/app/models/projects/ProjectStateType.ts rename to dmp-frontend/src/app/core/common/enum/project-state-type.ts diff --git a/dmp-frontend/src/app/core/common/enum/project-type.ts b/dmp-frontend/src/app/core/common/enum/project-type.ts new file mode 100644 index 000000000..4f26ba5dc --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/project-type.ts @@ -0,0 +1,4 @@ +export enum ProjectType { + External = 0, + Internal = 1 +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/common/enum/recent-activity-type.ts b/dmp-frontend/src/app/core/common/enum/recent-activity-type.ts new file mode 100644 index 000000000..30914a9e5 --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/recent-activity-type.ts @@ -0,0 +1,5 @@ +export enum RecentActivityType { + Project = 0, + Dataset = 1, + Dmp = 2 +} diff --git a/dmp-frontend/src/app/models/Status.ts b/dmp-frontend/src/app/core/common/enum/status.ts similarity index 100% rename from dmp-frontend/src/app/models/Status.ts rename to dmp-frontend/src/app/core/common/enum/status.ts diff --git a/dmp-frontend/src/app/core/common/enum/validation-type.ts b/dmp-frontend/src/app/core/common/enum/validation-type.ts new file mode 100644 index 000000000..f7ded1fba --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/validation-type.ts @@ -0,0 +1,4 @@ +export enum ValidationType { + None = 0, + Required = 1 +} diff --git a/dmp-frontend/src/app/core/core-service.module.ts b/dmp-frontend/src/app/core/core-service.module.ts new file mode 100644 index 000000000..a6f52f455 --- /dev/null +++ b/dmp-frontend/src/app/core/core-service.module.ts @@ -0,0 +1,86 @@ +import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core'; +import { CookieService } from 'ngx-cookie-service'; +import { LanguageResolverService } from '../services/language-resolver/language-resolver.service'; +import { LanguageService } from '../services/language/language.service'; +import { AuthGuard } from './auth-guard.service'; +import { AuthService } from './services/auth/auth.service'; +import { CultureService } from './services/culture/culture-service'; +import { DashboardService } from './services/dashboard/dashboard.service'; +import { DatasetProfileService } from './services/dataset-profile/dataset-profile.service'; +import { DatasetWizardService } from './services/dataset-wizard/dataset-wizard.service'; +import { DatasetService } from './services/dataset/dataset.service'; +import { DmpInvitationService } from './services/dmp/dmp-invitation.service'; +import { DmpProfileService } from './services/dmp/dmp-profile.service'; +import { DmpService } from './services/dmp/dmp.service'; +import { ExternalDataRepositoryService } from './services/external-sources/data-repository/extternal-data-repository.service'; +import { ExternalDatasetService } from './services/external-sources/dataset/external-dataset.service'; +import { ExternalSourcesConfigurationService } from './services/external-sources/external-sources-configuration.service'; +import { ExternalSourcesService } from './services/external-sources/external-sources.service'; +import { ExternalRegistryService } from './services/external-sources/registry/external-registry.service'; +import { ExternalResearcherService } from './services/external-sources/researcher/external-researcher.service'; +import { ExternalServiceService } from './services/external-sources/service/external-service.service'; +import { BaseHttpService } from './services/http/base-http.service'; +import { LoggingService } from './services/logging/logging-service'; +import { UiNotificationService } from './services/notification/ui-notification-service'; +import { ProgressIndicationService } from './services/progress-indication/progress-indication-service'; +import { ProjectFileUploadService } from './services/project/project-file-upload.service'; +import { ProjectService } from './services/project/project.service'; +import { SearchBarService } from './services/search-bar/search-bar.service'; +import { TimezoneService } from './services/timezone/timezone-service'; +import { UserService } from './services/user/user.service'; +import { CollectionUtils } from './services/utilities/collection-utils.service'; +import { TypeUtils } from './services/utilities/type-utils.service'; +// +// +// This is shared module that provides all the services. Its imported only once on the AppModule. +// +// + +@NgModule({ +}) +export class CoreServiceModule { + constructor(@Optional() @SkipSelf() parentModule: CoreServiceModule) { + if (parentModule) { + throw new Error( + 'CoreModule is already loaded. Import it in the AppModule only'); + } + } + static forRoot(): ModuleWithProviders { + return { + ngModule: CoreServiceModule, + providers: [ + AuthService, + CookieService, + BaseHttpService, + AuthGuard, + LanguageService, + CultureService, + TimezoneService, + TypeUtils, + CollectionUtils, + UiNotificationService, + ProgressIndicationService, + LoggingService, + SearchBarService, + DashboardService, + LanguageResolverService, + ProjectService, + ProjectFileUploadService, + DmpService, + DmpProfileService, + ExternalSourcesService, + ExternalSourcesConfigurationService, + DatasetService, + DatasetWizardService, + ExternalDatasetService, + ExternalDataRepositoryService, + ExternalRegistryService, + ExternalResearcherService, + ExternalServiceService, + DatasetProfileService, + UserService, + DmpInvitationService + ], + }; + } +} diff --git a/dmp-frontend/src/app/core/formatting.module.ts b/dmp-frontend/src/app/core/formatting.module.ts new file mode 100644 index 000000000..321184a44 --- /dev/null +++ b/dmp-frontend/src/app/core/formatting.module.ts @@ -0,0 +1,25 @@ +import { DatePipe } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { NgForLimitPipe } from './pipes/ng-for-limit.pipe'; +import { EnumUtils } from './services/utilities/enum-utils.service'; + +// +// +// This is shared module that provides all formatting utils. Its imported only once on the AppModule. +// +// + +@NgModule({ + declarations: [ + NgForLimitPipe + ], + exports: [ + NgForLimitPipe + ], + providers: [ + EnumUtils, + DatePipe, + NgForLimitPipe + ] +}) +export class FormattingModule { } diff --git a/dmp-frontend/src/app/core/model/admin/dataset-profile/dataset-profile.ts b/dmp-frontend/src/app/core/model/admin/dataset-profile/dataset-profile.ts new file mode 100644 index 000000000..9badb6cfc --- /dev/null +++ b/dmp-frontend/src/app/core/model/admin/dataset-profile/dataset-profile.ts @@ -0,0 +1,77 @@ +import { ValidationType } from "../../../common/enum/validation-type"; + +export interface DatasetProfile { + label: string; + sections: Section[]; + pages: Page[]; +} + +export interface Page { + id: string; + ordinal: number; + title: string; +} + +export interface Section { + sections: Section[]; + fieldSets: FieldSet[]; + defaultVisibility: boolean; + page: string; + ordinal: number; + id: string; + title: string; + description: string; +} + +export interface FieldSet { + id: string; + ordinal: number; + multiplicity: Multiplicity; + title: string; + description: string; + extendedDescription: string; + hasCommentField: boolean; + fields: Field[]; +} + +export interface Multiplicity { + min: number; + max: number; +} + +export interface Field { + id: string; + ordinal: number; + value: string; + viewStyle: ViewStyle; + datatype: string; + page: number; + defaultValue: DefaultValue; + data: any; + visible: Visibility; + validations: ValidationType[]; +} + +export interface ViewStyle { + renderStyle: string; + cssClass: string; +} + +export interface DefaultValue { + type: string; + value: string; +} + + +export interface Visibility { + rules: Rule[]; + style: string; +} + +export interface Rule { + ruleType: string; + target: string; + ruleStyle: string; + value: string; + valueType: string; +} diff --git a/dmp-frontend/src/app/core/model/auth/credential.ts b/dmp-frontend/src/app/core/model/auth/credential.ts new file mode 100644 index 000000000..a8c5d4f6b --- /dev/null +++ b/dmp-frontend/src/app/core/model/auth/credential.ts @@ -0,0 +1,4 @@ +export interface Credential { + username: string; + secret: string; +} diff --git a/dmp-frontend/src/app/core/model/auth/login-info.ts b/dmp-frontend/src/app/core/model/auth/login-info.ts new file mode 100644 index 000000000..6c6aa497a --- /dev/null +++ b/dmp-frontend/src/app/core/model/auth/login-info.ts @@ -0,0 +1,7 @@ +import { AuthProvider } from "../../common/enum/auth-provider"; + +export interface LoginInfo { + ticket: string; + provider: AuthProvider; + data?: any; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/model/auth/principal.ts b/dmp-frontend/src/app/core/model/auth/principal.ts new file mode 100644 index 000000000..06228d6dd --- /dev/null +++ b/dmp-frontend/src/app/core/model/auth/principal.ts @@ -0,0 +1,13 @@ +import { AppRole } from "../../common/enum/app-role"; + +export interface Principal { + id: number; + token: string; + name: string; + expiresAt: Date; + authorities: AppRole[]; + avatarUrl: string; + timezone: string; + language: string; + culture: string; +} diff --git a/dmp-frontend/src/app/core/model/base-form-model.ts b/dmp-frontend/src/app/core/model/base-form-model.ts new file mode 100644 index 000000000..2f13a1609 --- /dev/null +++ b/dmp-frontend/src/app/core/model/base-form-model.ts @@ -0,0 +1,4 @@ +import { FormBuilder } from '@angular/forms'; +export abstract class BaseFormModel { + public formBuilder: FormBuilder = new FormBuilder(); +} diff --git a/dmp-frontend/src/app/core/model/culture-info.ts b/dmp-frontend/src/app/core/model/culture-info.ts new file mode 100644 index 000000000..77ae0a475 --- /dev/null +++ b/dmp-frontend/src/app/core/model/culture-info.ts @@ -0,0 +1,5 @@ +export interface CultureInfo { + name: string; + displayName: string; + nativeName: string; +} diff --git a/dmp-frontend/src/app/core/model/dashboard/dashboard-statistics-model.ts b/dmp-frontend/src/app/core/model/dashboard/dashboard-statistics-model.ts new file mode 100644 index 000000000..fda037727 --- /dev/null +++ b/dmp-frontend/src/app/core/model/dashboard/dashboard-statistics-model.ts @@ -0,0 +1,7 @@ +import { Serializable } from "../../../common/types/json/serializable"; + +export interface DashboardStatisticsModel { + totalDataManagementPlanCount: number; + totalProjectCount: number; + totalDataSetCount: number; +} diff --git a/dmp-frontend/src/app/core/model/dashboard/search-bar-item.ts b/dmp-frontend/src/app/core/model/dashboard/search-bar-item.ts new file mode 100644 index 000000000..b8e18cdde --- /dev/null +++ b/dmp-frontend/src/app/core/model/dashboard/search-bar-item.ts @@ -0,0 +1,7 @@ +import { SearchBarType } from "../../../ui/misc/navigation/navigation.component"; + +export interface SearchBarItem { + id: string; + label: string; + type: SearchBarType; +} diff --git a/dmp-frontend/src/app/core/model/data-repository/data-repository.ts b/dmp-frontend/src/app/core/model/data-repository/data-repository.ts new file mode 100644 index 000000000..76f5cf372 --- /dev/null +++ b/dmp-frontend/src/app/core/model/data-repository/data-repository.ts @@ -0,0 +1,8 @@ +export interface DataRepositoryModel { + id: string; + label: string; + abbreviation: string; + uri: string; + pid: string; + info: string; +} diff --git a/dmp-frontend/src/app/core/model/data-table/column-ordering.ts b/dmp-frontend/src/app/core/model/data-table/column-ordering.ts new file mode 100644 index 000000000..3d86f8fd2 --- /dev/null +++ b/dmp-frontend/src/app/core/model/data-table/column-ordering.ts @@ -0,0 +1,3 @@ +export class ColumnOrdering { + public fields: Array = new Array(); +} diff --git a/dmp-frontend/src/app/models/data-table/DataTableData.ts b/dmp-frontend/src/app/core/model/data-table/data-table-data.ts similarity index 100% rename from dmp-frontend/src/app/models/data-table/DataTableData.ts rename to dmp-frontend/src/app/core/model/data-table/data-table-data.ts diff --git a/dmp-frontend/src/app/core/model/data-table/data-table-request.ts b/dmp-frontend/src/app/core/model/data-table/data-table-request.ts new file mode 100644 index 000000000..bd799a7fb --- /dev/null +++ b/dmp-frontend/src/app/core/model/data-table/data-table-request.ts @@ -0,0 +1,14 @@ +import { RequestItem } from '../../query/request-item'; +import { ColumnOrdering } from './column-ordering'; + +export class DataTableRequest extends RequestItem { + offset = 0; + length = 0; + public orderings: ColumnOrdering; + constructor(offset: number, length: number, orderings: ColumnOrdering) { + super(); + this.length = length; + this.offset = offset; + this.orderings = orderings; + } +} diff --git a/dmp-frontend/src/app/core/model/dataset-profile-definition/composite-field.ts b/dmp-frontend/src/app/core/model/dataset-profile-definition/composite-field.ts new file mode 100644 index 000000000..91e0b2a72 --- /dev/null +++ b/dmp-frontend/src/app/core/model/dataset-profile-definition/composite-field.ts @@ -0,0 +1,16 @@ +import { Field } from './field'; +import { Multiplicity } from './multiplicity'; + +export interface CompositeField { + fields: Array; + ordinal: number; + id: string; + numbering: string; + multiplicity: Multiplicity; + multiplicityItems: Array; + title: string; + description: string; + extendedDescription: string; + hasCommentField: boolean; + commentFieldValue: string; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/model/dataset-profile-definition/dataset-profile-definition.ts b/dmp-frontend/src/app/core/model/dataset-profile-definition/dataset-profile-definition.ts new file mode 100644 index 000000000..00edec7bb --- /dev/null +++ b/dmp-frontend/src/app/core/model/dataset-profile-definition/dataset-profile-definition.ts @@ -0,0 +1,8 @@ +import { Page } from "./page"; +import { Rule } from "./rule"; + +export interface DatasetProfileDefinitionModel { + status: number; + pages: Page[]; + rules: Rule[]; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/model/dataset-profile-definition/default-value.ts b/dmp-frontend/src/app/core/model/dataset-profile-definition/default-value.ts new file mode 100644 index 000000000..de586f657 --- /dev/null +++ b/dmp-frontend/src/app/core/model/dataset-profile-definition/default-value.ts @@ -0,0 +1,4 @@ +export interface DefaultValue { + type: string; + value: string; +} diff --git a/dmp-frontend/src/app/core/model/dataset-profile-definition/field-data/field-data.ts b/dmp-frontend/src/app/core/model/dataset-profile-definition/field-data/field-data.ts new file mode 100644 index 000000000..1c6993e12 --- /dev/null +++ b/dmp-frontend/src/app/core/model/dataset-profile-definition/field-data/field-data.ts @@ -0,0 +1,42 @@ +import { DatasetProfileComboBoxType } from "../../../common/enum/dataset-profile-combo-box-type"; + +export interface FieldData { + label: string; +} + +export interface AutoCompleteFieldData extends FieldData { + type: string; + url: string; + optionsRoot: string; + autoCompleteOptions: FieldDataOption; +} + +export interface CheckBoxFieldData extends FieldData { + +} + +export interface BooleanDecisionFieldData extends FieldData { + +} + +export interface FreeTextFieldData extends FieldData { + +} + +export interface RadioBoxFieldData extends FieldData { + options: Array; +} + +export interface TextAreaFieldData extends FieldData { + +} + +export interface WordListFieldData extends FieldData { + type: DatasetProfileComboBoxType; + options: Array; +} + +export interface FieldDataOption extends FieldData { + label: string; + value: string; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/model/dataset-profile-definition/field-group.ts b/dmp-frontend/src/app/core/model/dataset-profile-definition/field-group.ts new file mode 100644 index 000000000..a4ac67cf2 --- /dev/null +++ b/dmp-frontend/src/app/core/model/dataset-profile-definition/field-group.ts @@ -0,0 +1,51 @@ +// import { FormGroup } from "@angular/forms"; +// import { JsonSerializer } from "../../../common/types/json/json-serializer"; +// import { Serializable } from "../../../common/types/json/serializable"; +// import { BaseModel } from "../../../models/BaseModel"; +// import { CompositeField } from "./composite-field"; + +// export class FieldGroup extends BaseModel implements Serializable { +// public id: string; +// public title: string; +// public section: string; +// public value: string; +// public description: string; +// public extendedDescription: string; +// public defaultVisibility: boolean; +// public page: number; +// public compositeFields: Array = new Array(); + +// fromJSONObject(item: any): FieldGroup { +// this.id = item.id; +// this.title = item.title; +// this.value = item.value; +// this.description = item.description; +// this.extendedDescription = item.extendedDescription; +// this.defaultVisibility = item.defaultVisibility; +// this.page = item.page; +// this.compositeFields = new JsonSerializer(CompositeField).fromJSONArray(item.compositeFields); +// return this; +// } + +// buildForm(): FormGroup { +// const formGroup: FormGroup = this.formBuilder.group({ +// /* id: [this.id], +// title: [this.title], +// value: [this.value], +// description: [this.description], +// extendedDescription: [this.extendedDescription], +// defaultVisibility: [this.defaultVisibility], +// page: [this.page] */ +// }); +// const compositeFieldsFormArray = new Array(); +// if (this.compositeFields) { +// this.compositeFields.forEach(item => { +// const form: FormGroup = item.buildForm(); +// compositeFieldsFormArray.push(form); +// }); +// } +// formGroup.addControl('compositeFields', this.formBuilder.array(compositeFieldsFormArray)); + +// return formGroup; +// } +// } diff --git a/dmp-frontend/src/app/core/model/dataset-profile-definition/field.ts b/dmp-frontend/src/app/core/model/dataset-profile-definition/field.ts new file mode 100644 index 000000000..b37e6fd94 --- /dev/null +++ b/dmp-frontend/src/app/core/model/dataset-profile-definition/field.ts @@ -0,0 +1,23 @@ +import { ValidationType } from "../../common/enum/validation-type"; +import { DefaultValue } from "./default-value"; +import { Multiplicity } from "./multiplicity"; +import { ViewStyle } from "./view-style"; + +export interface Field { + + id: string; + title: string; + value: any; + defaultValue: DefaultValue; + description: string; + numbering: string; + extendedDescription: string; + viewStyle: ViewStyle; + defaultVisibility: boolean; + page: number; + multiplicity: Multiplicity; + multiplicityItems: Array; + data: any; + validations: Array; + validationRequired; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/model/dataset-profile-definition/multiplicity.ts b/dmp-frontend/src/app/core/model/dataset-profile-definition/multiplicity.ts new file mode 100644 index 000000000..2b21af29d --- /dev/null +++ b/dmp-frontend/src/app/core/model/dataset-profile-definition/multiplicity.ts @@ -0,0 +1,7 @@ + + +export interface Multiplicity { + min: number; + max: number; +} + diff --git a/dmp-frontend/src/app/core/model/dataset-profile-definition/page.ts b/dmp-frontend/src/app/core/model/dataset-profile-definition/page.ts new file mode 100644 index 000000000..b8c05a808 --- /dev/null +++ b/dmp-frontend/src/app/core/model/dataset-profile-definition/page.ts @@ -0,0 +1,7 @@ +import { Section } from "./section"; + +export interface Page { + ordinal: number; + title: string; + sections: Array
; +} diff --git a/dmp-frontend/src/app/core/model/dataset-profile-definition/rule.ts b/dmp-frontend/src/app/core/model/dataset-profile-definition/rule.ts new file mode 100644 index 000000000..b17886989 --- /dev/null +++ b/dmp-frontend/src/app/core/model/dataset-profile-definition/rule.ts @@ -0,0 +1,6 @@ +export class Rule { + sourceField: string; + targetField: string; + requiredValue: any; + type: string; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/model/dataset-profile-definition/section.ts b/dmp-frontend/src/app/core/model/dataset-profile-definition/section.ts new file mode 100644 index 000000000..8c52b1c4f --- /dev/null +++ b/dmp-frontend/src/app/core/model/dataset-profile-definition/section.ts @@ -0,0 +1,13 @@ +import { CompositeField } from "./composite-field"; + +export interface Section { + sections: Array
; + defaultVisibility: boolean; + page: number; + numbering: string; + ordinal: number; + id: string; + title: string; + description: string; + compositeFields: Array; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/model/dataset-profile-definition/view-style.ts b/dmp-frontend/src/app/core/model/dataset-profile-definition/view-style.ts new file mode 100644 index 000000000..daaba384c --- /dev/null +++ b/dmp-frontend/src/app/core/model/dataset-profile-definition/view-style.ts @@ -0,0 +1,4 @@ +export interface ViewStyle { + cssClass: string; + renderStyle: string; +} diff --git a/dmp-frontend/src/app/core/model/dataset/dataset-listing.ts b/dmp-frontend/src/app/core/model/dataset/dataset-listing.ts new file mode 100644 index 000000000..b1b07caed --- /dev/null +++ b/dmp-frontend/src/app/core/model/dataset/dataset-listing.ts @@ -0,0 +1,13 @@ +export interface DatasetListingModel { + id: String; + label: String; + dmp: String; + project: String; + profile: String; + dataRepositories: String; + registries: String; + services: String; + description: String; + status: Number; + created: Date; +} diff --git a/dmp-frontend/src/app/core/model/dataset/dataset-profile.ts b/dmp-frontend/src/app/core/model/dataset/dataset-profile.ts new file mode 100644 index 000000000..a8a2fd2ea --- /dev/null +++ b/dmp-frontend/src/app/core/model/dataset/dataset-profile.ts @@ -0,0 +1,33 @@ + +export interface DatasetProfileModel { + id: String; + label: String; +} + +// export class DatasetProfileModel implements Serializable { +// public id: String; +// public label: String; + +// fromJSONObject(item: any): DatasetProfileModel { +// this.id = item.id; +// this.label = item.label; + +// return this; +// } + +// buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { +// if (context == null) { context = this.createValidationContext(); } + +// const formGroup = new FormBuilder().group({ +// id: [{ value: this.id, disabled: disabled }], +// }); + +// return formGroup; +// } + +// createValidationContext(): ValidationContext { +// const baseContext: ValidationContext = new ValidationContext(); +// //baseContext.validation.push({ key: 'id', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'id')] }); +// return baseContext; +// } +// } diff --git a/dmp-frontend/src/app/core/model/dataset/dataset-wizard.ts b/dmp-frontend/src/app/core/model/dataset/dataset-wizard.ts new file mode 100644 index 000000000..10e705dc7 --- /dev/null +++ b/dmp-frontend/src/app/core/model/dataset/dataset-wizard.ts @@ -0,0 +1,24 @@ +import { DataRepositoryModel } from "../data-repository/data-repository"; +import { DatasetProfileDefinitionModel } from "../dataset-profile-definition/dataset-profile-definition"; +import { DmpModel } from "../dmp/dmp"; +import { ExternalDatasetModel } from "../external-dataset/external-dataset"; +import { RegistryModel } from "../registry/registry"; +import { ServiceModel } from "../service/service"; +import { TagModel } from "../tag/tag"; +import { DatasetProfileModel } from "./dataset-profile"; + +export interface DatasetWizardModel { + id?: string; + label?: string; + uri?: String; + description?: String; + status?: number; + dmp?: DmpModel; + datasetProfileDefinition?: DatasetProfileDefinitionModel; + registries?: RegistryModel[]; + services?: ServiceModel[]; + dataRepositories?: DataRepositoryModel[]; + tags?: TagModel[]; + externalDatasets?: ExternalDatasetModel[]; + profile?: DatasetProfileModel; +} diff --git a/dmp-frontend/src/app/core/model/dataset/dataset.ts b/dmp-frontend/src/app/core/model/dataset/dataset.ts new file mode 100644 index 000000000..9341cab81 --- /dev/null +++ b/dmp-frontend/src/app/core/model/dataset/dataset.ts @@ -0,0 +1,73 @@ +import { DataRepositoryModel } from '../data-repository/data-repository'; +import { RegistryModel } from '../registry/registry'; +import { ServiceModel } from '../service/service'; + +export interface DatasetModel { + id: String; + label: String; + profile: String; + uri: String; + status: String; + description: String; + services: ServiceModel[]; + registries: RegistryModel[]; + dataRepositories: DataRepositoryModel[]; +} +// export class DatasetModel implements Serializable { +// public id: String; +// public label: String; +// public profile: String; +// public uri: String; +// public status: String; +// public description: String; +// public services: ServiceModel[] = []; +// public registries: RegistryModel[] = []; +// public dataRepositories: DataRepositoryModel[] = []; + +// public errorModel: ValidationErrorModel = new ValidationErrorModel(); + +// fromJSONObject(item: any): DatasetModel { +// this.id = item.id; +// this.label = item.label; +// this.profile = item.profile; +// this.uri = item.uri; +// this.status = item.status; +// this.description = item.description; +// this.services = new JsonSerializer(ServiceModel).fromJSONArray(item.services); +// this.registries = new JsonSerializer(RegistryModel).fromJSONArray(item.registries); +// this.dataRepositories = new JsonSerializer(DataRepositoryModel).fromJSONArray(item.dataRepositories); + +// return this; +// } + +// buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { +// if (context == null) { context = this.createValidationContext(); } + +// const formGroup = new FormBuilder().group({ +// label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators], +// profile: [{ value: this.profile, disabled: disabled }, context.getValidation('profile').validators], +// uri: [{ value: this.uri, disabled: disabled }, context.getValidation('uri').validators], +// status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators], +// description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators], +// services: [{ value: this.services, disabled: disabled }, context.getValidation('services').validators], +// registries: [{ value: this.registries, disabled: disabled }, context.getValidation('registries').validators], +// dataRepositories: [{ value: this.dataRepositories, disabled: disabled }, context.getValidation('dataRepositories').validators] +// }); + +// return formGroup; +// } + +// createValidationContext(): ValidationContext { +// const baseContext: ValidationContext = new ValidationContext(); +// baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'label')] }); +// baseContext.validation.push({ key: 'profile', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'profile')] }); +// baseContext.validation.push({ key: 'uri', validators: [BackendErrorValidator(this.errorModel, 'uri')] }); +// baseContext.validation.push({ key: 'status', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'status')] }); +// baseContext.validation.push({ key: 'description', validators: [BackendErrorValidator(this.errorModel, 'description')] }); +// baseContext.validation.push({ key: 'services', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'services')] }); +// baseContext.validation.push({ key: 'registries', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'registries')] }); +// baseContext.validation.push({ key: 'dataRepositories', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'dataRepositories')] }); + +// return baseContext; +// } +// } diff --git a/dmp-frontend/src/app/core/model/dmp-profile/dmp-profile-field.ts b/dmp-frontend/src/app/core/model/dmp-profile/dmp-profile-field.ts new file mode 100644 index 000000000..dd9e84eb0 --- /dev/null +++ b/dmp-frontend/src/app/core/model/dmp-profile/dmp-profile-field.ts @@ -0,0 +1,11 @@ +import { DmpProfileFieldDataType } from '../../common/enum/dmp-profile-field-type'; +import { DmpProfileType } from '../../common/enum/dmp-profile-type'; + +export interface DmpProfileField { + id: string; + type: DmpProfileType; + dataType: DmpProfileFieldDataType; + required: boolean; + label: string; + value: any; +} diff --git a/dmp-frontend/src/app/core/model/dmp-profile/dmp-profile-listing.ts b/dmp-frontend/src/app/core/model/dmp-profile/dmp-profile-listing.ts new file mode 100644 index 000000000..eecb6a995 --- /dev/null +++ b/dmp-frontend/src/app/core/model/dmp-profile/dmp-profile-listing.ts @@ -0,0 +1,10 @@ +import { DmpProfileDefinition } from "./dmp-profile"; + +export interface DmpProfileListing { + id: string; + label: string; + definition: DmpProfileDefinition; + status: number; + created: Date; + modified: Date; +} diff --git a/dmp-frontend/src/app/core/model/dmp-profile/dmp-profile.ts b/dmp-frontend/src/app/core/model/dmp-profile/dmp-profile.ts new file mode 100644 index 000000000..0d40aa85d --- /dev/null +++ b/dmp-frontend/src/app/core/model/dmp-profile/dmp-profile.ts @@ -0,0 +1,15 @@ +import { DmpProfileField } from "./dmp-profile-field"; + + +export interface DmpProfile { + id: string; + label: string; + definition: DmpProfileDefinition; + status: number; + created: Date; + modified: Date; +} + +export interface DmpProfileDefinition { + fields: DmpProfileField[]; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/model/dmp/dmp-dynamic-field-dependency.ts b/dmp-frontend/src/app/core/model/dmp/dmp-dynamic-field-dependency.ts new file mode 100644 index 000000000..36ec05572 --- /dev/null +++ b/dmp-frontend/src/app/core/model/dmp/dmp-dynamic-field-dependency.ts @@ -0,0 +1,4 @@ +export interface DmpDynamicFieldDependency { + id: string; + queryProperty: string; +} diff --git a/dmp-frontend/src/app/core/model/dmp/dmp-dynamic-field.ts b/dmp-frontend/src/app/core/model/dmp/dmp-dynamic-field.ts new file mode 100644 index 000000000..08f932d7e --- /dev/null +++ b/dmp-frontend/src/app/core/model/dmp/dmp-dynamic-field.ts @@ -0,0 +1,10 @@ +import { DmpDynamicFieldDependency } from "./dmp-dynamic-field-dependency"; + +export interface DmpDynamicField { + id: string; + name: string; + required: boolean; + queryProperty; + value: string; + dependencies: Array; +} diff --git a/dmp-frontend/src/app/core/model/dmp/dmp-listing.ts b/dmp-frontend/src/app/core/model/dmp/dmp-listing.ts new file mode 100644 index 000000000..dacb4c5f5 --- /dev/null +++ b/dmp-frontend/src/app/core/model/dmp/dmp-listing.ts @@ -0,0 +1,14 @@ +import { DmpStatus } from "../../common/enum/dmp-status"; + +export interface DmpListingModel { + id: String; + label: String; + status: DmpStatus; + project: String; + profile: String; + creationTime: String; + organisations: String; + groupId: string; + version: number; + datasets: any[]; +} diff --git a/dmp-frontend/src/app/core/model/dmp/dmp.ts b/dmp-frontend/src/app/core/model/dmp/dmp.ts new file mode 100644 index 000000000..969f3144a --- /dev/null +++ b/dmp-frontend/src/app/core/model/dmp/dmp.ts @@ -0,0 +1,26 @@ +import { Status } from "../../common/enum/Status"; +import { DmpProfile, DmpProfileDefinition } from "../dmp-profile/dmp-profile"; +import { OrganizationModel } from "../organisation/organization"; +import { ProjectModel } from "../project/project"; +import { ResearcherModel } from "../researcher/researcher"; +import { UserModel } from "../user/user"; +import { DmpDynamicField } from "./dmp-dynamic-field"; + +export interface DmpModel { + id: string; + label: string; + groupId: String; + profile: String; + version: number; + status: Status; + lockable: boolean; + description: String; + profiles: DmpProfile[]; + project: ProjectModel; + organisations: OrganizationModel[]; + researchers: ResearcherModel[]; + associatedUsers: UserModel[]; + creator: UserModel; + definition: DmpProfileDefinition; + dynamicFields: Array; +} diff --git a/dmp-frontend/src/app/core/model/dmp/invitation/dmp-invitation-user.ts b/dmp-frontend/src/app/core/model/dmp/invitation/dmp-invitation-user.ts new file mode 100644 index 000000000..7634679cb --- /dev/null +++ b/dmp-frontend/src/app/core/model/dmp/invitation/dmp-invitation-user.ts @@ -0,0 +1,25 @@ +import { FormBuilder, FormGroup } from '@angular/forms'; +import { Serializable } from '../../../../common/types/json/serializable'; + +export class DmpInvitationUser implements Serializable { + + public id: string; + public email: string; + public name: string; + + fromJSONObject(item: any): DmpInvitationUser { + this.id = item.id; + this.email = item.email; + this.name = item.name; + return this; + } + + buildForm(): FormGroup { + return new FormBuilder().group({ + id: [this.id], + email: [this.email], + name: [this.name] + }); + } + +} diff --git a/dmp-frontend/src/app/core/model/dmp/invitation/dmp-invitation.ts b/dmp-frontend/src/app/core/model/dmp/invitation/dmp-invitation.ts new file mode 100644 index 000000000..51ff6afe8 --- /dev/null +++ b/dmp-frontend/src/app/core/model/dmp/invitation/dmp-invitation.ts @@ -0,0 +1,17 @@ +import { FormBuilder, FormGroup } from '@angular/forms'; +import { DmpInvitationUser } from './dmp-invitation-user'; + +export class DmpInvitation { + + public dataManagementPlan: string; + public users = new Array(); + + buildForm(): FormGroup { + const formGroup = new FormBuilder().group({ + dataManagementPlan: [this.dataManagementPlan], + users: [this.users] + }); + + return formGroup; + } +} diff --git a/dmp-frontend/src/app/core/model/external-dataset/external-dataset.ts b/dmp-frontend/src/app/core/model/external-dataset/external-dataset.ts new file mode 100644 index 000000000..e4cff37d9 --- /dev/null +++ b/dmp-frontend/src/app/core/model/external-dataset/external-dataset.ts @@ -0,0 +1,10 @@ +import { ExternalDatasetType } from '../../common/enum/external-dataset-type'; + +export interface ExternalDatasetModel { + abbreviation: String; + id: String; + label: String; + reference: String; + type: ExternalDatasetType; + info: String; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/model/external-sources/external-source-item.ts b/dmp-frontend/src/app/core/model/external-sources/external-source-item.ts new file mode 100644 index 000000000..2e703911a --- /dev/null +++ b/dmp-frontend/src/app/core/model/external-sources/external-source-item.ts @@ -0,0 +1,5 @@ +export interface ExternalSourceItemModel { + id: String; + name: String; + description: String; +} diff --git a/dmp-frontend/src/app/core/model/external-sources/external-source-url.ts b/dmp-frontend/src/app/core/model/external-sources/external-source-url.ts new file mode 100644 index 000000000..3965eb618 --- /dev/null +++ b/dmp-frontend/src/app/core/model/external-sources/external-source-url.ts @@ -0,0 +1,4 @@ +export class ExternalSourceUrlModel { + public key: String; + public label: String; +} diff --git a/dmp-frontend/src/app/core/model/external-sources/external-sources-configuration.ts b/dmp-frontend/src/app/core/model/external-sources/external-sources-configuration.ts new file mode 100644 index 000000000..7ca3e955d --- /dev/null +++ b/dmp-frontend/src/app/core/model/external-sources/external-sources-configuration.ts @@ -0,0 +1,9 @@ +import { ExternalSourceUrlModel } from "./external-source-url"; + +export class ExternalSourcesConfiguration { + public registries: Array; + public dataRepositories: Array; + public services: Array; + public externalDatasets: Array; + public tags: Array; +} diff --git a/dmp-frontend/src/app/models/help-content/active-topic-questions.ts b/dmp-frontend/src/app/core/model/help-content/active-topic-questions.ts similarity index 100% rename from dmp-frontend/src/app/models/help-content/active-topic-questions.ts rename to dmp-frontend/src/app/core/model/help-content/active-topic-questions.ts diff --git a/dmp-frontend/src/app/models/help-content/page-help-content.ts b/dmp-frontend/src/app/core/model/help-content/page-help-content.ts similarity index 100% rename from dmp-frontend/src/app/models/help-content/page-help-content.ts rename to dmp-frontend/src/app/core/model/help-content/page-help-content.ts diff --git a/dmp-frontend/src/app/models/help-content/page.ts b/dmp-frontend/src/app/core/model/help-content/page.ts similarity index 100% rename from dmp-frontend/src/app/models/help-content/page.ts rename to dmp-frontend/src/app/core/model/help-content/page.ts diff --git a/dmp-frontend/src/app/models/help-content/question.ts b/dmp-frontend/src/app/core/model/help-content/question.ts similarity index 100% rename from dmp-frontend/src/app/models/help-content/question.ts rename to dmp-frontend/src/app/core/model/help-content/question.ts diff --git a/dmp-frontend/src/app/models/help-content/topic.ts b/dmp-frontend/src/app/core/model/help-content/topic.ts similarity index 100% rename from dmp-frontend/src/app/models/help-content/topic.ts rename to dmp-frontend/src/app/core/model/help-content/topic.ts diff --git a/dmp-frontend/src/app/core/model/organisation/organization.ts b/dmp-frontend/src/app/core/model/organisation/organization.ts new file mode 100644 index 000000000..d623e9623 --- /dev/null +++ b/dmp-frontend/src/app/core/model/organisation/organization.ts @@ -0,0 +1,8 @@ +import { Status } from "../../common/enum/Status"; + +export interface OrganizationModel { + id: String; + name: String; + label: String; + status: Status; +} diff --git a/dmp-frontend/src/app/core/model/project/project-listing.ts b/dmp-frontend/src/app/core/model/project/project-listing.ts new file mode 100644 index 000000000..7dbbe1ebc --- /dev/null +++ b/dmp-frontend/src/app/core/model/project/project-listing.ts @@ -0,0 +1,16 @@ +import { UrlListingItem } from "../../../library/url-listing/url-listing-item"; +import { ContentFile } from "./project"; + +export interface ProjectListingModel { + id: String; + label: String; + abbreviation: String; + reference: String; + uri: String; + status: String; + startDate: Date; + endDate: Date; + description: String; + files: ContentFile[]; + dmps: UrlListingItem[]; +} diff --git a/dmp-frontend/src/app/core/model/project/project.ts b/dmp-frontend/src/app/core/model/project/project.ts new file mode 100644 index 000000000..8b4a39571 --- /dev/null +++ b/dmp-frontend/src/app/core/model/project/project.ts @@ -0,0 +1,24 @@ +import { ProjectType } from '../../common/enum/project-type'; +import { Status } from '../../common/enum/Status'; + +export interface ProjectModel { + id?: string; + label?: string; + abbreviation?: string; + reference?: string; + type?: ProjectType; + uri?: String; + status?: Status; + startDate?: Date; + endDate?: Date; + description?: String; + contentUrl?: string; + files?: ContentFile[]; +} + +export interface ContentFile { + filename?: string; + id?: string; + location?: string; + type?: string; +} diff --git a/dmp-frontend/src/app/core/model/registry/registry.ts b/dmp-frontend/src/app/core/model/registry/registry.ts new file mode 100644 index 000000000..c9568466c --- /dev/null +++ b/dmp-frontend/src/app/core/model/registry/registry.ts @@ -0,0 +1,9 @@ + +export interface RegistryModel { + abbreviation: String; + definition: String; + id: String; + label: String; + reference: String; + uri: String; +} diff --git a/dmp-frontend/src/app/core/model/researcher/researcher.ts b/dmp-frontend/src/app/core/model/researcher/researcher.ts new file mode 100644 index 000000000..0a1b250f6 --- /dev/null +++ b/dmp-frontend/src/app/core/model/researcher/researcher.ts @@ -0,0 +1,7 @@ +export interface ResearcherModel { + id: String; + name: String; + lastName: String; + uri: String; + email: String; +} diff --git a/dmp-frontend/src/app/core/model/service/service.ts b/dmp-frontend/src/app/core/model/service/service.ts new file mode 100644 index 000000000..20c8dacd4 --- /dev/null +++ b/dmp-frontend/src/app/core/model/service/service.ts @@ -0,0 +1,9 @@ +export interface ServiceModel { + id: String; + abbreviation: String; + definition: String; + uri: String; + label: String; + reference: String; +} + diff --git a/dmp-frontend/src/app/core/model/tag/tag.ts b/dmp-frontend/src/app/core/model/tag/tag.ts new file mode 100644 index 000000000..b38f2ddc8 --- /dev/null +++ b/dmp-frontend/src/app/core/model/tag/tag.ts @@ -0,0 +1,4 @@ +export interface TagModel { + id: string; + name: string; +} diff --git a/dmp-frontend/src/app/core/model/user/user-listing.ts b/dmp-frontend/src/app/core/model/user/user-listing.ts new file mode 100644 index 000000000..2ba60a45d --- /dev/null +++ b/dmp-frontend/src/app/core/model/user/user-listing.ts @@ -0,0 +1,7 @@ +import { AppRole } from "../../common/enum/app-role"; + +export interface UserListingModel { + id: String; + name: String; + appRoles: AppRole[]; +} diff --git a/dmp-frontend/src/app/core/model/user/user.ts b/dmp-frontend/src/app/core/model/user/user.ts new file mode 100644 index 000000000..bc235f03b --- /dev/null +++ b/dmp-frontend/src/app/core/model/user/user.ts @@ -0,0 +1,7 @@ +import { AppRole } from "../../common/enum/app-role"; + +export interface UserModel { + id: String; + name: String; + appRoles: AppRole[]; +} diff --git a/dmp-frontend/src/app/core/pipes/culture-info-display.pipe.ts b/dmp-frontend/src/app/core/pipes/culture-info-display.pipe.ts new file mode 100644 index 000000000..af5e470bc --- /dev/null +++ b/dmp-frontend/src/app/core/pipes/culture-info-display.pipe.ts @@ -0,0 +1,11 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { CultureInfo } from '../model/culture-info'; + +@Pipe({ name: 'cultureInfoDisplay' }) +export class CultureInfoDisplayPipe implements PipeTransform { + constructor() { } + + public transform(value: CultureInfo): any { + return value.nativeName + ' [' + value.name + ']'; + } +} diff --git a/dmp-frontend/src/app/core/pipes/date-format.pipe.ts b/dmp-frontend/src/app/core/pipes/date-format.pipe.ts new file mode 100644 index 000000000..dc3eb80c6 --- /dev/null +++ b/dmp-frontend/src/app/core/pipes/date-format.pipe.ts @@ -0,0 +1,43 @@ +import { DatePipe } from '@angular/common'; +import { Pipe, PipeTransform } from '@angular/core'; +import * as moment from 'moment'; +import 'moment-timezone'; + +@Pipe({ + name: 'dateFormatter' +}) +export class DateFormatPipe implements PipeTransform { + + constructor(private datePipe: DatePipe) { + + } + + transform(value: any, format?: string, locale?: string): string | null { + // using timezone set in timezoneService by default. can be overwritten with pipe arguments + const timezoneToUse = moment(value).tz('UTC').format('Z'); + return this.datePipe.transform(value, format, timezoneToUse, locale); + } +} + +@Pipe({ + name: 'dataTableDateFormatter' +}) +// This is only used for the DataTable Column definition. +// It's a hacky way to apply format to the pipe because it only supports passing a pipe instance and calls transform in it without params. +export class DataTableDateFormatPipe extends DateFormatPipe implements PipeTransform { + + format: string; + + constructor(_datePipe: DatePipe) { + super(_datePipe); + } + + public withFormat(format: string): DataTableDateFormatPipe { + this.format = format; + return this; + } + + transform(value: any): string | null { + return super.transform(value, this.format); + } +} diff --git a/dmp-frontend/src/app/core/pipes/date-time-format.pipe.ts b/dmp-frontend/src/app/core/pipes/date-time-format.pipe.ts new file mode 100644 index 000000000..26a6541b1 --- /dev/null +++ b/dmp-frontend/src/app/core/pipes/date-time-format.pipe.ts @@ -0,0 +1,46 @@ +import { DatePipe } from '@angular/common'; +import { Pipe, PipeTransform } from '@angular/core'; +import * as moment from 'moment'; +import 'moment-timezone'; +import { TimezoneService } from '../services/timezone/timezone-service'; + +@Pipe({ + name: 'dateTimeFormatter' +}) +export class DateTimeFormatPipe implements PipeTransform { + + constructor(private datePipe: DatePipe, private timezoneService: TimezoneService) { + + } + + transform(value: any, format?: string, timezone?: string, locale?: string): string | null { + // using timezone set in timezoneService by default. can be overwritten with pipe arguments + const timezoneToUse = timezone ? timezone : moment(value).tz(this.timezoneService.getCurrentTimezone()).format('Z'); + return this.datePipe.transform(value, format, timezoneToUse, locale); + } +} + + +@Pipe({ + name: 'dataTableDateTimeFormatter' +}) +// This is only used for the DataTable Column definition. +// It's a hacky way to apply format to the pipe because it only supports passing a pipe instance and calls transform in it without params. +export class DataTableDateTimeFormatPipe extends DateTimeFormatPipe implements PipeTransform { + + format: string; + + constructor(private _datePipe: DatePipe, private _timezoneService: TimezoneService) { + super(_datePipe, _timezoneService); + } + + public withFormat(format: string): DataTableDateTimeFormatPipe { + this.format = format; + return this; + } + + transform(value: any): string | null { + return super.transform(value, this.format); + } +} + diff --git a/dmp-frontend/src/app/shared/pipes/ngforlimit/ngforlimit.pipe.ts b/dmp-frontend/src/app/core/pipes/ng-for-limit.pipe.ts similarity index 100% rename from dmp-frontend/src/app/shared/pipes/ngforlimit/ngforlimit.pipe.ts rename to dmp-frontend/src/app/core/pipes/ng-for-limit.pipe.ts diff --git a/dmp-frontend/src/app/core/pipes/pipe.service.ts b/dmp-frontend/src/app/core/pipes/pipe.service.ts new file mode 100644 index 000000000..413383eeb --- /dev/null +++ b/dmp-frontend/src/app/core/pipes/pipe.service.ts @@ -0,0 +1,10 @@ +import { Injectable, Injector } from '@angular/core'; + +@Injectable() +export class PipeService { + constructor(private injector: Injector) { } + + public getPipe(T): T { + return this.injector.get(T); + } +} diff --git a/dmp-frontend/src/app/core/pipes/timezone-info-display.pipe.ts b/dmp-frontend/src/app/core/pipes/timezone-info-display.pipe.ts new file mode 100644 index 000000000..b55223c4f --- /dev/null +++ b/dmp-frontend/src/app/core/pipes/timezone-info-display.pipe.ts @@ -0,0 +1,12 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import * as moment from 'moment'; +import 'moment-timezone'; + +@Pipe({ name: 'timezoneInfoDisplay' }) +export class TimezoneInfoDisplayPipe implements PipeTransform { + constructor() { } + + public transform(value): any { + return value + ' (GMT' + moment.tz(value).format('Z') + ')'; + } +} diff --git a/dmp-frontend/src/app/core/query/base-criteria.ts b/dmp-frontend/src/app/core/query/base-criteria.ts new file mode 100644 index 000000000..29d339a13 --- /dev/null +++ b/dmp-frontend/src/app/core/query/base-criteria.ts @@ -0,0 +1,3 @@ +export class BaseCriteria { + public like: string; +} diff --git a/dmp-frontend/src/app/core/query/data-repository/data-repository-criteria.ts b/dmp-frontend/src/app/core/query/data-repository/data-repository-criteria.ts new file mode 100644 index 000000000..c4f286878 --- /dev/null +++ b/dmp-frontend/src/app/core/query/data-repository/data-repository-criteria.ts @@ -0,0 +1,5 @@ +import { BaseCriteria } from "../base-criteria"; + +export class DataRepositoryCriteria extends BaseCriteria { + public type: string; +} diff --git a/dmp-frontend/src/app/core/query/dataset-profile/dataset-profile-criteria.ts b/dmp-frontend/src/app/core/query/dataset-profile/dataset-profile-criteria.ts new file mode 100644 index 000000000..7a4ea5cd6 --- /dev/null +++ b/dmp-frontend/src/app/core/query/dataset-profile/dataset-profile-criteria.ts @@ -0,0 +1,5 @@ +import { BaseCriteria } from "../base-criteria"; + +export class DatasetProfileCriteria extends BaseCriteria { + public id: String; +} diff --git a/dmp-frontend/src/app/core/query/dataset/dataset-criteria.ts b/dmp-frontend/src/app/core/query/dataset/dataset-criteria.ts new file mode 100644 index 000000000..d662d56e6 --- /dev/null +++ b/dmp-frontend/src/app/core/query/dataset/dataset-criteria.ts @@ -0,0 +1,9 @@ +import { ExternalSourceItemModel } from "../../model/external-sources/external-source-item"; +import { BaseCriteria } from "../base-criteria"; + +export class DatasetCriteria extends BaseCriteria { + public status: Number; + public dmpIds: String[] = []; + public tags: ExternalSourceItemModel[] = []; + public allVersions: boolean; +} diff --git a/dmp-frontend/src/app/core/query/dmp/dmp-criteria.ts b/dmp-frontend/src/app/core/query/dmp/dmp-criteria.ts new file mode 100644 index 000000000..e70f3fdb2 --- /dev/null +++ b/dmp-frontend/src/app/core/query/dmp/dmp-criteria.ts @@ -0,0 +1,8 @@ +import { ProjectModel } from "../../model/project/project"; +import { BaseCriteria } from "../base-criteria"; + +export class DmpCriteria extends BaseCriteria { + public projects: ProjectModel[] = []; + public groupIds: string[]; + public allVersions: boolean; +} diff --git a/dmp-frontend/src/app/core/query/dmp/dmp-invitation-user-criteria.ts b/dmp-frontend/src/app/core/query/dmp/dmp-invitation-user-criteria.ts new file mode 100644 index 000000000..32c0b6653 --- /dev/null +++ b/dmp-frontend/src/app/core/query/dmp/dmp-invitation-user-criteria.ts @@ -0,0 +1,5 @@ +import { BaseCriteria } from "../base-criteria"; + +export class DmpInvitationUserCriteria extends BaseCriteria { + +} diff --git a/dmp-frontend/src/app/core/query/dmp/dmp-profile-criteria.ts b/dmp-frontend/src/app/core/query/dmp/dmp-profile-criteria.ts new file mode 100644 index 000000000..9855ca785 --- /dev/null +++ b/dmp-frontend/src/app/core/query/dmp/dmp-profile-criteria.ts @@ -0,0 +1,5 @@ +import { BaseCriteria } from "../base-criteria"; + +export class DmpProfileCriteria extends BaseCriteria { + +} diff --git a/dmp-frontend/src/app/core/query/explore-dataset/explore-dataset-criteria.ts b/dmp-frontend/src/app/core/query/explore-dataset/explore-dataset-criteria.ts new file mode 100644 index 000000000..4f7df4b5a --- /dev/null +++ b/dmp-frontend/src/app/core/query/explore-dataset/explore-dataset-criteria.ts @@ -0,0 +1,10 @@ +import { ProjectStateType } from "../../common/enum/project-state-type"; +import { BaseCriteria } from "../base-criteria"; + +export class ExploreDatasetCriteriaModel extends BaseCriteria { + public projectStatus: ProjectStateType; + public projects: string[] = []; + public datasetProfile: string[] = []; + public dmpOrganisations: string[] = []; + public tags = []; +} diff --git a/dmp-frontend/src/app/core/query/external-dataset/external-dataset-criteria.ts b/dmp-frontend/src/app/core/query/external-dataset/external-dataset-criteria.ts new file mode 100644 index 000000000..dec991910 --- /dev/null +++ b/dmp-frontend/src/app/core/query/external-dataset/external-dataset-criteria.ts @@ -0,0 +1,5 @@ +import { BaseCriteria } from "../base-criteria"; + +export class ExternalDatasetCriteria extends BaseCriteria { + public type: string; +} diff --git a/dmp-frontend/src/app/core/query/project/project-criteria.ts b/dmp-frontend/src/app/core/query/project/project-criteria.ts new file mode 100644 index 000000000..bf8c8e795 --- /dev/null +++ b/dmp-frontend/src/app/core/query/project/project-criteria.ts @@ -0,0 +1,8 @@ +import { ProjectStateType } from "../../common/enum/project-state-type"; +import { BaseCriteria } from "../base-criteria"; + +export class ProjectCriteria extends BaseCriteria { + public periodStart: Date; + public periodEnd: Date; + public projectStateType: ProjectStateType; +} diff --git a/dmp-frontend/src/app/core/query/registry/registry-criteria.ts b/dmp-frontend/src/app/core/query/registry/registry-criteria.ts new file mode 100644 index 000000000..be7d0da31 --- /dev/null +++ b/dmp-frontend/src/app/core/query/registry/registry-criteria.ts @@ -0,0 +1,5 @@ +import { BaseCriteria } from "../base-criteria"; + +export class RegistryCriteria extends BaseCriteria { + public type: string; +} diff --git a/dmp-frontend/src/app/core/query/request-item.ts b/dmp-frontend/src/app/core/query/request-item.ts new file mode 100644 index 000000000..2aacfb551 --- /dev/null +++ b/dmp-frontend/src/app/core/query/request-item.ts @@ -0,0 +1,3 @@ +export class RequestItem { + public criteria: T; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/query/researcher/researcher-criteria.ts b/dmp-frontend/src/app/core/query/researcher/researcher-criteria.ts new file mode 100644 index 000000000..3eda8ff2a --- /dev/null +++ b/dmp-frontend/src/app/core/query/researcher/researcher-criteria.ts @@ -0,0 +1,5 @@ +import { BaseCriteria } from "../base-criteria"; + +export class ResearcherCriteria extends BaseCriteria { + public name: String; +} diff --git a/dmp-frontend/src/app/core/query/service/service-criteria.ts b/dmp-frontend/src/app/core/query/service/service-criteria.ts new file mode 100644 index 000000000..8c397cf4d --- /dev/null +++ b/dmp-frontend/src/app/core/query/service/service-criteria.ts @@ -0,0 +1,5 @@ +import { BaseCriteria } from "../base-criteria"; + +export class ServiceCriteria extends BaseCriteria { + public type: string; +} diff --git a/dmp-frontend/src/app/core/query/tag/tag-criteria.ts b/dmp-frontend/src/app/core/query/tag/tag-criteria.ts new file mode 100644 index 000000000..e78ed43c6 --- /dev/null +++ b/dmp-frontend/src/app/core/query/tag/tag-criteria.ts @@ -0,0 +1,5 @@ +import { BaseCriteria } from "../base-criteria"; + +export class TagCriteria extends BaseCriteria { + public type: string; +} diff --git a/dmp-frontend/src/app/core/query/user/user-criteria.ts b/dmp-frontend/src/app/core/query/user/user-criteria.ts new file mode 100644 index 000000000..5d0c631a2 --- /dev/null +++ b/dmp-frontend/src/app/core/query/user/user-criteria.ts @@ -0,0 +1,7 @@ +import { AppRole } from "../../common/enum/app-role"; +import { BaseCriteria } from "../base-criteria"; + +export class UserCriteria extends BaseCriteria { + public label: String; + public appRoles: AppRole[]; +} diff --git a/dmp-frontend/src/app/core/services/auth/auth.service.ts b/dmp-frontend/src/app/core/services/auth/auth.service.ts new file mode 100644 index 000000000..256bf5718 --- /dev/null +++ b/dmp-frontend/src/app/core/services/auth/auth.service.ts @@ -0,0 +1,150 @@ +import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { MatSnackBar } from '@angular/material'; +import { Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { takeUntil } from 'rxjs/operators'; +import { Observable } from 'rxjs/Rx'; +import { environment } from '../../../../environments/environment'; +import { SnackBarNotificationComponent } from '../../../library/notification/snack-bar/snack-bar-notification.component'; +import { BaseService } from '../../common/base/base.service'; +import { Credential } from '../../model/auth/credential'; +import { LoginInfo } from '../../model/auth/login-info'; +import { Principal } from '../../model/auth/Principal'; + + +@Injectable() +export class AuthService extends BaseService { + private actionUrl: string; + private headers: HttpHeaders; + + constructor( + private http: HttpClient, + public snackBar: MatSnackBar, + public language: TranslateService, + public router: Router + ) { + super(); + this.actionUrl = environment.Server + 'auth/'; + + this.headers = new HttpHeaders(); + this.headers = this.headers.set('Content-Type', 'application/json'); + this.headers = this.headers.set('Accept', 'application/json'); + } + + private clear(): void { + localStorage.removeItem('principal'); + } + + public current(principal?: Principal): Principal { + if (principal) { + localStorage.setItem('principal', JSON.stringify(principal)); + return principal; + } + const principalJson = localStorage.getItem('principal'); + if (!principalJson) { return null; } + const principalObj = JSON.parse(principalJson) as Principal; + return principalObj; + } + + //public login(credential: Credential): Observable { + // const url = this.actionUrl + 'login'; + + // return this.http.post(url, credential, { headers: this.headers }) + // .map((res: Response) => { + // let principal = this.current(new JsonSerializer().fromJSONObject(res, Principal)); + // //this.loginContextSubject.next(true); + // return principal; + // }) + // .catch((error: any) => { + // //this.loginContextSubject.next(false); + // return Observable.throw(error); + // }); + //} + + public login(loginInfo: LoginInfo): Observable { + const url = this.actionUrl + 'externallogin'; + + return this.http.post(url, loginInfo, { headers: this.headers }) + .map((res: any) => { + const principal = this.current(res.payload); + //this.loginContextSubject.next(true); + return principal; + }) + .catch((error: any) => { + //this.loginContextSubject.next(false); + return Observable.throw(error); + }); + } + + public nativeLogin(credentials: Credential): Observable { + const url = this.actionUrl + 'nativelogin'; + + return this.http.post(url, credentials, { headers: this.headers }) + .map((res: any) => { + const principal = this.current(res.payload); + //this.loginContextSubject.next(true); + return principal; + }) + .catch((error: any) => { + //this.loginContextSubject.next(false); + return Observable.throw(error); + }); + } + + + public logout(): void { + const url = this.actionUrl + 'logout'; + const principal = this.current(); + this.clear(); + + if (!principal) { return; } + let headers = this.headers; + headers = headers.set('AuthToken', principal.token); + this.http.post(url, null, { headers: headers }) + .pipe(takeUntil(this._destroyed)) + .subscribe( + res => this.onLogOutSuccess(res), + error => this.onLogOutError(error) + ); + } + + public me(): Observable { + const url = this.actionUrl + '/me'; + const principal = this.current(); + if (!principal) { + this.clear(); + return Observable.of(); + } + let headers = this.headers; + headers = headers.set('AuthToken', principal.token); + return this.http.post(url, null, { headers: headers }) + .map((res: any) => { + const princ = this.current(res.payload); + return princ; + }) + .catch((error: any) => { + //console.warn('could not retrieve me info:\n', error); + this.clear(); + const princ = this.current(); + this.router.navigate(['/login']); + return Observable.of(princ); + }); + } + + public onLogOutSuccess(logoutMessage: any) { + this.snackBar.openFromComponent(SnackBarNotificationComponent, { + data: { message: 'GENERAL.SNACK-BAR.SUCCESSFUL-LOGOUT', language: this.language }, + duration: 3000, + }); + this.router.navigate(['/login']); + } + + public onLogOutError(errorMessage: string) { + this.snackBar.openFromComponent(SnackBarNotificationComponent, { + data: { message: 'GENERAL.SNACK-BAR.UNSUCCESSFUL-LOGOUT', language: this.language }, + duration: 3000, + }); + this.router.navigate(['/login']); + } +} diff --git a/dmp-frontend/src/app/core/services/culture/culture-service.ts b/dmp-frontend/src/app/core/services/culture/culture-service.ts new file mode 100644 index 000000000..32294c806 --- /dev/null +++ b/dmp-frontend/src/app/core/services/culture/culture-service.ts @@ -0,0 +1,84 @@ +import { registerLocaleData } from '@angular/common'; +import { Injectable } from '@angular/core'; +import { Observable, Subject } from 'rxjs'; +import { CultureInfo } from '../../model/culture-info'; +import { LoggingService } from '../logging/logging-service'; +import { TypeUtils } from '../utilities/type-utils.service'; + +const availableCultures: CultureInfo[] = require('../../../../assets/localization/available-cultures.json'); + +@Injectable() +export class CultureService { + + private cultureValues = new Map(); // cultures by name + private cultureChangeSubject = new Subject(); + private currentCulture: CultureInfo; + + constructor( + private typeUtils: TypeUtils, + private logger: LoggingService + ) { + if (availableCultures) { + this.cultureValues = new Map(); + availableCultures.forEach(culture => { + this.cultureValues.set(culture.name, culture); + }); + } + } + + getCultureValues(): CultureInfo[] { + const values: CultureInfo[] = []; + this.cultureValues.forEach((value) => values.push(value)); + return values; + } + + getCultureValue(culture: string): CultureInfo | undefined { + return this.cultureValues.get(culture); + } + + cultureSelected(culture: string | CultureInfo) { + let newCultureName: string; + if (this.typeUtils.isString(culture)) { + if (this.currentCulture && this.currentCulture.name === culture) { return; } + newCultureName = culture; + } else { + if (this.currentCulture && this.currentCulture.name === culture.name) { return; } + newCultureName = culture.name; + } + + const newCulture = this.cultureValues.get(newCultureName); + if (!newCulture) { + console.error(`unsupported culture given: ${newCultureName}`); //TODO: throw error? + return; + } + this.currentCulture = newCulture; + this.cultureChangeSubject.next(newCulture); + + // Set angular locale based on user selection. + // This is a very hacky way to map cultures with angular cultures, since there is no mapping. We first try to + // use the culture with the specialization (ex en-US), and if not exists we import the base culture (first part). + let locale = newCulture.name; + import(`@angular/common/locales/${locale}.js`).catch(reason => { + this.logger.error('Could not load locale: ' + locale); + }).then(selectedLocale => { + if (selectedLocale) { + registerLocaleData(selectedLocale.default); + } else { + locale = newCulture.name.split('-')[0]; + import(`@angular/common/locales/${locale}.js`).catch(reason => { + this.logger.error('Could not load locale: ' + locale); + }).then(selectedDefaultLocale => { + registerLocaleData(selectedDefaultLocale.default); + }); + } + }); + } + + getCultureChangeObservable(): Observable { + return this.cultureChangeSubject.asObservable(); + } + + getCurrentCulture(): CultureInfo { + return this.currentCulture; + } +} diff --git a/dmp-frontend/src/app/core/services/dashboard/dashboard.service.ts b/dmp-frontend/src/app/core/services/dashboard/dashboard.service.ts new file mode 100644 index 000000000..156a5d596 --- /dev/null +++ b/dmp-frontend/src/app/core/services/dashboard/dashboard.service.ts @@ -0,0 +1,25 @@ +import { HttpHeaders } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../environments/environment'; +import { DashboardStatisticsModel } from '../../model/dashboard/dashboard-statistics-model'; +import { BaseHttpService } from '../http/base-http.service'; + +@Injectable() +export class DashboardService { + + private actionUrl: string; + private headers: HttpHeaders; + + constructor(private http: BaseHttpService) { + this.actionUrl = environment.Server + 'dashboard/'; + } + + getStatistics(): Observable { + return this.http.get(this.actionUrl + 'getStatistics', { headers: this.headers }); + } + + getUserStatistics(): Observable { + return this.http.get(this.actionUrl + 'me/getStatistics', { headers: this.headers }); + } +} diff --git a/dmp-frontend/src/app/core/services/dataset-profile/dataset-profile.service.ts b/dmp-frontend/src/app/core/services/dataset-profile/dataset-profile.service.ts new file mode 100644 index 000000000..16ccf85a7 --- /dev/null +++ b/dmp-frontend/src/app/core/services/dataset-profile/dataset-profile.service.ts @@ -0,0 +1,44 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../environments/environment'; +import { DataTableData } from '../../model/data-table/data-table-data'; +import { DataTableRequest } from '../../model/data-table/data-table-request'; +import { DatasetProfileEditorModel } from '../../../ui/admin/dataset-profile/editor/dataset-profile-editor-model'; +import { DatasetProfile } from '../../model/admin/dataset-profile/dataset-profile'; +import { DatasetListingModel } from '../../model/dataset/dataset-listing'; +import { DatasetProfileCriteria } from '../../query/dataset-profile/dataset-profile-criteria'; +import { BaseHttpService } from '../http/base-http.service'; +import { DatasetProfileDefinitionModel } from '../../model/dataset-profile-definition/dataset-profile-definition'; + +@Injectable() +export class DatasetProfileService { + + private actionUrl: string; + + constructor(private http: BaseHttpService) { + this.actionUrl = environment.Server + 'admin/'; + } + createForm(data) { + return this.http.post(this.actionUrl + 'addDmp', data); + } + + updateForm(id, data) { + return this.http.post(this.actionUrl + 'addDmp/' + id, data); + } + + getDatasetProfileById(datasetProfileID) { + return this.http.get(this.actionUrl + 'get/' + datasetProfileID); + } + + getPaged(dataTableRequest: DataTableRequest): Observable> { + return this.http.post>(this.actionUrl + 'datasetprofiles/getPaged', dataTableRequest); + } + + preview(data: DatasetProfile): Observable { + return this.http.post(this.actionUrl + 'preview', data); + } + + clone(id: string): Observable { + return this.http.post(environment.Server + 'datasetprofile/clone/' + id, {}); + } +} diff --git a/dmp-frontend/src/app/core/services/dataset-wizard/dataset-wizard.service.ts b/dmp-frontend/src/app/core/services/dataset-wizard/dataset-wizard.service.ts new file mode 100644 index 000000000..69c045786 --- /dev/null +++ b/dmp-frontend/src/app/core/services/dataset-wizard/dataset-wizard.service.ts @@ -0,0 +1,59 @@ +import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../environments/environment'; +import { RequestItem } from '../../query/request-item'; +import { DatasetProfileDefinitionModel } from '../../model/dataset-profile-definition/dataset-profile-definition'; +import { DatasetProfileModel } from '../../model/dataset/dataset-profile'; +import { DatasetWizardModel } from '../../model/dataset/dataset-wizard'; +import { DmpModel } from '../../model/dmp/dmp'; +import { DatasetProfileCriteria } from '../../query/dataset-profile/dataset-profile-criteria'; +import { DmpCriteria } from '../../query/dmp/dmp-criteria'; +import { BaseHttpService } from '../http/base-http.service'; + +@Injectable() +export class DatasetWizardService { + + private actionUrl: string; + private headers: HttpHeaders; + + constructor(private http: BaseHttpService, private httpClient: HttpClient) { + this.actionUrl = environment.Server + 'datasetwizard/'; + } + + public userDmps(criteria: RequestItem): Observable { + return this.http.post(this.actionUrl + 'userDmps', criteria, { headers: this.headers }); + } + + public getAvailableProfiles(criteria: RequestItem): Observable { + return this.http.post(this.actionUrl + 'getAvailableProfiles/', criteria, { headers: this.headers }); + } + + public getSingle(id: String): Observable { + return this.http.get(this.actionUrl + 'getSingle/' + id, { headers: this.headers }); + } + + public delete(id: string): Observable { + return this.http.delete(this.actionUrl + 'delete/' + id, { headers: this.headers }); + } + + createDataset(datasetModel: DatasetWizardModel): Observable { + return this.http.post(this.actionUrl + 'createOrUpdate', datasetModel, { headers: this.headers }); + } + + public downloadPDF(id: string): Observable> { + return this.httpClient.get(this.actionUrl + 'getPDF/' + id, { responseType: 'blob', observe: 'response' }); + } + + public downloadXML(id: string): Observable> { + return this.httpClient.get(this.actionUrl + 'getXml/' + id, { responseType: 'blob', observe: 'response' }); + } + + public getDefinition(id: String): Observable { + return this.http.get(this.actionUrl + 'get/' + id, { headers: this.headers }); + } + + unlock(id: String): Observable { + return this.http.get(this.actionUrl + id + '/unlock', { headers: this.headers }); + } +} diff --git a/dmp-frontend/src/app/core/services/dataset/dataset.service.ts b/dmp-frontend/src/app/core/services/dataset/dataset.service.ts new file mode 100644 index 000000000..d78361d79 --- /dev/null +++ b/dmp-frontend/src/app/core/services/dataset/dataset.service.ts @@ -0,0 +1,36 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../environments/environment'; +import { DataTableData } from '../../model/data-table/data-table-data'; +import { DataTableRequest } from '../../model/data-table/data-table-request'; +import { DatasetListingModel } from '../../model/dataset/dataset-listing'; +import { DatasetProfileModel } from '../../model/dataset/dataset-profile'; +import { DatasetCriteria } from '../../query/dataset/dataset-criteria'; +import { ExploreDatasetCriteriaModel } from '../../query/explore-dataset/explore-dataset-criteria'; +import { BaseHttpService } from '../http/base-http.service'; + +@Injectable() +export class DatasetService { + + private actionUrl: string; + + constructor(private http: BaseHttpService) { + this.actionUrl = environment.Server + 'datasets/'; + } + + getPaged(dataTableRequest: DataTableRequest): Observable> { + return this.http.post>(this.actionUrl + 'getPaged', dataTableRequest); + } + + getPublicPaged(dataTableRequest: DataTableRequest): Observable> { + return this.http.post>(this.actionUrl + 'public/paged', dataTableRequest); + } + + makeDatasetPublic(id: String) { + return this.http.get(this.actionUrl + 'makepublic/' + id); + } + + getDatasetProfiles(): Observable { + return this.http.get(environment.Server + 'datasetprofiles/getAll'); + } +} diff --git a/dmp-frontend/src/app/core/services/dmp/dmp-invitation.service.ts b/dmp-frontend/src/app/core/services/dmp/dmp-invitation.service.ts new file mode 100644 index 000000000..3f7dca82f --- /dev/null +++ b/dmp-frontend/src/app/core/services/dmp/dmp-invitation.service.ts @@ -0,0 +1,32 @@ +import { HttpHeaders } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../environments/environment'; +import { RequestItem } from '../../query/request-item'; +import { DmpInvitation } from '../../model/dmp/invitation/dmp-invitation'; +import { DmpInvitationUser } from '../../model/dmp/invitation/dmp-invitation-user'; +import { DmpInvitationUserCriteria } from '../../query/dmp/dmp-invitation-user-criteria'; +import { BaseHttpService } from '../http/base-http.service'; + +@Injectable() +export class DmpInvitationService { + + private actionUrl: string; + private headers: HttpHeaders; + + constructor(private http: BaseHttpService) { + this.actionUrl = environment.Server + 'invite/'; + } + + public inviteDmpInvitationUsers(invitation: DmpInvitation): Observable { + return this.http.post(this.actionUrl + 'users', invitation, { headers: this.headers }); + } + + public getDmpInvitationUsers(usersInvitationRequestItem: RequestItem): Observable { + return this.http.post(this.actionUrl + 'getUsers', usersInvitationRequestItem, { headers: this.headers }); + } + + public exchange(id: String): Observable { + return this.http.get(this.actionUrl + 'exchange/' + id, { headers: this.headers }); + } +} diff --git a/dmp-frontend/src/app/core/services/dmp/dmp-profile.service.ts b/dmp-frontend/src/app/core/services/dmp/dmp-profile.service.ts new file mode 100644 index 000000000..851c27427 --- /dev/null +++ b/dmp-frontend/src/app/core/services/dmp/dmp-profile.service.ts @@ -0,0 +1,38 @@ +import { HttpHeaders } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../environments/environment'; +import { DataTableRequest } from '../../model/data-table/data-table-request'; +import { DmpProfile } from '../../model/dmp-profile/dmp-profile'; +import { BaseHttpService } from '../http/base-http.service'; +import { DmpProfileListing } from '../../model/dmp-profile/dmp-profile-listing'; +import { RequestItem } from '../../query/request-item'; +import { DataTableData } from '../../model/data-table/data-table-data'; +import { DmpProfileCriteria } from '../../query/dmp/dmp-profile-criteria'; + +@Injectable() +export class DmpProfileService { + + private actionUrl: string; + private headers: HttpHeaders; + + constructor(private http: BaseHttpService) { + this.actionUrl = environment.Server + 'dmpprofile/'; + } + + getPaged(dataTableRequest: DataTableRequest): Observable> { + return this.http.post>(this.actionUrl + 'getPaged', dataTableRequest, { headers: this.headers }); + } + + getSingle(id: String): Observable { + return this.http.get(this.actionUrl + 'getSingle/' + id, { headers: this.headers }); + } + + createDmp(dataManagementPlanModel: DmpProfile): Observable { + return this.http.post(this.actionUrl + 'createOrUpdate', dataManagementPlanModel, { headers: this.headers }); + } + + getAll(criteria: RequestItem): Observable { + return this.http.post(this.actionUrl + 'get/', criteria, { headers: this.headers }); + } +} diff --git a/dmp-frontend/src/app/core/services/dmp/dmp.service.ts b/dmp-frontend/src/app/core/services/dmp/dmp.service.ts new file mode 100644 index 000000000..78df66786 --- /dev/null +++ b/dmp-frontend/src/app/core/services/dmp/dmp.service.ts @@ -0,0 +1,80 @@ +import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../environments/environment'; +import { DynamicFieldProjectCriteria } from '../../../models/dynamic-field-project/DynamicFieldProjectCriteria'; +import { DataTableData } from '../../model/data-table/data-table-data'; +import { DataTableRequest } from '../../model/data-table/data-table-request'; +import { DatasetProfileModel } from '../../model/dataset/dataset-profile'; +import { DmpModel } from '../../model/dmp/dmp'; +import { DmpListingModel } from '../../model/dmp/dmp-listing'; +import { DatasetProfileCriteria } from '../../query/dataset-profile/dataset-profile-criteria'; +import { DmpCriteria } from '../../query/dmp/dmp-criteria'; +import { RequestItem } from '../../query/request-item'; +import { BaseHttpService } from '../http/base-http.service'; + +@Injectable() +export class DmpService { + + private actionUrl: string; + private headers: HttpHeaders; + + constructor(private http: BaseHttpService, private httpClient: HttpClient) { + this.actionUrl = environment.Server + 'dmps/'; + } + + getPaged(dataTableRequest: DataTableRequest): Observable> { + return this.http.post>(this.actionUrl + 'getPaged', dataTableRequest, { headers: this.headers }); + } + + getSingle(id: String): Observable { + return this.http.get(this.actionUrl + 'getSingle/' + id, { headers: this.headers }); + } + + unlock(id: String): Observable { + return this.http.get(this.actionUrl + id + '/unlock', { headers: this.headers }); + } + createDmp(dataManagementPlanModel: DmpModel): Observable { + return this.http.post(this.actionUrl + 'createOrUpdate', dataManagementPlanModel, { headers: this.headers }); + } + + inactivate(id: String): Observable { + return this.http.delete(this.actionUrl + 'inactivate/' + id, { headers: this.headers }); + } + + searchDMPProfiles(dataSetProfileRequest: RequestItem): Observable { + return this.http.post(this.actionUrl + 'datasetprofiles/get', dataSetProfileRequest, { headers: this.headers }); + } + + newVersion(dataManagementPlanModel: DmpModel, id: String): Observable { + return this.http.post(this.actionUrl + 'new/' + id, dataManagementPlanModel, { headers: this.headers }); + } + + clone(dataManagementPlanModel: DmpModel, id: String): Observable { + return this.http.post(this.actionUrl + 'clone/' + id, dataManagementPlanModel, { headers: this.headers }); + } + + delete(id: String): Observable { + return this.http.delete(this.actionUrl + 'delete/' + id, { headers: this.headers }); + } + + getDynamicField(requestItem: RequestItem): any { + return this.http.post(this.actionUrl + 'dynamic', requestItem, { headers: this.headers }); + } + + get(requestItem: RequestItem): Observable { + return this.http.post(this.actionUrl + 'get', requestItem, { headers: this.headers }); + } + + public downloadXML(id: string): Observable> { + return this.httpClient.get(this.actionUrl + 'getXml/' + id, { responseType: 'blob', observe: 'response' }); + } + + public downloadDocx(id: string): Observable> { + return this.httpClient.get(this.actionUrl + 'getWord/' + id, { responseType: 'blob', observe: 'response' }); + } + + public downloadPDF(id: string): Observable> { + return this.httpClient.get(this.actionUrl + 'getPDF/' + id, { responseType: 'blob', observe: 'response' }); + } +} diff --git a/dmp-frontend/src/app/core/services/external-sources/data-repository/extternal-data-repository.service.ts b/dmp-frontend/src/app/core/services/external-sources/data-repository/extternal-data-repository.service.ts new file mode 100644 index 000000000..58e2ab577 --- /dev/null +++ b/dmp-frontend/src/app/core/services/external-sources/data-repository/extternal-data-repository.service.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../../environments/environment'; +import { DataRepositoryModel } from '../../../model/data-repository/data-repository'; +import { BaseHttpService } from '../../http/base-http.service'; + +@Injectable() +export class ExternalDataRepositoryService { + + private actionUrl: string; + constructor(private http: BaseHttpService) { + this.actionUrl = environment.Server + 'datarepos/'; + } + + create(dataRepoModel: DataRepositoryModel): Observable { + return this.http.post(this.actionUrl + 'create', dataRepoModel); + } + +} diff --git a/dmp-frontend/src/app/core/services/external-sources/dataset/external-dataset.service.ts b/dmp-frontend/src/app/core/services/external-sources/dataset/external-dataset.service.ts new file mode 100644 index 000000000..ff431b62c --- /dev/null +++ b/dmp-frontend/src/app/core/services/external-sources/dataset/external-dataset.service.ts @@ -0,0 +1,38 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../../environments/environment'; +import { RequestItem } from '../../../query/request-item'; +import { DataTableData } from '../../../model/data-table/data-table-data'; +import { DataTableRequest } from '../../../model/data-table/data-table-request'; +import { ExternalDatasetModel } from '../../../model/external-dataset/external-dataset'; +import { ExternalDatasetCriteria } from '../../../query/external-dataset/external-dataset-criteria'; +import { BaseHttpService } from '../../http/base-http.service'; + +@Injectable() +export class ExternalDatasetService { + + private actionUrl: string; + constructor(private http: BaseHttpService) { + this.actionUrl = environment.Server + 'externaldatasets/'; + } + + getPaged(dataTableRequest: DataTableRequest): Observable> { + return this.http.post>(this.actionUrl + 'getPaged', dataTableRequest); + } + + /* get(requestItem: RequestItem): Observable { + return this.http.post(this.actionUrl + 'get', requestItem); + }*/ + + getWithExternal(requestItem: RequestItem): Observable { + return this.http.post(this.actionUrl + 'getWithExternal', requestItem); + } + + getSingle(id: string): Observable { + return this.http.get(this.actionUrl + 'getSingle/' + id); + } + + create(externalDatasetModel: ExternalDatasetModel): Observable { + return this.http.post(this.actionUrl + 'create', externalDatasetModel); + } +} diff --git a/dmp-frontend/src/app/core/services/external-sources/external-sources-configuration.service.ts b/dmp-frontend/src/app/core/services/external-sources/external-sources-configuration.service.ts new file mode 100644 index 000000000..ab6247a64 --- /dev/null +++ b/dmp-frontend/src/app/core/services/external-sources/external-sources-configuration.service.ts @@ -0,0 +1,22 @@ +import { HttpHeaders } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../environments/environment'; +import { ExternalSourcesConfiguration } from '../../model/external-sources/external-sources-configuration'; +import { BaseHttpService } from '../http/base-http.service'; + +@Injectable() +export class ExternalSourcesConfigurationService { + + private actionUrl: string; + private headers: HttpHeaders; + + constructor(private http: BaseHttpService) { + this.actionUrl = environment.Server + 'common/'; + } + + public getExternalSourcesConfiguration(): Observable { + return this.http.get(this.actionUrl + 'externalSourcesConfiguration', { headers: this.headers }); + } + +} diff --git a/dmp-frontend/src/app/core/services/external-sources/external-sources.service.ts b/dmp-frontend/src/app/core/services/external-sources/external-sources.service.ts new file mode 100644 index 000000000..11cac4e6d --- /dev/null +++ b/dmp-frontend/src/app/core/services/external-sources/external-sources.service.ts @@ -0,0 +1,72 @@ +import { HttpHeaders } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../environments/environment'; +import { RequestItem } from '../../query/request-item'; +import { ExternalSourceItemModel } from '../../model/external-sources/external-source-item'; +import { DataRepositoryCriteria } from '../../query/data-repository/data-repository-criteria'; +import { ExternalDatasetCriteria } from '../../query/external-dataset/external-dataset-criteria'; +import { RegistryCriteria } from '../../query/registry/registry-criteria'; +import { ResearcherCriteria } from '../../query/researcher/researcher-criteria'; +import { ServiceCriteria } from '../../query/service/service-criteria'; +import { TagCriteria } from '../../query/tag/tag-criteria'; +import { BaseHttpService } from '../http/base-http.service'; + +@Injectable() +export class ExternalSourcesService { + + private actionUrl: string; + private headers: HttpHeaders; + + constructor(private http: BaseHttpService) { + + this.actionUrl = environment.Server + 'external/'; + + this.headers = new HttpHeaders(); + this.headers = this.headers.set('Content-Type', 'application/json'); + this.headers = this.headers.set('Accept', 'application/json'); + } + + public searchDatasetRegistry(requestItem: RequestItem): Observable { + return this.http.get(this.actionUrl + 'registries' + '?query=' + requestItem.criteria.like + '&type=' + requestItem.criteria.type, { headers: this.headers }); + } + + public searchDatasetRepository(requestItem: RequestItem): Observable { + return this.http.get(this.actionUrl + 'datarepos' + '?query=' + requestItem.criteria.like + '&type=' + requestItem.criteria.type, { headers: this.headers }); + } + + public searchDatasetService(requestItem: RequestItem): Observable { + return this.http.get(this.actionUrl + 'services' + '?query=' + requestItem.criteria.like + '&type=' + requestItem.criteria.type, { headers: this.headers }); + } + + public searchDatasetTags(requestItem: RequestItem): Observable { + return Observable.of([ + { id: '1', name: 'Tag 1', description: '' }, + { id: '2', name: 'Tag 2', description: '' }, + { id: '3', name: 'Tag 3', description: '' }, + { id: '4', name: 'Tag 4', description: '' }, + { id: '5', name: 'Tag 5', description: '' }, + { id: '6', name: 'Tag 6', description: '' }, + { id: '7', name: 'Tag 7', description: '' }, + { id: '8', name: 'Tag 8', description: '' }, + ]); + //return this.http.get(this.actionUrl + "tags" + "?query=" + requestItem.criteria.like + "&type=" + requestItem.criteria.type, { headers: this.headers }); + } + + public searchDatasetSExternalDatasetservice(requestItem: RequestItem): Observable { + return this.http.get(this.actionUrl + 'datasets' + '?query=' + requestItem.criteria.like + '&type=' + requestItem.criteria.type, { headers: this.headers }); + } + + public searchDMPResearchers(requestItem: RequestItem): Observable { + return this.http.post(environment.Server + '/researchers/getWithExternal', requestItem, { headers: this.headers }); + } + + public searchDMPOrganizations(like: string): Observable { + return this.http.get(this.actionUrl + 'organisations' + '?query=' + like, { headers: this.headers }); + }//organizationscriteria.criteria.like + + public searchDMPProfiles(like: string): Observable { + return this.http.get(this.actionUrl + 'datasetprofiles/get' + '?query=' + like, { headers: this.headers }); + } + +} diff --git a/dmp-frontend/src/app/core/services/external-sources/registry/external-registry.service.ts b/dmp-frontend/src/app/core/services/external-sources/registry/external-registry.service.ts new file mode 100644 index 000000000..0006f62f0 --- /dev/null +++ b/dmp-frontend/src/app/core/services/external-sources/registry/external-registry.service.ts @@ -0,0 +1,18 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../../environments/environment'; +import { RegistryModel } from '../../../model/registry/registry'; +import { BaseHttpService } from '../../http/base-http.service'; + +@Injectable() +export class ExternalRegistryService { + + private actionUrl: string; + constructor(private http: BaseHttpService) { + this.actionUrl = environment.Server + 'registries/'; + } + + create(registerModel: RegistryModel): Observable { + return this.http.post(this.actionUrl + 'create', registerModel); + } +} diff --git a/dmp-frontend/src/app/core/services/external-sources/researcher/external-researcher.service.ts b/dmp-frontend/src/app/core/services/external-sources/researcher/external-researcher.service.ts new file mode 100644 index 000000000..1ccc52750 --- /dev/null +++ b/dmp-frontend/src/app/core/services/external-sources/researcher/external-researcher.service.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@angular/core'; +import { environment } from '../../../../../environments/environment'; +import { ResearcherModel } from '../../../model/researcher/researcher'; +import { BaseHttpService } from '../../http/base-http.service'; + +@Injectable() +export class ExternalResearcherService { + + private actionUrl: string; + + constructor(private http: BaseHttpService) { + this.actionUrl = environment.Server + 'researchers/'; + } + + public createResearcher(researcher: ResearcherModel) { + return this.http.post(this.actionUrl + 'create', researcher); + } + +} diff --git a/dmp-frontend/src/app/core/services/external-sources/service/external-service.service.ts b/dmp-frontend/src/app/core/services/external-sources/service/external-service.service.ts new file mode 100644 index 000000000..ef556b667 --- /dev/null +++ b/dmp-frontend/src/app/core/services/external-sources/service/external-service.service.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../../environments/environment'; +import { ServiceModel } from '../../../model/service/service'; +import { BaseHttpService } from '../../http/base-http.service'; + +@Injectable() +export class ExternalServiceService { + + private actionUrl: string; + constructor(private http: BaseHttpService) { + this.actionUrl = environment.Server + 'services/'; + } + + create(serviceModel: ServiceModel): Observable { + return this.http.post(this.actionUrl + 'create', serviceModel); + } + +} diff --git a/dmp-frontend/src/app/core/services/help-content/cached-content-item.ts b/dmp-frontend/src/app/core/services/help-content/cached-content-item.ts new file mode 100644 index 000000000..c33f7a264 --- /dev/null +++ b/dmp-frontend/src/app/core/services/help-content/cached-content-item.ts @@ -0,0 +1,6 @@ +import { PageHelpContent } from "../../model/help-content/page-help-content"; + +export class CachedContentItem { + public timestamp: number; + public content: PageHelpContent; +} diff --git a/dmp-frontend/src/app/core/services/help-content/help-content.service.ts b/dmp-frontend/src/app/core/services/help-content/help-content.service.ts new file mode 100644 index 000000000..638e289c9 --- /dev/null +++ b/dmp-frontend/src/app/core/services/help-content/help-content.service.ts @@ -0,0 +1,55 @@ +/** + * Created by stefania on 7/17/17. + */ +import { Injectable } from '@angular/core'; +import { Http, Response } from '@angular/http'; +import { Observable } from 'rxjs/Rx'; +import { environment } from '../../../../environments/environment'; +import { PageHelpContent } from '../../model/help-content/page-help-content'; +import { CachedContentItem } from './cached-content-item'; + +@Injectable() +export class HelpContentService { + private _helpServiceUrl = environment.HelpService.Url; + cache = new Map(); + + constructor(private http: Http) { + } + + getActivePageContent(route: string) { + if (!this.cache.get(route) || !this.isValidCachedItem(route)) { + return this.http.get(this._helpServiceUrl + '/page/route?q=' + route) + .map(res => { + this.cache.set(route, { timestamp: Date.now(), content: res.json() }); + return res.json(); + }) + .catch(this.handleError); + } + return Observable.create(observer => observer.next(this.cache.get(route).content)); + } + private extractData(res: Response) { + const body = res.json(); + return body.data || {}; + } + private handleError(error: Response | any) { + // In a real world app, we might use a remote logging infrastructure + // We'd also dig deeper into the error to get a better message + let errMsg = ''; + if (error instanceof Response) { + const body = error.text() || ''; + //const err = body.error || JSON.stringify(body); + errMsg = `${error.status} - ${error.statusText || ''} ${body}`; + } else { + errMsg = (error.message) ? error.message : + error.status ? `${error.status} - ${error.statusText}` : 'Server error'; + console.error(errMsg); // log to console instead + } + return Observable.throw(errMsg); + } + + isValidCachedItem(route) { + const cachedTimestamp = this.cache.get(route).timestamp; + const currentTimestamp = Date.now(); + if (currentTimestamp - cachedTimestamp > 30000) { return false; } else { return true; } + } +} diff --git a/dmp-frontend/src/app/core/services/http/base-http.service.ts b/dmp-frontend/src/app/core/services/http/base-http.service.ts new file mode 100644 index 000000000..a3e0aca26 --- /dev/null +++ b/dmp-frontend/src/app/core/services/http/base-http.service.ts @@ -0,0 +1,88 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { ApiMessageCode } from '../../common/enum/api-message-code'; + +@Injectable() +export class BaseHttpService { + constructor( + protected http: HttpClient + ) { + } + + get(url: string, options?: Object): Observable { + return this.interceptRepsonse(this.http.get(url, options)); + } + + post(url: string, body: any, options?: Object): Observable { + return this.interceptRepsonse(this.http.post(url, body, options)); + } + + put(url: string, body: any, options?: Object): Observable { + return this.interceptRepsonse(this.http.put(url, body, options)); + } + + delete(url: string, options?: Object): Observable { + return this.interceptRepsonse(this.http.delete(url, options)); + } + + patch(url: string, body: any, options?: Object): Observable { + return this.interceptRepsonse(this.http.patch(url, body, options)); + } + + head(url: string, options?: Object): Observable { + return this.interceptRepsonse(this.http.head(url, options)); + } + + options(url: string, options?: Object): Observable { + return this.interceptRepsonse(this.http.options(url, options)); + } + + private interceptRepsonse(observable: Observable): Observable { + return observable + // .catch((errorResponse) => { + // if (errorResponse.status === 401) { + // this.snackBar.openFromComponent(SnackBarNotificationComponent, { + // data: { message: 'GENERAL.SNACK-BAR.SUCCESSFUL-LOGOUT', language: this.language }, + // duration: 3000, + // }); + // const currentPage = this.router.url; + // this.router.navigate(['/unauthorized'], { queryParams: { returnUrl: currentPage } }); + // //this.notification.httpError(error); + // return Observable.of(); + // } else { + // const error: any = errorResponse.error; + // if (error.statusCode === ApiMessageCode.ERROR_MESSAGE) { + // this.snackBar.openFromComponent(SnackBarNotificationComponent, { + // data: { message: error.message, language: null }, + // duration: 3000, + // }); + // return Observable.throw(errorResponse); + // } else if (error.statusCode === ApiMessageCode.VALIDATION_MESSAGE) { + // return Observable.throw(errorResponse); + // } else { + // this.snackBar.openFromComponent(SnackBarNotificationComponent, { + // data: { message: 'GENERAL.ERRORS.HTTP-REQUEST-ERROR', language: this.language }, + // duration: 3000, + // }); + // return Observable.throw(errorResponse); + // } + // } + // }) + .map(response => { + if (response instanceof Blob) { return response; } + if (response['statusCode'] === ApiMessageCode.SUCCESS_MESSAGE) { + //throw new Error('Request failed'); + // this.snackBar.openFromComponent(SnackBarNotificationComponent, { + // data: { message: response['message'], language: null }, + // duration: 3000, + // }); + return response['payload']; + } else if (response['statusCode'] === ApiMessageCode.NO_MESSAGE) { + return response['payload']; + } else { + return response['payload']; + } + }); + } +} diff --git a/dmp-frontend/src/app/core/services/logging/logging-service.ts b/dmp-frontend/src/app/core/services/logging/logging-service.ts new file mode 100644 index 000000000..1da0dc0cc --- /dev/null +++ b/dmp-frontend/src/app/core/services/logging/logging-service.ts @@ -0,0 +1,69 @@ +import { Injectable } from '@angular/core'; +import { environment } from '../../../../environments/environment'; + +export enum LogLevel { + Error = 'error', + Warning = 'warning', + Info = 'info', + Debug = 'debug', +} + +export type LogOutput = (level: LogLevel, ...objects: any[]) => void; + +@Injectable() +export class LoggingService { + + private loggingLevels: LogLevel[]; + private loggingOutputs: LogOutput[] = []; + + constructor() { + + } + + debug(...logs: any[]) { + this.log(LogLevel.Debug, logs); + } + + info(...logs: any[]) { + this.log(LogLevel.Info, logs); + } + + warn(...logs: any[]) { + this.log(LogLevel.Warning, logs); + } + + error(...logs: any[]) { + this.log(LogLevel.Error, logs); + } + + init() { + this.loggingLevels = environment.logging.logLevels as LogLevel[]; + + this.loggingOutputs.push((level: LogLevel, ...objects: any[]) => { + switch (level) { + case LogLevel.Debug: + // tslint:disable-next-line:no-console + console.debug(objects.join(', ')); + break; + case LogLevel.Info: + // tslint:disable-next-line:no-console + console.info(objects.join(', ')); + break; + case LogLevel.Warning: + console.warn(objects.join(', ')); + break; + case LogLevel.Error: + console.error(objects.join(', ')); + break; + } + }); + } + + private log(level: LogLevel, logs: any[]) { + if (!this.loggingLevels) { this.init(); } + + if (environment.logging.enabled && this.loggingLevels.includes(level)) { + this.loggingOutputs.forEach((output) => output.apply(output, [level, logs])); + } + } +} diff --git a/dmp-frontend/src/app/core/services/notification/ui-notification-service.ts b/dmp-frontend/src/app/core/services/notification/ui-notification-service.ts new file mode 100644 index 000000000..3219daa45 --- /dev/null +++ b/dmp-frontend/src/app/core/services/notification/ui-notification-service.ts @@ -0,0 +1,60 @@ +import { Injectable } from '@angular/core'; +import { Observable, Subject } from 'rxjs'; + +@Injectable() +export class UiNotificationService { + + private notificationSubject = new Subject(); + + constructor() { + } + + public snackBarNotification(message: string, level: SnackBarNotificationLevel, duration: number = 5000) { + const notification: SnackBarNotification = new SnackBarNotification(); + notification.level = level; + notification.message = message; + notification.duration = duration; + this.notificationSubject.next(notification); + } + + public popupNotification(title: string, message: string) { + const notification: PopupNotification = new PopupNotification(); + notification.title = title; + notification.message = message; + this.notificationSubject.next(notification); + } + + public getNotificationObservable(): Observable { + return this.notificationSubject.asObservable(); + } +} + +export enum UiNotificationType { + SnackBar = 0, + Popup = 1 +} + +export interface UiNotification { + type: UiNotificationType; + +} + +export enum SnackBarNotificationLevel { + Info = 0, + Warning = 1, + Success = 2, + Error = 3 +} + +export class SnackBarNotification implements UiNotification { + type: UiNotificationType = UiNotificationType.SnackBar; + message: string; + level: SnackBarNotificationLevel; + duration: number; +} + +export class PopupNotification implements UiNotification { + type: UiNotificationType = UiNotificationType.Popup; + message: string; + title: string; +} diff --git a/dmp-frontend/src/app/core/services/progress-indication/progress-indication-service.ts b/dmp-frontend/src/app/core/services/progress-indication/progress-indication-service.ts new file mode 100644 index 000000000..08ef8e991 --- /dev/null +++ b/dmp-frontend/src/app/core/services/progress-indication/progress-indication-service.ts @@ -0,0 +1,37 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable } from 'rxjs'; + +@Injectable() +export class ProgressIndicationService { + public progressIndicator: BehaviorSubject; + + private requestsRunning = 0; + + constructor() { + this.progressIndicator = new BehaviorSubject(false); + } + + public getProgressIndicationObservable(): Observable { + return this.progressIndicator.asObservable(); + } + + public list(): number { + return this.requestsRunning; + } + + public show(): void { + this.requestsRunning++; + if (this.requestsRunning === 1) { + this.progressIndicator.next(true); + } + } + + public dismiss(): void { + if (this.requestsRunning > 0) { + this.requestsRunning--; + if (this.requestsRunning === 0) { + this.progressIndicator.next(false); + } + } + } +} diff --git a/dmp-frontend/src/app/core/services/project/project-file-upload.service.ts b/dmp-frontend/src/app/core/services/project/project-file-upload.service.ts new file mode 100644 index 000000000..e72ef95f7 --- /dev/null +++ b/dmp-frontend/src/app/core/services/project/project-file-upload.service.ts @@ -0,0 +1,21 @@ +import { HttpHeaders } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../environments/environment'; +import { ContentFile } from '../../model/project/project'; +import { BaseHttpService } from '../http/base-http.service'; + +@Injectable() +export class ProjectFileUploadService { + + private actionUrl: string; + private headers: HttpHeaders; + + constructor(private http: BaseHttpService) { + this.actionUrl = environment.Server + 'files/'; + } + + uploadFile(formData: FormData): Observable { + return this.http.post(this.actionUrl + 'upload', formData, this.headers); + } +} diff --git a/dmp-frontend/src/app/core/services/project/project.service.ts b/dmp-frontend/src/app/core/services/project/project.service.ts new file mode 100644 index 000000000..209e58b61 --- /dev/null +++ b/dmp-frontend/src/app/core/services/project/project.service.ts @@ -0,0 +1,50 @@ +import { HttpHeaders } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../environments/environment'; +import { RequestItem } from '../../query/request-item'; +import { DataTableData } from '../../model/data-table/data-table-data'; +import { DataTableRequest } from '../../model/data-table/data-table-request'; +import { ProjectModel } from '../../model/project/project'; +import { ProjectListingModel } from '../../model/project/project-listing'; +import { ProjectCriteria } from '../../query/project/project-criteria'; +import { BaseHttpService } from '../http/base-http.service'; + +@Injectable() +export class ProjectService { + + private actionUrl: string; + private headers: HttpHeaders; + + constructor(private http: BaseHttpService) { + this.actionUrl = environment.Server + 'projects/'; + } + + getPaged(dataTableRequest: DataTableRequest): Observable> { + return this.http.post>(this.actionUrl + 'getPaged', dataTableRequest, { headers: this.headers }); + } + + get(requestItem: RequestItem): Observable { + return this.http.post(this.actionUrl + 'get', requestItem, { headers: this.headers }); + } + + getWithExternal(requestItem: RequestItem): Observable { + return this.http.post(this.actionUrl + 'getWithExternal', requestItem, { headers: this.headers }); + } + + getSingle(id: string): Observable { + return this.http.get(this.actionUrl + 'getSingle/' + id, { headers: this.headers }); + } + + createProject(projectModel: ProjectModel): Observable { + return this.http.post(this.actionUrl + 'createOrUpdate', projectModel, { headers: this.headers }); + } + + inactivate(id: String): Observable { + return this.http.delete(this.actionUrl + 'inactivate/' + id, { headers: this.headers }); + } + + public delete(id: string): Observable { + return this.http.delete(this.actionUrl + 'delete' + id, { headers: this.headers }); + } +} diff --git a/dmp-frontend/src/app/core/services/search-bar/search-bar.service.ts b/dmp-frontend/src/app/core/services/search-bar/search-bar.service.ts new file mode 100644 index 000000000..3e2cd1876 --- /dev/null +++ b/dmp-frontend/src/app/core/services/search-bar/search-bar.service.ts @@ -0,0 +1,22 @@ +import { HttpHeaders } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../environments/environment'; +import { SearchBarItem } from '../../model/dashboard/search-bar-item'; +import { BaseHttpService } from '../http/base-http.service'; + +@Injectable() +export class SearchBarService { + + private actionUrl: string; + private headers: HttpHeaders; + + constructor(private http: BaseHttpService) { + + this.actionUrl = environment.Server + 'dashboard/'; + } + + search(like: string): Observable { + return this.http.get(this.actionUrl + 'search?like=' + like, { headers: this.headers }); + } +} diff --git a/dmp-frontend/src/app/core/services/timezone/timezone-service.ts b/dmp-frontend/src/app/core/services/timezone/timezone-service.ts new file mode 100644 index 000000000..095e144b6 --- /dev/null +++ b/dmp-frontend/src/app/core/services/timezone/timezone-service.ts @@ -0,0 +1,38 @@ +import { Injectable } from '@angular/core'; +import * as moment from 'moment'; +import 'moment-timezone'; +import { Observable, Subject } from 'rxjs'; + +@Injectable() +export class TimezoneService { + + private timezoneValues: string[]; + private timezoneChangeSubject = new Subject(); + private currentTimezone: string; + + constructor() { + this.timezoneValues = moment.tz.names(); + } + + getTimezoneValues(): string[] { + return this.timezoneValues; + } + + hasTimezoneValue(timezone: string): boolean { + return this.timezoneValues.includes(timezone); + } + + timezoneSelected(timezone: string) { + if (this.currentTimezone === timezone) { return; } + this.currentTimezone = timezone; + this.timezoneChangeSubject.next(timezone); + } + + getTimezoneChangeObservable(): Observable { + return this.timezoneChangeSubject.asObservable(); + } + + getCurrentTimezone(): string { + return this.currentTimezone; + } +} diff --git a/dmp-frontend/src/app/core/services/user/user.service.ts b/dmp-frontend/src/app/core/services/user/user.service.ts new file mode 100644 index 000000000..38a028b05 --- /dev/null +++ b/dmp-frontend/src/app/core/services/user/user.service.ts @@ -0,0 +1,45 @@ +import { HttpHeaders } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../environments/environment'; +import { DataTableData } from '../../model/data-table/data-table-data'; +import { DataTableRequest } from '../../model/data-table/data-table-request'; +import { UserListingModel } from '../../model/user/user-listing'; +import { UserCriteria } from '../../query/user/user-criteria'; +import { BaseHttpService } from '../http/base-http.service'; + +@Injectable() +export class UserService { + + private actionUrl: string; + private headers: HttpHeaders; + + constructor(private http: BaseHttpService) { + + this.actionUrl = environment.Server + '/user/'; + } + + getPaged(dataTableRequest: DataTableRequest): Observable> { + return this.http.post>(this.actionUrl + 'getPaged', JSON.stringify(dataTableRequest), { headers: this.headers }); + } + + getUser(id: String): Observable { + return this.http.get(this.actionUrl + id, { headers: this.headers }); + } + + updateRoles(itemToUpdate: UserListingModel): Observable { + return this.http.post(this.actionUrl + 'updateRoles', JSON.stringify(itemToUpdate), { headers: this.headers }); + } + + delete(id: String): Observable { + return this.http.delete(this.actionUrl + id, { headers: this.headers }); + } + + getRecentActivity(): Observable { + return this.http.get(this.actionUrl + 'recentActivity', { headers: this.headers }); + } + + updateUserSettings(value: any): Observable { + return this.http.post(this.actionUrl + 'settings', value, { headers: this.headers }); + } +} diff --git a/dmp-frontend/src/app/core/services/utilities/collection-utils.service.ts b/dmp-frontend/src/app/core/services/utilities/collection-utils.service.ts new file mode 100644 index 000000000..43d327e02 --- /dev/null +++ b/dmp-frontend/src/app/core/services/utilities/collection-utils.service.ts @@ -0,0 +1,96 @@ +import { Injectable } from '@angular/core'; + +@Injectable() +export class CollectionUtils { + public static defaultArrayComparer(itemComparer: EqualityComparer = new StrictEqualityComparer()): EqualityComparer { + return new InOrderComparer(itemComparer); + } + + public static defaultIterableComparer(itemComparer: EqualityComparer = new StrictEqualityComparer()): EqualityComparer> { + return new InOrderComparer(itemComparer); + } + + public static asArray(collection: Iterable): ItemType[] { + return asArray(collection); + } + + public equal(left: ItemType[], right: ItemType[], arrayComparer?: EqualityComparer): boolean { + return equal(left, right, arrayComparer); + } + + public setEqual(left: ItemType[], right: ItemType[]): boolean { + return equal(left, right, new SetComparer()); + } + + public any(collection: Iterable, predicate?: (item: ItemType, index: number) => boolean): boolean { + return any(collection, predicate); + } + + public all(collection: Iterable, predicate: (item: ItemType, index: number) => boolean): boolean { + return all(collection, predicate); + } + + public flatten(source: ItemType[][]): ItemType[] { + return source.reduce(flatteningReducer, []); + } +} + +export interface EqualityComparer { + equal(left: ItemType, right: ItemType); +} + +function equal(left: ItemType[], right: ItemType[], arrayComparer?: EqualityComparer): boolean { + arrayComparer = arrayComparer || new InOrderComparer(); + return arrayComparer.equal(left, right); +} + +function any(collection: Iterable, predicate?: (item: ItemType, index: number) => boolean): boolean { + if (!collection) { return false; } + const array = asArray(collection); + if (!predicate) { predicate = () => array.length > 0; } + return array.some(predicate); +} + +function all(collection: Iterable, predicate: (item: ItemType, index: number) => boolean): boolean { + if (!collection) { return false; } + const array = asArray(collection); + let index = 0, result = true; + while (result && index < array.length) { + result = predicate(array[index], index); + index++; + } + return result; +} + +function asArray(collection: Iterable): ItemType[] { + return Array.isArray(collection) ? collection as ItemType[] : Array.from(collection); +} + +function flatteningReducer(target: ItemType[], currentValue: ItemType[]): ItemType[] { + return [...target, ...currentValue]; +} + +export class StrictEqualityComparer implements EqualityComparer { + equal(left: ItemType, right: ItemType) { + return left === right; + } +} + +export class InOrderComparer, ItemType> implements EqualityComparer { + constructor(private itemComparer: EqualityComparer = new StrictEqualityComparer()) { } + equal(left: IterableType, right: IterableType) { + if (!left) { return !right; } + if (!right) { return false; } + const leftArray = asArray(left), rightArray = asArray(right); + return leftArray.length === leftArray.length && all(leftArray, (x, index) => this.itemComparer.equal(x, rightArray[index])); + } +} + +export class SetComparer, ItemType> implements EqualityComparer { + equal(left: IterableType, right: IterableType) { + if (!left) { return !right; } + if (!right) { return false; } + const leftSet = new Set(left), rightSet = new Set(right); + return leftSet.size === rightSet.size && all(leftSet, x => rightSet.has(x)); + } +} diff --git a/dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts b/dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts new file mode 100644 index 000000000..5a2b25d3a --- /dev/null +++ b/dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts @@ -0,0 +1,83 @@ +import { Injectable } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { AppRole } from '../../common/enum/app-role'; +import { DatasetProfileComboBoxType } from '../../common/enum/dataset-profile-combo-box-type'; +import { DatasetProfileFieldViewStyle } from '../../common/enum/dataset-profile-field-view-style'; +import { DatasetStatus } from '../../common/enum/dataset-status'; +import { DmpProfileFieldDataType } from '../../common/enum/dmp-profile-field-type'; +import { DmpProfileType } from '../../common/enum/dmp-profile-type'; +import { DmpStatus } from '../../common/enum/dmp-status'; +import { ValidationType } from '../../common/enum/validation-type'; + +@Injectable() +export class EnumUtils { + constructor(private language: TranslateService) { } + + public getEnumValues(T): Array { + let keys = Object.keys(T); + keys = keys.slice(0, keys.length / 2); + const values: Array = keys.map(Number); + return values; + } + + convertFromPrincipalAppRole(status: AppRole): string { + switch (status) { + case AppRole.Admin: return 'TYPES.APP-ROLE.ADMIN'; + case AppRole.User: return 'TYPES.APP-ROLE.USER'; + case AppRole.Manager: return 'TYPES.APP-ROLE.MANAGER'; + } + } + + toDmpProfileFieldDataTypeString(type: DmpProfileFieldDataType): string { + switch (type) { + case DmpProfileFieldDataType.Date: return 'TYPES.DMP-PROFILE-FIELD.DATA-TYPE.DATE'; + case DmpProfileFieldDataType.Number: return 'TYPES.DMP-PROFILE-FIELD.DATA-TYPE.NUMBER'; + case DmpProfileFieldDataType.Text: return 'TYPES.DMP-PROFILE-FIELD.DATA-TYPE.TEXT'; + } + } + + toDmpProfileTypeString(type: DmpProfileType): string { + switch (type) { + case DmpProfileType.Input: return 'TYPES.DMP-PROFILE-FIELD.TYPE.INPUT'; + } + } + + toDatasetStatusString(status: DatasetStatus): string { + switch (status) { + case DatasetStatus.Draft: return this.language.instant('TYPES.DATASET-STATUS.DRAFT'); + case DatasetStatus.Finalized: return this.language.instant('TYPES.DATASET-STATUS.FINALISED'); + } + } + + toDmpStatusString(status: DmpStatus): string { + switch (status) { + case DmpStatus.Draft: return this.language.instant('TYPES.DMP.DRAFT'); + case DmpStatus.Finalized: return this.language.instant('TYPES.DMP.FINALISED'); + } + } + + toDatasetProfileFieldValidationTypeString(status: ValidationType): string { + switch (status) { + case ValidationType.None: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VALIDATION-TYPE.NONE'); + case ValidationType.Required: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VALIDATION-TYPE.REQUIRED'); + } + } + + toDatasetProfileFieldViewStyleString(status: DatasetProfileFieldViewStyle): string { + switch (status) { + case DatasetProfileFieldViewStyle.BooleanDecision: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.BOOLEAN-DECISION'); + case DatasetProfileFieldViewStyle.CheckBox: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.CHECKBOX'); + case DatasetProfileFieldViewStyle.ComboBox: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.COMBO-BOX'); + case DatasetProfileFieldViewStyle.FreeText: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.FREE-TEXT'); + case DatasetProfileFieldViewStyle.RadioBox: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.RADIO-BOX'); + case DatasetProfileFieldViewStyle.TextArea: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.TEXT-AREA'); + } + } + + toDatasetProfileComboBoxTypeString(status: DatasetProfileComboBoxType): string { + switch (status) { + case DatasetProfileComboBoxType.WordList: return this.language.instant('TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.WORD-LIST'); + case DatasetProfileComboBoxType.Autocomplete: return this.language.instant('TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.AUTOCOMPLETE'); + } + } +} diff --git a/dmp-frontend/src/app/core/services/utilities/type-utils.service.ts b/dmp-frontend/src/app/core/services/utilities/type-utils.service.ts new file mode 100644 index 000000000..c738059f1 --- /dev/null +++ b/dmp-frontend/src/app/core/services/utilities/type-utils.service.ts @@ -0,0 +1,6 @@ +import { Injectable } from '@angular/core'; + +@Injectable() +export class TypeUtils { + public isString(value: any): value is string { return typeof value === 'string'; } +} diff --git a/dmp-frontend/src/app/dataset-profile-form/compositefield-form/compositefield-form.component.html b/dmp-frontend/src/app/dataset-profile-form/compositefield-form/compositefield-form.component.html deleted file mode 100644 index 32f903310..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/compositefield-form/compositefield-form.component.html +++ /dev/null @@ -1,77 +0,0 @@ -
-

Composite Field Description

-
- Composite Field - Multiplicity - Comment -
-
-
- - - -
-
- - - -
-
- - - -
-
-
- -
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- -
- -
-

Field Description

-
- -
-
- - - -
- - - {{i + 1}}. {{form.get('fields').get(''+i).get('title').value}} -
- -
-
-
- -
-
-
diff --git a/dmp-frontend/src/app/dataset-profile-form/compositefield-form/compositefield-form.component.ts b/dmp-frontend/src/app/dataset-profile-form/compositefield-form/compositefield-form.component.ts deleted file mode 100644 index 3b48e17d7..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/compositefield-form/compositefield-form.component.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { FormArray, FormControl } from '@angular/forms'; -import { FieldSet } from '../../models/datasetProfileAdmin/FieldSet'; -import { Field } from '../../models/datasetProfileAdmin/Field'; - -@Component({ - selector: 'app-compositefield-form', - templateUrl: './compositefield-form.component.html', - styleUrls: ['./compositefield-form.component.scss'] -}) - -export class CompositeFieldFormComponent implements OnInit { - @Input() form: FormGroup; - @Input() dataModel: FieldSet; - @Input() indexPath: string; - - isComposite = false; - isMultiplicityEnabled = false; - - constructon() { } - - ngOnInit() { - //this.addNewField(); - if (this.form.get('multiplicity')) { - if (this.form.get('multiplicity').value.min > 1 || this.form.get('multiplicity').value.max > 1) { - this.isMultiplicityEnabled = true; - } - } - this.isComposite = this.dataModel.fields.length > 1; - } - - onIsCompositeChange(isComposite: boolean) { - if (!isComposite && (this.form.get('fields')).length > 1) { - for (let i = 0; i < (this.form.get('fields')).length - 1; i++) { - (this.form.get('fields')).removeAt(1); - } - this.dataModel.fields.splice(1); - } - } - - onIsMultiplicityEnabledChange(isMultiplicityEnabled: boolean) { - if (!isMultiplicityEnabled) { - (this.form.get('multiplicity').get('min')).setValue(0); - (this.form.get('multiplicity').get('max')).setValue(0); - } - } - - addNewField() { - const field: Field = new Field(); - this.dataModel.fields.push(field); - (this.form.get('fields')).push(field.buildForm()); - } - - DeleteField(index) { - this.dataModel.fields.splice(index, 1); - (this.form.get('fields')).removeAt(index); - } -} diff --git a/dmp-frontend/src/app/dataset-profile-form/dataset-profile.module.ts b/dmp-frontend/src/app/dataset-profile-form/dataset-profile.module.ts deleted file mode 100644 index 92c4fbca9..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/dataset-profile.module.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; - -import { DatasetProfileRoutes } from './dataset-profile.router'; -import { RouterModule } from '@angular/router'; - -import { FormComponent } from './form/form.component'; -//import { GroupFieldFormComponent } from './groupfield-form/groupfield-form.component'; -import { RuleFormComponent } from './rule-component/rule.component'; -import { SectionFormComponent } from './section-form/section-form.component'; -import { PageFormComponent } from './page-form/page-component'; -import { CompositeFieldFormComponent } from './compositefield-form/compositefield-form.component'; -import { FieldFormComponent } from './field-form/field-form.component'; -import { HttpClientModule, HttpClient } from '@angular/common/http'; - -import { CheckBoxComponent } from '../shared/componentsAdmin/checkbox/checkbox-component'; -import { FreeTextData } from '../models/DataField/FreeTextData'; -import { BooleanDecisionComponent } from '../shared/componentsAdmin/booleanDecision/booleanDecision-component'; -import { FreeTextComponent } from '../shared/componentsAdmin/freetext/freetext-component'; -import { TextAreaComponent } from '../shared/componentsAdmin/textarea/textarea-component'; -import { RadioBoxComponent } from '../shared/componentsAdmin/radiobox/radiobox-component'; -import { WordlistComponent } from '../shared/componentsAdmin/wordlist/wordlist-component'; -import { AutocompleteComponent } from '../shared/componentsAdmin/autocomplete/autocomplete-component'; -import { ComboboxComponent } from '../shared/componentsAdmin/combobox/combobox-component'; -import { SharedModule } from '../shared/shared.module'; -import { DatasetProfilePreviewerComponent } from './previewer/dataset-profile-previewer.component'; -import { DynamicFormModule } from '../form/dynamic-form.module'; -import { DatasetProfileAdminListingComponent } from './datasets-admin-listing/dataset-profile-admin-listing.component'; -import { TranslateService, TranslateModule, TranslateLoader } from '@ngx-translate/core'; -import { TranslateHttpLoader } from '@ngx-translate/http-loader'; - -@NgModule({ - imports: [ - CommonModule, - FormsModule, - HttpClientModule, - ReactiveFormsModule, - RouterModule, - SharedModule, - DynamicFormModule, - RouterModule.forChild(DatasetProfileRoutes), - TranslateModule.forRoot({ - loader: { - provide: TranslateLoader, - useFactory: HttpLoaderFactory, - deps: [HttpClient] - } - }), - ], - - declarations: [ - FormComponent, - //GroupFieldFormComponent, - RuleFormComponent, - SectionFormComponent, - DatasetProfileAdminListingComponent, - PageFormComponent, - CompositeFieldFormComponent, - FieldFormComponent, - TextAreaComponent, - CheckBoxComponent, - BooleanDecisionComponent, - FreeTextComponent, - ComboboxComponent, - AutocompleteComponent, - WordlistComponent, - RadioBoxComponent, - DatasetProfilePreviewerComponent - ], - - exports: [ - FormComponent, - //GroupFieldFormComponent, - RuleFormComponent, - SectionFormComponent, - PageFormComponent, - CompositeFieldFormComponent, - DatasetProfileAdminListingComponent, - FieldFormComponent, - TextAreaComponent, - CheckBoxComponent, - BooleanDecisionComponent, - FreeTextComponent, - ComboboxComponent, - AutocompleteComponent, - WordlistComponent, - RadioBoxComponent - ], - providers: [ - ], - entryComponents: [ - DatasetProfilePreviewerComponent - ] -}) - - -export class DatasetProfileModule { - constructor(private translate: TranslateService) { - translate.setDefaultLang('en'); - translate.use('en'); - } -} - -export function HttpLoaderFactory(httpClient: HttpClient) { - return new TranslateHttpLoader(httpClient, 'assets/lang/', '.json'); -} diff --git a/dmp-frontend/src/app/dataset-profile-form/dataset-profile.router.ts b/dmp-frontend/src/app/dataset-profile-form/dataset-profile.router.ts deleted file mode 100644 index d649770fc..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/dataset-profile.router.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { RouterModule, Routes } from '@angular/router'; -import { FormComponent } from './form/form.component'; -import { AuthGuard } from '../shared/guards/auth.guard'; -import { DatasetProfileAdminListingComponent } from './datasets-admin-listing/dataset-profile-admin-listing.component'; - -export const DatasetProfileRoutes: Routes = [ - { - path: ':id', - component: FormComponent - }, - { - path: 'clone/:cloneid', - component: FormComponent - }, - { - path: '', - component: DatasetProfileAdminListingComponent, - }, - -]; diff --git a/dmp-frontend/src/app/dataset-profile-form/datasets-admin-listing/dataset-profile-admin-listing.component.html b/dmp-frontend/src/app/dataset-profile-form/datasets-admin-listing/dataset-profile-admin-listing.component.html deleted file mode 100644 index e44aed963..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/datasets-admin-listing/dataset-profile-admin-listing.component.html +++ /dev/null @@ -1,59 +0,0 @@ -
-

{{titlePrefix}} {{'DATASET-PROFILE-LISTING.TITLE' | translate}}

- - - - - - - - - - - - {{'DATASET-PROFILE-LISTING.COLUMNS.NAME' | translate}} - {{row.label}} - - - - - {{'DATASET-PROFILE-LISTING.COLUMNS.DESCRIPTION' | translate}} - {{row.description}} - - - - - {{'DATASET-PROFILE-LISTING.COLUMNS.CREATED' | - translate}} - {{row.created | date:'shortDate'}} - - - - - {{'DATASET-PROFILE-LISTING.COLUMNS.ACTIONS' | translate}} - - - - - - - - - - - - - - - - - - - -
diff --git a/dmp-frontend/src/app/dataset-profile-form/datasets-admin-listing/dataset-profile-admin-listing.component.ts b/dmp-frontend/src/app/dataset-profile-form/datasets-admin-listing/dataset-profile-admin-listing.component.ts deleted file mode 100644 index 6dcc94fb1..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/datasets-admin-listing/dataset-profile-admin-listing.component.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { DataSource } from '@angular/cdk/table'; -import { Component, OnInit, ViewChild } from '@angular/core'; -import { MatPaginator, MatSnackBar, MatSort, PageEvent } from '@angular/material'; -import { ActivatedRoute, Params, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { DatasetProfileCriteria } from '../../models/criteria/dataset-profile/DatasetProfileCriteria'; -import { DataManagementPlanModel } from '../../models/data-managemnt-plans/DataManagementPlanModel'; -import { DataTableRequest } from '../../models/data-table/DataTableRequest'; -import { DatasetListingModel } from '../../models/datasets/DatasetListingModel'; -import { DataManagementPlanService } from '../../services/data-management-plan/data-management-plan.service'; -import { DatasetProfileAdmin } from '../../services/datasetProfileAdmin/datasetProfileAfmin.service'; -import { DatasetProfileCriteriaComponent } from '../../shared/components/criteria/dataset-profile/dataset-profile.component'; - -@Component({ - selector: 'app-dataset-profile-admin-listing-component', - templateUrl: 'dataset-profile-admin-listing.component.html', - styleUrls: ['./dataset-profile-admin-listing.component.scss'], - providers: [DatasetProfileAdmin, DataManagementPlanService] -}) -export class DatasetProfileAdminListingComponent extends BaseComponent implements OnInit { - - @ViewChild(MatPaginator) _paginator: MatPaginator; - @ViewChild(MatSort) sort: MatSort; - @ViewChild(DatasetProfileCriteriaComponent) criteria: DatasetProfileCriteriaComponent; - - - dataSource: DatasetDataSource | null; - displayedColumns: String[] = ['label', 'description', 'created', 'actions']; - pageEvent: PageEvent; - titlePrefix: String; - dmpId: String; - - statuses = [ - { value: '0', viewValue: 'Active' }, - { value: '1', viewValue: 'Inactive' } - ]; - - constructor( - private datasetService: DatasetProfileAdmin, - private router: Router, - private languageService: TranslateService, - public snackBar: MatSnackBar, - public route: ActivatedRoute, - public dataManagementPlanService: DataManagementPlanService - ) { - super(); - } - - - ngOnInit() { - this.route.params - .pipe(takeUntil(this._destroyed)) - .subscribe((params: Params) => { - this.dmpId = params['dmpId']; - if (this.dmpId != null) { this.setDmpTitle(this.dmpId); } - this.criteria.setCriteria(this.getDefaultCriteria(this.dmpId)); - this.refresh(); - this.criteria.setRefreshCallback(() => this.refresh()); - }); - } - - setDmpTitle(dmpId: String) { - this.dataManagementPlanService.getSingle(dmpId).map(data => data as DataManagementPlanModel) - .pipe(takeUntil(this._destroyed)) - .subscribe(data => { - this.titlePrefix = data.label; - }); - } - - refresh() { - this.dataSource = new DatasetDataSource(this.datasetService, this._paginator, this.sort, this.languageService, this.snackBar, this.criteria); - } - - rowClick(rowId: String) { - this.router.navigate(['dataset-profile/' + rowId]); - } - - getDefaultCriteria(dmpId: String): DatasetProfileCriteria { - const defaultCriteria = new DatasetProfileCriteria(); - - return defaultCriteria; - } - - clone(id: string) { - this.router.navigate(['dataset-profile/clone/' + id]); - } - - // makeItPublic(id: String) { - // debugger; - // this.datasetService.makeDatasetPublic(id).pipe(takeUntil(this._destroyed)).subscribe(); - // } - -} - -export class DatasetDataSource extends DataSource { - - totalCount = 0; - isLoadingResults = false; - - constructor( - private _service: DatasetProfileAdmin, - private _paginator: MatPaginator, - private _sort: MatSort, - private _languageService: TranslateService, - private _snackBar: MatSnackBar, - private _criteria: DatasetProfileCriteriaComponent - ) { - super(); - - } - - connect(): Observable { - const displayDataChanges = [ - this._paginator.page - //this._sort.matSortChange - ]; - - return Observable.merge(...displayDataChanges) - .startWith(null) - .switchMap(() => { - setTimeout(() => { - this.isLoadingResults = true; - }); - const startIndex = this._paginator.pageIndex * this._paginator.pageSize; - let fields: Array = new Array(); - if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; } - const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); - request.criteria = this._criteria.criteria; - return this._service.getPaged(request); - }) - /*.catch((error: any) => { - this._snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService }, - duration: 3000, - extraClasses: ['snackbar-warning'] - }); - //this._criteria.criteria.onCallbackError(error); - return Observable.of(null); - })*/ - .map(result => { - setTimeout(() => { - this.isLoadingResults = false; - }); - return result; - }) - .map(result => { - if (!result) { return []; } - if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; } - return result.data; - }); - } - - disconnect() { - // No-op - } -} diff --git a/dmp-frontend/src/app/dataset-profile-form/field-form/field-form.component.html b/dmp-frontend/src/app/dataset-profile-form/field-form/field-form.component.html deleted file mode 100644 index c647b08d4..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/field-form/field-form.component.html +++ /dev/null @@ -1,104 +0,0 @@ -
-
-
- - - -
- - - textarea - booleanDecision - combobox - checkBox - freetext - radiobox - - -
-
-
- -
-
-
Multiplicity
- - - - - - - -
-
- - - -
-
- - - -
-
-
-
- - - {{option.value}} - - -
-
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- Multiplicity -
-

Rules Description

- -
- - - {{i + 1}}. Rule {{i + 1}} - -
- -
-
- -
-
diff --git a/dmp-frontend/src/app/dataset-profile-form/field-form/field-form.component.ts b/dmp-frontend/src/app/dataset-profile-form/field-form/field-form.component.ts deleted file mode 100644 index 37dd1ea4b..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/field-form/field-form.component.ts +++ /dev/null @@ -1,56 +0,0 @@ - -import { Component, Input, OnInit } from '@angular/core'; -import { FormGroup, FormControl, FormArray } from '@angular/forms'; -import { ValidationTypes } from '../../models/common/ValidationTypes'; -import { Field } from '../../models/datasetProfileAdmin/Field'; -import { Rule } from '../../models/datasetProfileAdmin/Rule'; - -@Component({ - selector: 'app-field-form', - templateUrl: './field-form.component.html', - styleUrls: ['./field-form.component.scss'] -}) - -export class FieldFormComponent implements OnInit { - @Input() form: FormGroup; - @Input() dataModel: Field; - @Input() showMultiplicity = true; - @Input() indexPath: string; - validationsOptions: Array; - isFieldMultiplicityEnabled = false; - - constructon() { - } - - ngOnInit() { - if (this.form.get('multiplicity')) { - if (this.form.get('multiplicity').value.min > 1 || this.form.get('multiplicity').value.max > 1) { - this.isFieldMultiplicityEnabled = true; - } - } - this.validationsOptions = [{ key: 0, value: ValidationTypes[0] }, { key: 1, value: ValidationTypes[1] }]; - // this.addNewRule(); - } - - onIsFieldMultiplicityEnabledChange(isFieldMultiplicityEnabled: boolean) { - if (!isFieldMultiplicityEnabled) { - (this.form.get('multiplicity').get('min')).setValue(0); - (this.form.get('multiplicity').get('max')).setValue(0); - } - } - - addNewRule() { - const rule: Rule = new Rule(); - this.dataModel.visible.rules.push(rule); - (this.form.get('visible').get('rules')).push(rule.buildForm()); - } - - DeleteRule(index) { - this.dataModel.visible.rules.splice(index, 1); - (this.form.get('visible').get('rules')).removeAt(index); - } - - onchangeCombo() { - if (this.form.get('data')) { this.form.removeControl('data'); } - } -} diff --git a/dmp-frontend/src/app/dataset-profile-form/form/form.component.html b/dmp-frontend/src/app/dataset-profile-form/form/form.component.html deleted file mode 100644 index d3a5c212d..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/form/form.component.html +++ /dev/null @@ -1,72 +0,0 @@ -
- - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - - - - - {{'DATASET-PROFILE.PAGES-DESCRIPTION' | translate}} -
-
- - - {{i + - 1}}.{{form.get('pages').at(i).get('title').value}} -
- -
-
-
-
- -
-
-
-
-
- -
-
-
- - {{'DATASET-PROFILE.FORM-DESCRIPTION' | translate}} -
-
- - - {{i + 1}}. - {{form.get('sections').get(''+i).get('title').value}} -
- -
-
-
-
- -
-
-
-
-
- -
-
-
- - {{'DATASET-PROFILE.PREVIEW' | translate}} -
- -
-
-
- -
diff --git a/dmp-frontend/src/app/dataset-profile-form/form/form.component.scss b/dmp-frontend/src/app/dataset-profile-form/form/form.component.scss deleted file mode 100644 index a013c86bc..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/form/form.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.full-width { - width: 100%; - } diff --git a/dmp-frontend/src/app/dataset-profile-form/form/form.component.ts b/dmp-frontend/src/app/dataset-profile-form/form/form.component.ts deleted file mode 100644 index 0064c080c..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/form/form.component.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core'; -import { FormArray, FormControl, FormGroup } from '@angular/forms'; -import { MatDialog, MatHorizontalStepper } from '@angular/material'; -import { ActivatedRoute, Router } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { DatasetProfileModelAdmin } from '../../models/datasetProfileAdmin/DatasetProfileModelAdmin'; -import { Page } from '../../models/datasetProfileAdmin/Page'; -import { Section } from '../../models/datasetProfileAdmin/Section'; -import { DatasetProfileDefinitionModel } from '../../models/DatasetProfileDefinitionModel'; -import { DatasetWizardModel } from '../../models/datasets/DatasetWizardModel'; -import { DatasetProfileService } from '../../services/dataset-profile.service'; -import { DatasetProfileAdmin } from '../../services/datasetProfileAdmin/datasetProfileAfmin.service'; -import { JsonSerializer } from '../../utilities/JsonSerializer'; - -@Component({ - selector: 'app-form-component', - templateUrl: './form.component.html', - providers: [DatasetProfileAdmin, DatasetProfileService], - styleUrls: ['./form.component.scss'] -}) - -export class FormComponent extends BaseComponent implements OnInit, AfterViewInit { - - - dataModel: DatasetProfileModelAdmin; - form: FormGroup; - previewerFormGroup: FormGroup; - private profileID: string; - private cloneId: string; - dataWizardModel: DatasetWizardModel; - @ViewChild('stepper') stepper: MatHorizontalStepper; - constructor( - public datasetprofileAdmin: DatasetProfileAdmin, - private datasetProfileService: DatasetProfileService, - private datasetProfileAdminService: DatasetProfileAdmin, - private route: ActivatedRoute, - private router: Router, - public dialog: MatDialog, - ) { - super(); - this.profileID = route.snapshot.params['id']; - this.cloneId = route.snapshot.params['cloneid']; - } - - ngAfterViewInit(): void { - console.log(this.stepper); - } - - ngOnInit() { - - this.dataModel = JsonSerializer.fromJSONObject(new DatasetProfileModelAdmin(), DatasetProfileModelAdmin); - if (this.profileID) { - this.datasetProfileService.getDatasetProfileById(this.profileID) - .pipe(takeUntil(this._destroyed)) - .subscribe((data) => { - this.dataModel = JsonSerializer.fromJSONObject(data, DatasetProfileModelAdmin); - this.form = this.dataModel.buildForm(); - this.form.valueChanges - .pipe(takeUntil(this._destroyed)) - .subscribe(change => { - this.datasetProfileAdminService.preview(this.dataModel) - .pipe(takeUntil(this._destroyed)) - .subscribe(dataset => { - const datasetModel = new DatasetWizardModel(); - datasetModel.datasetProfileDefinition = JsonSerializer.fromJSONObject(dataset, DatasetProfileDefinitionModel); - this.dataWizardModel = datasetModel; - this.previewerFormGroup = this.dataWizardModel.buildForm().get('datasetProfileDefinition'); - }); - }); - this.form.updateValueAndValidity(); - }); - } else if (this.cloneId) { - this.datasetprofileAdmin.clone(this.cloneId) - .pipe(takeUntil(this._destroyed)) - .subscribe((data) => { - this.dataModel = JsonSerializer.fromJSONObject(data, DatasetProfileModelAdmin); - this.form = this.dataModel.buildForm(); - this.form.valueChanges - .pipe(takeUntil(this._destroyed)) - .subscribe(change => { - this.datasetProfileAdminService.preview(this.dataModel) - .pipe(takeUntil(this._destroyed)) - .subscribe(dataset => { - const datasetModel = new DatasetWizardModel(); - datasetModel.datasetProfileDefinition = JsonSerializer.fromJSONObject(dataset, DatasetProfileDefinitionModel); - this.dataWizardModel = datasetModel; - this.previewerFormGroup = this.dataWizardModel.buildForm().get('datasetProfileDefinition'); - }); - }); - this.form.updateValueAndValidity(); - }); - } else { - this.addSection(); - this.addPage(); - } - } - - onIsMultiplicityEnabledChange(isMultiplicityEnabled: boolean) { - if (!isMultiplicityEnabled) { - (this.form.get('multiplicity').get('min')).setValue(0); - (this.form.get('multiplicity').get('max')).setValue(0); - } - } - - addSection() { - const section: Section = new Section(); - this.dataModel.sections.push(section); - (this.form.get('sections')).push(section.buildForm()); - } - - addPage() { - const page: Page = new Page(this.dataModel.pages.length); - this.dataModel.pages.push(page); - (this.form.get('pages')).push(page.buildForm()); - } - - DeleteSection(index) { - this.dataModel.sections.splice(index, 1); - (this.form.get('sections')).removeAt(index); - } - - DeletePage(index) { - this.dataModel.pages.splice(index, 1); - (this.form.get('pages')).removeAt(index); - } - - createForm(data) { - return this.datasetprofileAdmin.createForm(data); - } - updateForm(id, data) { - return this.datasetprofileAdmin.updateForm(id, data); - } - - onSubmit() { - const data = this.form.value; - - if (this.profileID) { - this.updateForm(this.profileID, data) - .pipe(takeUntil(this._destroyed)) - .subscribe(() => { - this.router.navigate(['/dataset-profile']); - }); - } else { - this.createForm(data) - .pipe(takeUntil(this._destroyed)) - .subscribe(() => { - this.router.navigate(['/dataset-profile']); - }); - } - } - - isStepActive(step: number) { - return this.stepper && this.stepper.selectedIndex === step; - } -} diff --git a/dmp-frontend/src/app/dataset-profile-form/page-form/page-component.html b/dmp-frontend/src/app/dataset-profile-form/page-form/page-component.html deleted file mode 100644 index ed248310f..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/page-form/page-component.html +++ /dev/null @@ -1,9 +0,0 @@ -
-
-
- - - -
-
-
diff --git a/dmp-frontend/src/app/dataset-profile-form/page-form/page-component.ts b/dmp-frontend/src/app/dataset-profile-form/page-form/page-component.ts deleted file mode 100644 index c1d58f859..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/page-form/page-component.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Component, Input, Output, EventEmitter } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { Page } from '../../models/datasetProfileAdmin/Page'; - - -@Component({ - selector: 'app-page-form', - templateUrl: './page-component.html', - styleUrls: ['./page-component.scss'] -}) - -export class PageFormComponent { - @Input() form: FormGroup; - @Input() dataModel: Page; - - TargetValidation() { - } - -} diff --git a/dmp-frontend/src/app/dataset-profile-form/previewer/dataset-profile-previewer.component.ts b/dmp-frontend/src/app/dataset-profile-form/previewer/dataset-profile-previewer.component.ts deleted file mode 100644 index 05180f86f..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/previewer/dataset-profile-previewer.component.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Component, Inject, OnInit, ViewEncapsulation } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { DatasetProfileDefinitionModel } from '../../models/DatasetProfileDefinitionModel'; -import { DatasetWizardModel } from '../../models/datasets/DatasetWizardModel'; -import { DatasetProfileAdmin } from '../../services/datasetProfileAdmin/datasetProfileAfmin.service'; -import { JsonSerializer } from '../../utilities/JsonSerializer'; - -@Component({ - selector: 'app-dataset-profile-previewer', - templateUrl: './dataset-profile-previewer.component.html', - styleUrls: ['./dataset-profile-previewer.component.scss'], - encapsulation: ViewEncapsulation.None -}) - -export class DatasetProfilePreviewerComponent extends BaseComponent implements OnInit { - formGroup: FormGroup; - datasetWizardModel: DatasetWizardModel; - constructor( - private datasetProfileAdminService: DatasetProfileAdmin, - public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any - ) { super(); } - - ngOnInit(): void { - - this.datasetProfileAdminService.preview(this.data['model']) - .pipe(takeUntil(this._destroyed)) - .subscribe(x => { - this.datasetWizardModel = new DatasetWizardModel(); - this.datasetWizardModel.datasetProfileDefinition = JsonSerializer.fromJSONObject(x, DatasetProfileDefinitionModel); - this.formGroup = this.datasetWizardModel.buildForm().get('datasetProfileDefinition'); - }); - - } -} diff --git a/dmp-frontend/src/app/dataset-profile-form/rule-component/rule.component.html b/dmp-frontend/src/app/dataset-profile-form/rule-component/rule.component.html deleted file mode 100644 index 98e304860..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/rule-component/rule.component.html +++ /dev/null @@ -1,23 +0,0 @@ -
-
-
-
- - - field value - - -
-
- - - -
-
- - - -
-
-
-
diff --git a/dmp-frontend/src/app/dataset-profile-form/rule-component/rule.component.ts b/dmp-frontend/src/app/dataset-profile-form/rule-component/rule.component.ts deleted file mode 100644 index 34980934f..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/rule-component/rule.component.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Component, Input } from '@angular/core'; -import { FormGroup } from '@angular/forms'; - -@Component({ - selector: 'app-rule-form', - templateUrl: './rule.component.html', - styleUrls: ['./rule.component.scss'] -}) - -export class RuleFormComponent { - @Input() form: FormGroup; - @Input() dataModel: FormGroup; - - TargetValidation() { - } - -} diff --git a/dmp-frontend/src/app/dataset-profile-form/section-form/section-form.component.html b/dmp-frontend/src/app/dataset-profile-form/section-form/section-form.component.html deleted file mode 100644 index 6f6db96f9..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/section-form/section-form.component.html +++ /dev/null @@ -1,127 +0,0 @@ -
-
-

Section Description

-
- -
-
- -
-
- - - -
-
- - - -
-
- - - {{pageGroup.get('title').value}} - - - -
-
-
-
- - - -
-
- - - true - false - -
-
- -
- - - {{i + 1}}. {{form.get('sections').get(''+i).get('title').value}} -
- -
-
-
- -
-
-
- - - - - - - -
-
-

Field Sets

-
- -
-
- - - - - {{i + 1}}. Field {{i + 1}} - -
- -
-
- - - -
-
- - - - -
diff --git a/dmp-frontend/src/app/dataset-profile-form/section-form/section-form.component.scss b/dmp-frontend/src/app/dataset-profile-form/section-form/section-form.component.scss deleted file mode 100644 index 4a04dea81..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/section-form/section-form.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.full-width { - width: 90%; -} diff --git a/dmp-frontend/src/app/dataset-profile-form/section-form/section-form.component.ts b/dmp-frontend/src/app/dataset-profile-form/section-form/section-form.component.ts deleted file mode 100644 index 0cbee6087..000000000 --- a/dmp-frontend/src/app/dataset-profile-form/section-form/section-form.component.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; -import { FormArray, FormGroup } from '@angular/forms'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { Field } from '../../models/datasetProfileAdmin/Field'; -import { FieldSet } from '../../models/datasetProfileAdmin/FieldSet'; -import { Page } from '../../models/datasetProfileAdmin/Page'; -import { Section } from '../../models/datasetProfileAdmin/Section'; -import { JsonSerializer } from '../../utilities/JsonSerializer'; - -@Component({ - selector: 'app-section-form', - templateUrl: './section-form.component.html', - styleUrls: ['./section-form.component.scss'], - encapsulation: ViewEncapsulation.None -}) - -export class SectionFormComponent extends BaseComponent implements OnInit { - @Input() form: FormGroup; - @Input() dataModel: Section; - @Input() indexPath: string; - - constructor() { super(); } - - ngOnInit() { - this.form.root.get('pages').valueChanges - .pipe(takeUntil(this._destroyed)) - .subscribe(x => - this.keepPageSelectionValid(x) - ); - } - - addField() { - const fieldSet: FieldSet = new FieldSet(); - const field: Field = new Field(); - fieldSet.fields.push(field); - if (this.dataModel.fieldSets) { - this.dataModel.fieldSets.push(fieldSet); - } - (this.form.get('fieldSets')).push(fieldSet.buildForm()); - } - - addSectioninSection() { - const section: Section = new Section(); - this.dataModel.sections.push(section); - (this.form.get('sections')).push(section.buildForm()); - } - - DeleteSectionInSection(index) { - this.dataModel.sections.splice(index); - (this.form.get('sections')).removeAt(index); - } - - DeleteFieldSet(index) { - this.dataModel.fieldSets.splice(index, 1); - (this.form.get('fieldSets')).removeAt(index); - } - - keepPageSelectionValid(pagesJson: Array) { - const selectedPage = this.form.get('page').value as String; - const pages: Array = JsonSerializer.fromJSONArray(pagesJson, Page); - if (pages.find(elem => elem.id === selectedPage) === undefined) { - this.form.get('page').reset(); - } - } -} diff --git a/dmp-frontend/src/app/datasets/dataset-public/dataset-public-listing.component.html b/dmp-frontend/src/app/datasets/dataset-public/dataset-public-listing.component.html deleted file mode 100644 index 451b50bf3..000000000 --- a/dmp-frontend/src/app/datasets/dataset-public/dataset-public-listing.component.html +++ /dev/null @@ -1,91 +0,0 @@ -
-

{{'DATASET-PUBLIC-LISTING.TITLE' | translate}} {{titlePrefix}}

-
-
- - - -
-
-
- - - - - - - - - - {{'DATASET-LISTING.COLUMNS.NAME' | translate}} - {{row.label}} - - - - - {{'DATASET-LISTING.COLUMNS.PROJECT' | - translate}} - {{row.project}} - - - - - {{'DATASET-LISTING.COLUMNS.PROFILE' - | translate}} - {{row.profile}} - - - - - - - - - - - - - - - - - {{'DATASET-LISTING.COLUMNS.DESCRIPTION' | translate}} - {{row.description}} - - - - - {{'DATASET-LISTING.COLUMNS.CREATED' | - translate}} - {{row.created | date:'shortDate'}} - - - - - - - - - - - - - -
- -
-
-
diff --git a/dmp-frontend/src/app/datasets/dataset-public/dataset-public-listing.component.ts b/dmp-frontend/src/app/datasets/dataset-public/dataset-public-listing.component.ts deleted file mode 100644 index 4109bdde6..000000000 --- a/dmp-frontend/src/app/datasets/dataset-public/dataset-public-listing.component.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { DataSource } from '@angular/cdk/table'; -import { Component, OnInit, ViewChild } from '@angular/core'; -import { MatPaginator, MatSnackBar, MatSort, PageEvent } from '@angular/material'; -import { ActivatedRoute, Params, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { DatasetCriteria } from '../../models/criteria/dataset/DatasetCriteria'; -import { DataTableRequest } from '../../models/data-table/DataTableRequest'; -import { DatasetListingModel } from '../../models/datasets/DatasetListingModel'; -import { FacetSearchCriteriaModel } from '../../models/facet-search/FacetSearchCriteriaModel'; -import { DataManagementPlanService } from '../../services/data-management-plan/data-management-plan.service'; -import { DatasetService } from '../../services/dataset/dataset.service'; - - -@Component({ - selector: 'app-dataset-public-listing-component', - templateUrl: 'dataset-public-listing.component.html', - styleUrls: ['./dataset-public-listing.component.scss'], -}) -export class DatasetPublicListingComponent extends BaseComponent implements OnInit { - - @ViewChild(MatPaginator) _paginator: MatPaginator; - @ViewChild(MatSort) sort: MatSort; - criteria: FacetSearchCriteriaModel; - - dataSource: DatasetDataSource | null; - displayedColumns: String[] = ['label', 'project', 'profile', 'description', 'created']; - pageEvent: PageEvent; - titlePrefix: String; - dmpId: string; - - constructor( - private datasetService: DatasetService, - private router: Router, - private languageService: TranslateService, - public snackBar: MatSnackBar, - public route: ActivatedRoute, - public dataManagementPlanService: DataManagementPlanService - ) { - super(); - } - - ngOnInit() { - - this.route.params - .pipe(takeUntil(this._destroyed)) - .subscribe(async (params: Params) => { - this.dmpId = params['dmpId']; - this.refresh(); - if (this.dmpId != null) { - const dmp = await this.dataManagementPlanService.getSingle(this.dmpId).toPromise(); - if (params['dmpLabel'] !== undefined) { - this.titlePrefix = 'for ' + params['dmpLabel']; - } - } - }); - } - - onCriteriaChange(event: FacetSearchCriteriaModel) { - //console.log(event) - this.criteria = event; - this.refresh(); - } - - refresh() { - this.dataSource = new DatasetDataSource(this.datasetService, this._paginator, this.sort, this.languageService, this.snackBar, this.criteria, this.dmpId); - } - - rowClick(rowId: String) { - this.router.navigate(['/datasets/publicEdit/' + rowId]); - } - - getDefaultCriteria(dmpId: String): DatasetCriteria { - const defaultCriteria = new DatasetCriteria(); - if (dmpId != null) { - defaultCriteria.dmpIds.push(dmpId); - } - return defaultCriteria; - } - - makeItPublic(id: String) { - this.datasetService.makeDatasetPublic(id) - .pipe(takeUntil(this._destroyed)) - .subscribe(); - } -} - -export class DatasetDataSource extends DataSource { - - totalCount = 0; - isLoadingResults = false; - constructor( - private _service: DatasetService, - private _paginator: MatPaginator, - private _sort: MatSort, - private _languageService: TranslateService, - private _snackBar: MatSnackBar, - private _criteria: FacetSearchCriteriaModel, - private dmpId: String - ) { - super(); - - } - - connect(): Observable { - const displayDataChanges = [ - this._paginator.page - //this._sort.matSortChange - ]; - - - return Observable.merge(...displayDataChanges) - .startWith(null) - .switchMap(() => { - setTimeout(() => { - this.isLoadingResults = true; - }); - const startIndex = this._paginator.pageIndex * this._paginator.pageSize; - let fields: Array = new Array(); - if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; } - const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); - request.criteria = this._criteria; - //if (this.dmpId) request.criteria.allVersions = true; - return this._service.getPublicPaged(request); - }) - /*.catch((error: any) => { - this._snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService }, - duration: 3000, - extraClasses: ['snackbar-warning'] - }); - //this._criteria.criteria.onCallbackError(error); - return Observable.of(null); - })*/ - .map(result => { - setTimeout(() => { - this.isLoadingResults = false; - }); - return result; - }) - .map(result => { - if (!result) { return []; } - if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; } - return result.data; - }); - } - - disconnect() { - // No-op - } -} diff --git a/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/datarepository/datarepository-referenced-model-helper.component.ts b/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/datarepository/datarepository-referenced-model-helper.component.ts deleted file mode 100644 index a781cb594..000000000 --- a/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/datarepository/datarepository-referenced-model-helper.component.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Component, Inject, OnInit, ViewEncapsulation } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; -import { ActivatedRoute, Router } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { DataRepositoryModel } from '../../../models/dataRepositories/DataRepositoryModel'; -import { DataRepositoryService } from '../../../services/datarepository/datarepository.service'; - -@Component({ - selector: 'app-datarepository-referenced-model-helper', - templateUrl: 'datarepository-referenced-model-helper.component.html', - styleUrls: ['./datarepository-referenced-model-helper.component.scss'], - encapsulation: ViewEncapsulation.None -}) -export class DataRepositoryReferencedModelHelperComponent extends BaseComponent implements OnInit { - public formGroup: FormGroup; - - constructor( - private dataRepositoryService: DataRepositoryService, - private route: ActivatedRoute, - public router: Router, - public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any - ) { super(); } - - ngOnInit(): void { - const datarepo = new DataRepositoryModel(); - this.formGroup = datarepo.buildForm(); - } - - - send(value: any) { - this.dataRepositoryService.create(this.formGroup.value) - .pipe(takeUntil(this._destroyed)) - .subscribe( - (item) => this.dialogRef.close(item) - ); - } -} diff --git a/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/externalDataset/externaldataset-referenced-model-helper.component.ts b/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/externalDataset/externaldataset-referenced-model-helper.component.ts deleted file mode 100644 index 623454d3a..000000000 --- a/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/externalDataset/externaldataset-referenced-model-helper.component.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Component, Inject, OnInit, ViewEncapsulation } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; -import { ActivatedRoute, Router } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { ExternalDatasetModel } from '../../../models/external-dataset/ExternalDatasetModel'; -import { ExternalDatasetService } from '../../../services/external-dataset/external-dataset.service'; - -@Component({ - selector: 'app-externaldataset-referenced-model-helper', - templateUrl: 'externaldataset-referenced-model-helper.component.html', - styleUrls: ['./externaldataset-referenced-model-helper.component.scss'], - encapsulation: ViewEncapsulation.None -}) -export class ExternalDatasetReferencedModelHelperComponent extends BaseComponent implements OnInit { - public formGroup: FormGroup; - - constructor( - private externalDatasetService: ExternalDatasetService, - private route: ActivatedRoute, - public router: Router, - public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any - ) { super(); } - - ngOnInit(): void { - const externalDatasetModel = new ExternalDatasetModel(); - this.formGroup = externalDatasetModel.buildForm(); - } - - - send(value: any) { - this.externalDatasetService.create(this.formGroup.value) - .pipe(takeUntil(this._destroyed)) - .subscribe( - (item) => this.dialogRef.close(item) - ); - } -} diff --git a/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/registry/registry-referenced-model-helper.component.ts b/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/registry/registry-referenced-model-helper.component.ts deleted file mode 100644 index 48e8728e9..000000000 --- a/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/registry/registry-referenced-model-helper.component.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Component, Inject, OnInit, ViewEncapsulation } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; -import { ActivatedRoute, Router } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { RegisterModel } from '../../../models/registers/RegisterModel'; -import { RegistryService } from '../../../services/registries/registry.service'; - -@Component({ - selector: 'app-registry-referenced-model-helper', - templateUrl: 'registry-referenced-model-helper.component.html', - styleUrls: ['./registry-referenced-model-helper.component.scss'], - encapsulation: ViewEncapsulation.None -}) -export class RegistryReferencedModelHelperComponent extends BaseComponent implements OnInit { - public formGroup: FormGroup; - - constructor( - private registryService: RegistryService, - private route: ActivatedRoute, - public router: Router, - public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any - ) { super(); } - - ngOnInit(): void { - const registryModel = new RegisterModel(); - this.formGroup = registryModel.buildForm(); - } - - - send(value: any) { - this.registryService.create(this.formGroup.value) - .pipe(takeUntil(this._destroyed)) - .subscribe( - (item) => this.dialogRef.close(item) - ); - } -} diff --git a/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/services/services-referenced-model-helper.component.ts b/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/services/services-referenced-model-helper.component.ts deleted file mode 100644 index 83492e7d5..000000000 --- a/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/services/services-referenced-model-helper.component.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Component, Inject, OnInit, ViewEncapsulation } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; -import { ActivatedRoute, Router } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { ServiceModel } from '../../../models/services/ServiceModel'; -import { ServicesDataService } from '../../../services/services/services-data.service'; - -@Component({ - selector: 'app-services-referenced-model-helper', - templateUrl: 'services-referenced-model-helper.component.html', - styleUrls: ['./services-referenced-model-helper.component.scss'], - encapsulation: ViewEncapsulation.None -}) -export class ServicesReferencedModelHelperComponent extends BaseComponent implements OnInit { - public formGroup: FormGroup; - - constructor( - private registryService: ServicesDataService, - private route: ActivatedRoute, - public router: Router, - public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any - ) { super(); } - - ngOnInit(): void { - const serviceModel = new ServiceModel(); - this.formGroup = serviceModel.buildForm(); - } - - - send() { - this.registryService.create(this.formGroup.value) - .pipe(takeUntil(this._destroyed)) - .subscribe( - (item) => this.dialogRef.close(item) - ); - } -} diff --git a/dmp-frontend/src/app/datasets/dataset-wizard/dataset-wizard.component.html b/dmp-frontend/src/app/datasets/dataset-wizard/dataset-wizard.component.html deleted file mode 100644 index 42b50b304..000000000 --- a/dmp-frontend/src/app/datasets/dataset-wizard/dataset-wizard.component.html +++ /dev/null @@ -1,251 +0,0 @@ -
-

{{ 'DATASET-WIZARD.TITLE.NEW' | translate }}

-
-
-

{{datasetWizardModel?.label}} {{ 'GENERAL.NAMES.DATASET' | translate }}

-

- {{ 'GENERAL.STATUSES.EDIT' | translate }}

-

- {{'GENERAL.STATUSES.FINALISED' | translate }}

-
-
- - -
-
- - - - - -
-
-
- - - {{'DATASET-WIZARD.FIRST-STEP.TITLE' | translate}} -
-
- - - - - - {{profile.label}} - - - {{baseErrorModel['Criteria.status']}} - - -
-
-
-
-
-
-
-
-
- - {{'DATASET-WIZARD.SECOND-STEP.TITLE' | translate}} -
-
- -
-
-

{{'DATASET-EDITOR.FIELDS.DATAREPOSITORIES' | translate}}

-
-
-
-
-
- - - -
- - {{i+1}}) {{suggestion.get('label').value}} - -
- - - -
-
- -
-
-
-
- -
-
-

{{'DATASET-EDITOR.FIELDS.EXTERNAL-DATASETS' | translate}}

-
-
-
-
-
- - - - -
-
-

- {{i+1}}) {{suggestion.get('label').value}} -

-
-
- - - -
- -
- - - {{'TYPES.EXTERNAL-DATASET-TYPE.SOURCE' | translate}} - {{'TYPES.EXTERNAL-DATASET-TYPE.OUTPUT' | translate}} - - -
-
- -
-
-
-
- - -
-
-

{{'DATASET-EDITOR.FIELDS.REGISTRIES' | translate}}

-
-
-
-
-
- - - - -
-
-

- {{i+1}}) {{suggestion.get('label').value}} -

-
-
- -
-
-
-
- - -
-
-

{{'DATASET-EDITOR.FIELDS.SERVICES' | translate}}

-
-
- -
-
-
- - - - -
-
-

- {{i+1}}) {{suggestion.get('label').value}} -

-
-
- -
-
-
-
- - -
-
-

{{'DATASET-EDITOR.FIELDS.TAGS' | translate}}

-
-
- - - - -
-
-

- {{i+1}}) {{suggestion.get('name').value}} -

-
-
- -
-
-
-
-
-
- -
- -
-
-
- - {{'DATASET-WIZARD.THIRD-STEP.TITLE' | translate}} -
- -
-
-
- -
-
-
-
- -
-
-
diff --git a/dmp-frontend/src/app/datasets/dataset-wizard/dataset-wizard.component.ts b/dmp-frontend/src/app/datasets/dataset-wizard/dataset-wizard.component.ts deleted file mode 100644 index ba786ffc7..000000000 --- a/dmp-frontend/src/app/datasets/dataset-wizard/dataset-wizard.component.ts +++ /dev/null @@ -1,544 +0,0 @@ -import { AfterViewInit, Component, OnInit, ViewChild, ViewContainerRef } from '@angular/core'; -import { FormArray, FormGroup } from '@angular/forms'; -import { MatDialog, MatSnackBar, MatStepper } from '@angular/material'; -import { ActivatedRoute, Params, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import * as FileSaver from 'file-saver'; -import { BehaviorSubject, Observable } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { DataManagementPlanCriteria } from '../../models/criteria/data-management-plan/DataManagementPlanCriteria'; -import { DataRepositoryCriteria } from '../../models/criteria/data-repository/DataRepositoryCriteria'; -import { DatasetProfileCriteria } from '../../models/criteria/dataset-profile/DatasetProfileCriteria'; -import { ExternalDatasetCriteria } from '../../models/criteria/external-dataset/ExternalDatasetCriteria'; -import { RegistryCriteria } from '../../models/criteria/registry/RegistryCriteria'; -import { RequestItem } from '../../models/criteria/RequestItem'; -import { ServicesCriteria } from '../../models/criteria/services/ServicesCriteria'; -import { TagsCriteria } from '../../models/criteria/tags/TagsCriteria'; -import { DataManagementPlanListingModel } from '../../models/data-managemnt-plans/DataManagementPlanListingModel'; -import { DataManagementPlanModel } from '../../models/data-managemnt-plans/DataManagementPlanModel'; -import { DataRepositoryModel } from '../../models/dataRepositories/DataRepositoryModel'; -import { DatasetProfileModel } from '../../models/datasetprofile/DatasetProfileModel'; -import { DatasetProfileDefinitionModel } from '../../models/DatasetProfileDefinitionModel'; -import { DatasetStatus, DatasetWizardModel } from '../../models/datasets/DatasetWizardModel'; -import { BaseErrorModel } from '../../models/error/BaseErrorModel'; -import { ExternalDatasetModel } from '../../models/external-dataset/ExternalDatasetModel'; -import { ExternalSourcesConfiguration } from '../../models/external-sources/ExternalSourcesConfiguration'; -import { RegisterModel } from '../../models/registers/RegisterModel'; -import { ServiceModel } from '../../models/services/ServiceModel'; -import { TagModel } from '../../models/tags/TagModel'; -import { DataManagementPlanService } from '../../services/data-management-plan/data-management-plan.service'; -import { DatasetWizardService } from '../../services/dataset-wizard/dataset-wizard.service'; -import { ExternalSourcesConfigurationService } from '../../services/external-sources/external-sources-configuration.service'; -import { ExternalSourcesService } from '../../services/external-sources/external-sources.service'; -import { AutoCompleteConfiguration } from '../../shared/components/auto-complete/AutoCompleteConfiguration'; -import { SingleAutoCompleteConfiguration } from '../../shared/components/autocompletes/single/single-auto-complete-configuration'; -import { BreadcrumbItem } from '../../shared/components/breadcrumb/definition/breadcrumb-item'; -import { IBreadCrumbComponent } from '../../shared/components/breadcrumb/definition/IBreadCrumbComponent'; -import { SnackBarNotificationComponent } from '../../shared/components/notificaiton/snack-bar-notification.component'; -import { JsonSerializer } from '../../utilities/JsonSerializer'; -import { DataRepositoryReferencedModelHelperComponent } from '../dataset-referenced-models-helper/datarepository/datarepository-referenced-model-helper.component'; -import { ExternalDatasetReferencedModelHelperComponent } from '../dataset-referenced-models-helper/externalDataset/externaldataset-referenced-model-helper.component'; -import { RegistryReferencedModelHelperComponent } from '../dataset-referenced-models-helper/registry/registry-referenced-model-helper.component'; -import { ServicesReferencedModelHelperComponent } from '../dataset-referenced-models-helper/services/services-referenced-model-helper.component'; -import { TdDialogService } from '@covalent/core'; - -@Component({ - selector: 'app-dataset-wizard-component', - templateUrl: 'dataset-wizard.component.html', - styleUrls: ['./dataset-wizard.component.scss'] -}) -export class DatasetWizardComponent extends BaseComponent implements OnInit, AfterViewInit, IBreadCrumbComponent { - breadCrumbs: Observable; - viewOnly = false; - @ViewChild('stepper') stepper: MatStepper; - editMode = false; - - //autocomplete Display Functions; - //autocomplete Configurations; - DatasetStatus = DatasetStatus; - externalDatasetAutoCompleteConfiguration: AutoCompleteConfiguration; - registriesAutoCompleteConfiguration: AutoCompleteConfiguration; - dataRepositoriesAutoCompleteConfiguration: AutoCompleteConfiguration; - servicesAutoCompleteConfiguration: AutoCompleteConfiguration; - tagsAutoCompleteConfiguration: AutoCompleteConfiguration; - dmpAutoCompleteConfiguration: SingleAutoCompleteConfiguration; - - externalSourcesConfiguration: ExternalSourcesConfiguration; - - datasetWizardModel: DatasetWizardModel; - isNew = true; - formGroup: FormGroup; - datasetProfileDefinitionModel: DatasetProfileDefinitionModel; - - availableProfiles: DatasetProfileModel[] = []; - itemId: string; - isLinear = false; - firstStepFormGroup: FormGroup; - secondFormGroup: FormGroup; - - externalDatasetDisplayFunc = (item) => item ? item.label : null; - registriesDisplayFunc = (item) => item ? item.label : null; - dataRepositoryDisplayFunc = (item) => item ? item.name : null; - servicesDisplayFunc = (item) => item ? item.label : null; - tagsDisplayFunc = (item) => item ? item.name : null; - externalDatasetDisplaySubtitleFunc = (item) => item ? item.tag : null; - registriesDisplaySubtitleFunc = (item) => item ? item.tag : null; - dataRepositoryDisplaySubtitleFunc = (item) => item ? item.tag : null; - servicesDisplaySubtitleFunc = (item) => item ? item.tag : null; - tagsDisplaySubtitleFunc = (item) => item ? item.tag : null; - - constructor( - private datasetWizardService: DatasetWizardService, - private route: ActivatedRoute, - public snackBar: MatSnackBar, - public router: Router, - public language: TranslateService, - public externalSourcesService: ExternalSourcesService, - public dataManagementPlanService: DataManagementPlanService, - public dialog: MatDialog, - private _dialogService: TdDialogService, - private _viewContainerRef: ViewContainerRef, - public externalSourcesConfigurationService: ExternalSourcesConfigurationService - ) { - super(); - } - - - ngOnInit() { - this.route - .data - .pipe(takeUntil(this._destroyed)) - .subscribe(v => this.viewOnly = v['public']); - - const dmpRequestItem: RequestItem = new RequestItem(); - dmpRequestItem.criteria = new DataManagementPlanCriteria(); - - const externalDatasetRequestItem: RequestItem = new RequestItem(); - externalDatasetRequestItem.criteria = new ExternalDatasetCriteria(); - this.externalDatasetAutoCompleteConfiguration = new AutoCompleteConfiguration(this.externalSourcesService.searchDatasetSExternalDatasetservice.bind(this.externalSourcesService), - externalDatasetRequestItem, new BehaviorSubject(false)); - - const registriesRequestItem: RequestItem = new RequestItem(); - registriesRequestItem.criteria = new RegistryCriteria(); - this.registriesAutoCompleteConfiguration = new AutoCompleteConfiguration(this.externalSourcesService.searchDatasetRegistry.bind(this.externalSourcesService), - registriesRequestItem, new BehaviorSubject(false)); - - const dataRepositoriesRequestItem: RequestItem = new RequestItem(); - dataRepositoriesRequestItem.criteria = new DataRepositoryCriteria(); - this.dataRepositoriesAutoCompleteConfiguration = new AutoCompleteConfiguration(this.externalSourcesService.searchDatasetRepository.bind(this.externalSourcesService), - dataRepositoriesRequestItem, new BehaviorSubject(false)); - - const servicesRequestItem: RequestItem = new RequestItem(); - servicesRequestItem.criteria = new ServicesCriteria(); - this.servicesAutoCompleteConfiguration = new AutoCompleteConfiguration(this.externalSourcesService.searchDatasetService.bind(this.externalSourcesService), - servicesRequestItem, new BehaviorSubject(false)); - - const tagsRequestItem: RequestItem = new RequestItem(); - tagsRequestItem.criteria = new TagsCriteria(); - this.tagsAutoCompleteConfiguration = new AutoCompleteConfiguration(this.externalSourcesService.searchDatasetTags.bind(this.externalSourcesService), - tagsRequestItem, new BehaviorSubject(false)); - - this.externalSourcesConfigurationService.getExternalSourcesConfiguration() - .pipe(takeUntil(this._destroyed)) - .subscribe(result => { - this.externalSourcesConfiguration = result; - this.externalSourcesConfiguration.dataRepositories.push({ key: '', label: 'All' }); - this.externalSourcesConfiguration.externalDatasets.push({ key: '', label: 'All' }); - this.externalSourcesConfiguration.registries.push({ key: '', label: 'All' }); - this.externalSourcesConfiguration.services.push({ key: '', label: 'All' }); - this.externalSourcesConfiguration.tags.push({ key: '', label: 'All' }); - }); - - this.dmpAutoCompleteConfiguration = { - filterFn: this.searchDmp.bind(this), - items: this.searchDmp(''), - displayFn: (item) => item['label'], - titleFn: (item) => item['label'], - loadDataOnStart: true - }; - - const params = this.route.snapshot.params; - this.itemId = params['id']; - const dmpId = params['dmpId']; - if (this.itemId != null) { - this.isNew = false; - this.datasetWizardService.getSingle(this.itemId).map(data => data as DatasetWizardModel) - .pipe(takeUntil(this._destroyed)) - .subscribe(data => { - this.datasetWizardModel = JsonSerializer.fromJSONObject(data, DatasetWizardModel); - this.breadCrumbs = Observable.of([ - { - parentComponentName: null, - label: 'Datasets', - url: '/datasets', - notFoundResolver: [ - { - parentComponentName: null, - label: this.datasetWizardModel.dmp.project.label, - url: '/projects/edit/' + this.datasetWizardModel.dmp.project.id - }, - { - parentComponentName: null, - label: this.datasetWizardModel.dmp.label, - url: '/dmps/edit/' + this.datasetWizardModel.dmp.id, - }, - ] - }]); - this.formGroup = this.datasetWizardModel.buildForm(); - this.editMode = this.datasetWizardModel.status === DatasetStatus.Draft; - if (this.datasetWizardModel.status === 1) { - this.formGroup.disable(); - this.viewOnly = true; - } - if (this.viewOnly) { this.formGroup.disable(); } - this.loadDatasetProfiles(); - }); - } else if (dmpId != null) { - this.isNew = true; - this.dataManagementPlanService.getSingle(dmpId).map(data => data as DataManagementPlanModel) - .pipe(takeUntil(this._destroyed)) - .subscribe(data => { - this.datasetWizardModel = new DatasetWizardModel(); - setTimeout(() => { - this.datasetWizardModel.dmp = data; - this.formGroup = this.datasetWizardModel.buildForm(); - this.editMode = this.datasetWizardModel.status === DatasetStatus.Draft; - if (this.datasetWizardModel.status === 1) { - this.formGroup.disable(); - this.viewOnly = true; - } - this.loadDatasetProfiles(); - this.breadCrumbs = Observable.of([ - { - parentComponentName: null, - label: 'Datasets', - url: '/datasets', - notFoundResolver: [ - { - parentComponentName: null, - label: this.datasetWizardModel.dmp.project.label, - url: '/projects/edit/' + this.datasetWizardModel.dmp.project.id - }, - { - parentComponentName: null, - label: this.datasetWizardModel.dmp.label, - url: '/dmps/edit/' + this.datasetWizardModel.dmp.id, - }] - }]); - }); - }); - } else { - this.datasetWizardModel = new DatasetWizardModel(); - this.formGroup = this.datasetWizardModel.buildForm(); - this.editMode = this.datasetWizardModel.status === DatasetStatus.Draft; - if (this.datasetWizardModel.status === 1) { - this.formGroup.disable(); - this.viewOnly = true; - } - if (this.viewOnly) { this.formGroup.disable(); } - this.formGroup.get('dmp').valueChanges - .pipe(takeUntil(this._destroyed)) - .subscribe(x => { - this.loadDatasetProfiles(); - }); - } - } - - ngAfterViewInit() { - this.route.params - .pipe(takeUntil(this._destroyed)) - .subscribe((params: Params) => { - const itemId = params['id']; - if (itemId != null) { this.stepper.selectedIndex = 2; } - }); - } - - searchDmp(query: string): Observable { - const dmpRequestItem: RequestItem = new RequestItem(); - dmpRequestItem.criteria = new DataManagementPlanCriteria(); - dmpRequestItem.criteria.like = query; - return this.dataManagementPlanService.get(dmpRequestItem); - } - - loadDatasetProfiles() { - const datasetProfileRequestItem: RequestItem = new RequestItem(); - datasetProfileRequestItem.criteria = new DatasetProfileCriteria(); - datasetProfileRequestItem.criteria.id = this.formGroup.get('dmp').value.id; - if (datasetProfileRequestItem.criteria.id) { - this.datasetWizardService.getAvailableProfiles(datasetProfileRequestItem) - .pipe(takeUntil(this._destroyed)) - .subscribe(items => { - this.availableProfiles = JsonSerializer.fromJSONArray(items, DatasetProfileModel); - }); - } - } - - public cancel(): void { - //this.router.navigate(['/dataManagementPlans']); - } - - getDefinition() { - if (this.formGroup.invalid) { this.stepper.selectedIndex = 0; return; } - if (this.isNew) { - this.datasetWizardService.getDefinition(this.formGroup.get('profile').get('id').value) - .pipe(takeUntil(this._destroyed)) - .subscribe(item => { - this.datasetWizardModel.datasetProfileDefinition = JsonSerializer.fromJSONObject(item, DatasetProfileDefinitionModel); - this.datasetProfileDefinitionModel = this.datasetWizardModel.datasetProfileDefinition; - this.formGroup.addControl('datasetProfileDefinition', this.datasetProfileDefinitionModel.buildForm()); - }); - } - } - - - formSubmit(): void { - if (!this.isFormValid()) { return; } - this.onSubmit(); - } - - public isFormValid() { - return this.formGroup.valid; - } - - onSubmit(): void { - this.datasetWizardService.createDataset(this.formGroup.value) - .pipe(takeUntil(this._destroyed)) - .subscribe( - complete => { - this.datasetWizardService.getSingle(complete.id) - .pipe(takeUntil(this._destroyed)) - .subscribe( - result => { - this.datasetWizardModel = JsonSerializer.fromJSONObject(result, DatasetWizardModel); - } - ); - this.onCallbackSuccess(); - }, - error => this.onCallbackError(error) - ); - } - - submit() { - this.datasetWizardService.createDataset(this.formGroup.value) - .pipe(takeUntil(this._destroyed)) - .subscribe(data => { - this.router.navigateByUrl('/datasets/dmp/' + this.formGroup.get('dmp').value.id); - }); - } - - - save() { - if (!this.isFormValid()) { return; } - this.formGroup.get('status').setValue('0'); - this.submit(); - } - - saveFinalize() { - if (!this.isFormValid()) { return; } - this.formGroup.get('status').setValue('1'); - this.submit(); - } - - onCallbackSuccess(): void { - this.snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, - duration: 3000, - }); - } - - onCallbackError(error: any) { - this.setErrorModel(error.error); - } - - public setErrorModel(errorModel: BaseErrorModel) { - Object.keys(errorModel).forEach(item => { - (this.datasetWizardModel.errorModel)[item] = (errorModel)[item]; - }); - } - - downloadPDF(): void { - this.datasetWizardService.downloadPDF(this.itemId) - .pipe(takeUntil(this._destroyed)) - .subscribe(response => { - const blob = new Blob([response.body], { type: 'application/pdf' }); - const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition')); - - FileSaver.saveAs(blob, filename); - }); - } - - downloadXML(): void { - this.datasetWizardService.downloadXML(this.itemId) - .pipe(takeUntil(this._destroyed)) - .subscribe(response => { - const blob = new Blob([response.body], { type: 'application/xml' }); - const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition')); - - FileSaver.saveAs(blob, filename); - }); - } - - getFilenameFromContentDispositionHeader(header: string): string { - const regex: RegExp = new RegExp(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/g); - - const matches = header.match(regex); - let filename: string; - for (let i = 0; i < matches.length; i++) { - const match = matches[i]; - if (match.includes('filename="')) { - filename = match.substring(10, match.length - 1); - break; - } else if (match.includes('filename=')) { - filename = match.substring(9); - break; - } - } - return filename; - } - - public redirectToProject() { - this.router.navigate(['projects/edit/' + this.datasetWizardModel.dmp.project.id]); - } - - public redirectToDmp() { - this.router.navigate(['dmps/edit/' + this.datasetWizardModel.dmp.id]); - } - - externalDatasetsOnItemChange(event) { - const externalDatasetModel = new ExternalDatasetModel(event.id, event.abbreviation, event.label, event.reference); - (this.formGroup.get('externalDatasets')).push(externalDatasetModel.buildForm()); - } - - registriesOnItemChange(event) { - const registryModel = new RegisterModel(event.abbreviation, event.definition, event.id, event.label, event.reference, event.uri); - (this.formGroup.get('registries')).push(registryModel.buildForm()); - } - - servicesOnItemChange(event) { - const serviceModel = new ServiceModel(event.abbreviation, event.definition, event.id, event.label, event.reference, event.uri); - (this.formGroup.get('services')).push(serviceModel.buildForm()); - } - - tagsOnItemChange(event) { - const serviceModel = new TagModel(event.id, event.name); - (this.formGroup.get('tags')).push(serviceModel.buildForm()); - } - - - dataRepositoriesOnItemChange(event) { - const dataRepositoryModel = new DataRepositoryModel(event.id, event.name, event.abbreviation, event.uri, event.pid); - (this.formGroup.get('dataRepositories')).push(dataRepositoryModel.buildForm()); - } - - addDataRepository() { - const dialogRef = this.dialog.open(DataRepositoryReferencedModelHelperComponent, { - data: { - - } - }); - dialogRef.afterClosed() - .pipe(takeUntil(this._destroyed)) - .subscribe(result => { - if (!result) { return; } - const dataRepositoryModel = new DataRepositoryModel(result.id, result.label, result.pid, result.uri, result.reference); - (this.formGroup.get('dataRepositories')).push(dataRepositoryModel.buildForm()); - }); - } - - addRegistry() { - const dialogRef = this.dialog.open(RegistryReferencedModelHelperComponent, { - data: { - - } - }); - dialogRef.afterClosed() - .pipe(takeUntil(this._destroyed)) - .subscribe(result => { - if (!result) { return; } - const registryModel = new RegisterModel(result.abbreviation, result.definition, result.id, result.label, result.reference, result.uri); - (this.formGroup.get('registries')).push(registryModel.buildForm()); - }); - } - - addExternalDataset() { - const dialogRef = this.dialog.open(ExternalDatasetReferencedModelHelperComponent, { - data: { - - } - }); - dialogRef.afterClosed() - .pipe(takeUntil(this._destroyed)) - .subscribe(result => { - if (!result) { return; } - const externalDatasetModel = new ExternalDatasetModel(result.id, result.abbreviation, result.label, result.reference); - (this.formGroup.get('externalDatasets')).push(externalDatasetModel.buildForm()); - }); - } - - addService() { - const dialogRef = this.dialog.open(ServicesReferencedModelHelperComponent, { - data: { - - } - }); - dialogRef.afterClosed() - .pipe(takeUntil(this._destroyed)) - .subscribe(result => { - if (!result) { return; } - const serviceModel = new ServiceModel(result.id, result.abbreviation, result.definition, result.uri, result.label, result.reference); - (this.formGroup.get('services')).push(serviceModel.buildForm()); - }); - } - - public enableForm() { - if (this.formGroup.get('status').value !== DatasetStatus.Finalised) { - this.editMode = true; - this.viewOnly = false; - this.formGroup.enable(); - } else { - this.datasetWizardService.unlock(this.formGroup.get('id').value) - .pipe(takeUntil(this._destroyed)) - .subscribe(x => { - this.editMode = true; - this.viewOnly = false; - this.datasetWizardModel.status = DatasetStatus.Draft; - this.formGroup.get('status').patchValue(DatasetStatus.Draft); - this.formGroup.enable(); - }); - } - } - - public disableForm() { - this.editMode = false; - this.viewOnly = true; - this.formGroup.disable(); - } - - isActiveStep(index: number) { - return this.stepper.selectedIndex === index; - } - - openConfirm(dmpLabel, id): void { - this._dialogService.openConfirm({ - message: 'Are you sure you want to delete the "' + dmpLabel + '"', - disableClose: true || false, - viewContainerRef: this._viewContainerRef, - title: 'Confirm', - cancelButton: 'No', - acceptButton: 'Yes' - }).afterClosed() - .pipe(takeUntil(this._destroyed)) - .subscribe((accept: boolean) => { - if (accept) { - this.datasetWizardService.delete(id) - .pipe(takeUntil(this._destroyed)) - .subscribe(() => { - this.router.navigate(['/datasets']); - }); - } else { - // DO SOMETHING ELSE - } - }); - } -} diff --git a/dmp-frontend/src/app/datasets/dataset.module.ts b/dmp-frontend/src/app/datasets/dataset.module.ts deleted file mode 100644 index 73fdcd50f..000000000 --- a/dmp-frontend/src/app/datasets/dataset.module.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { RouterModule } from '@angular/router'; -import { TranslateHttpLoader } from '@ngx-translate/http-loader'; -import { DatasetService } from '../services/dataset/dataset.service'; -import { DynamicFormModule } from '../form/dynamic-form.module'; -import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; -import { DatasetWizardComponent } from './dataset-wizard/dataset-wizard.component'; -import { DatasetRoutes } from './dataset.routes'; -import { DatasetListingComponent } from './listing/dataset-listing.component'; -import { DatasetEditorComponent } from './editor/dataset-editor.component'; -import { CommonModule } from '@angular/common'; -import { HttpClient, HttpClientModule } from '@angular/common/http'; -import { NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; - -import { SharedModule } from '../shared/shared.module'; -import { BaseHttpService } from '../utilities/cite-http-service-module/base-http.service'; -import { BaseHttpModule } from '../utilities/cite-http-service-module/cite-http.module'; -import { MaterialModule } from '../shared/material/material.module'; -import { DataManagementPlanService } from '../services/data-management-plan/data-management-plan.service'; -import { DatasetWizardService } from '../services/dataset-wizard/dataset-wizard.service'; -import { ExternalSourcesService } from '../services/external-sources/external-sources.service'; -import { ExternalSourcesConfigurationService } from '../services/external-sources/external-sources-configuration.service'; -import { DatasetPublicListingComponent } from './dataset-public/dataset-public-listing.component'; -import { DataRepositoryReferencedModelHelperComponent } from './dataset-referenced-models-helper/datarepository/datarepository-referenced-model-helper.component'; -import { ExternalDatasetReferencedModelHelperComponent } from './dataset-referenced-models-helper/externalDataset/externaldataset-referenced-model-helper.component'; -import { ServicesReferencedModelHelperComponent } from './dataset-referenced-models-helper/services/services-referenced-model-helper.component'; -import { RegistryReferencedModelHelperComponent } from './dataset-referenced-models-helper/registry/registry-referenced-model-helper.component'; -import { RegistryService } from '../services/registries/registry.service'; -import { ServicesDataService } from '../services/services/services-data.service'; -import { DataRepositoryService } from '../services/datarepository/datarepository.service'; -import { ExternalDatasetService } from '../services/external-dataset/external-dataset.service'; -@NgModule({ - imports: [ - CommonModule, - FormsModule, - HttpClientModule, - SharedModule, - MaterialModule, - RouterModule.forChild(DatasetRoutes), - ReactiveFormsModule, - DynamicFormModule, - - TranslateModule.forRoot({ - loader: { - provide: TranslateLoader, - useFactory: HttpLoaderFactory, - deps: [HttpClient] - } - }), - ], - - declarations: [ - DatasetListingComponent, - DatasetEditorComponent, - DatasetWizardComponent, - DatasetPublicListingComponent, - DataRepositoryReferencedModelHelperComponent, - ExternalDatasetReferencedModelHelperComponent, - ServicesReferencedModelHelperComponent, - RegistryReferencedModelHelperComponent, - ], - - exports: [ - DatasetListingComponent, - DatasetEditorComponent, - DatasetWizardComponent, - DataRepositoryReferencedModelHelperComponent, - ExternalDatasetReferencedModelHelperComponent, - ServicesReferencedModelHelperComponent, - RegistryReferencedModelHelperComponent, - DatasetPublicListingComponent, - RouterModule - ], - providers: [ - DatasetWizardService, - ExternalSourcesService, - ExternalSourcesConfigurationService, - DataManagementPlanService, - DatasetService, - DataRepositoryService, - ExternalDatasetService, - ServicesDataService, - RegistryService - ], - entryComponents: [ - DataRepositoryReferencedModelHelperComponent, - ExternalDatasetReferencedModelHelperComponent, - ServicesReferencedModelHelperComponent, - RegistryReferencedModelHelperComponent - ] -}) - -export class DatasetModule { - constructor(private translate: TranslateService) { - translate.setDefaultLang('en'); - translate.use('en'); - } -} - -export function HttpLoaderFactory(httpClient: HttpClient) { - return new TranslateHttpLoader(httpClient, 'assets/lang/', '.json'); -} diff --git a/dmp-frontend/src/app/datasets/dataset.routes.ts b/dmp-frontend/src/app/datasets/dataset.routes.ts deleted file mode 100644 index a4813cd12..000000000 --- a/dmp-frontend/src/app/datasets/dataset.routes.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { DatasetWizardComponent } from './dataset-wizard/dataset-wizard.component'; -import { DatasetListingComponent } from './listing/dataset-listing.component'; -import { RouterModule, Routes } from '@angular/router'; -import { AuthGuard } from '../shared/guards/auth.guard'; -import { DatasetPublicListingComponent } from './dataset-public/dataset-public-listing.component'; - -export const DatasetRoutes: Routes = [ - { - path: 'new/:dmpId', - component: DatasetWizardComponent, - canActivate: [AuthGuard], - data: { - breadcrumb: true - }, - }, - { - path: 'edit/:id', - component: DatasetWizardComponent, - canActivate: [AuthGuard], - data: { - breadcrumb: true, - public: false - }, - }, - { - path: 'publicEdit/:id', - component: DatasetWizardComponent, - //canActivate: [AuthGuard], - data: { - public: true - } - }, - { - path: 'new', - component: DatasetWizardComponent, - canActivate: [AuthGuard], - data: { - breadcrumb: true - }, - }, - { - path: '', - component: DatasetListingComponent, - //canActivate: [AuthGuard], - data: { - breadcrumb: true - }, - }, - { - path: 'public', - component: DatasetPublicListingComponent, - data: { - breadcrumb: false - } - }, - { - path: 'dmp/:dmpId', - component: DatasetListingComponent, - //canActivate: [AuthGuard], - data: { - breadcrumb: true - }, - } -]; diff --git a/dmp-frontend/src/app/datasets/editor/dataset-editor.component.html b/dmp-frontend/src/app/datasets/editor/dataset-editor.component.html deleted file mode 100644 index ee9e10dc5..000000000 --- a/dmp-frontend/src/app/datasets/editor/dataset-editor.component.html +++ /dev/null @@ -1,23 +0,0 @@ -
-
- - - - {{baseErrorModel.label}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - - - - - {{baseErrorModel.uri}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - - - - - - {{errorModel.description}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - -
-
diff --git a/dmp-frontend/src/app/datasets/editor/dataset-editor.component.scss b/dmp-frontend/src/app/datasets/editor/dataset-editor.component.scss deleted file mode 100644 index 289699735..000000000 --- a/dmp-frontend/src/app/datasets/editor/dataset-editor.component.scss +++ /dev/null @@ -1,38 +0,0 @@ -.full-width { - width: 100%; -} - -.input-table { - table-layout: fixed; -} - -.table-card .mat-grid-tile { - background: rgba(0, 0, 0, 0.32); -} - -.project-editor { - .mat-form-field-full-width{ - mat-form-field { - width: 100%; - padding: 3px; - } - } - - - .mat-card { - margin: 16px 0; - } - - p { - margin: 16px; - } - - .left-button { - float: left; - } - - .description-area { - height: 100px; - } - -} diff --git a/dmp-frontend/src/app/datasets/editor/dataset-editor.component.ts b/dmp-frontend/src/app/datasets/editor/dataset-editor.component.ts deleted file mode 100644 index b48b08506..000000000 --- a/dmp-frontend/src/app/datasets/editor/dataset-editor.component.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { AfterViewInit, Component, Input, ViewEncapsulation } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { MatSnackBar } from '@angular/material'; -import { Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { DatasetModel } from '../../models/datasets/DatasetModel'; - - - -@Component({ - selector: 'app-dataset-editor-component', - templateUrl: 'dataset-editor.component.html', - styleUrls: ['./dataset-editor.component.scss'], - encapsulation: ViewEncapsulation.None -}) -export class DatasetEditorComponent implements AfterViewInit { - - isNew = true; - dataset: DatasetModel; - @Input() formGroup: FormGroup = null; - - // filtereddataRepositoriesAsync: boolean = false; - // filteredRegistriesAsync: boolean = false; - // filteredServicesAsync: boolean = false; - - // filtereddataRepositories: ExternalSourcesItemModel[]; - // filteredRegistries: ExternalSourcesItemModel[]; - // filteredServices: ExternalSourcesItemModel[]; - - constructor( - public snackBar: MatSnackBar, - public router: Router, - public language: TranslateService, - ) { - - } - - ngAfterViewInit() { - /* this.route.params.pipe(takeUntil(this._destroyed)).subscribe((params: Params) => { - const itemId = params['id']; - - if (itemId != null) { - this.isNew = false; - this.datasetService.getSingle(itemId).map(data => data as DatasetModel) - .pipe(takeUntil(this._destroyed)) - .subscribe(data => { - this.dataset = new JsonSerializer().fromJSONObject(data, DatasetModel); - this.formGroup = this.dataset.buildForm(); - }); - } else { - this.dataset = new DatasetModel(); - setTimeout(() => { - this.formGroup = this.dataset.buildForm(); - }); - } - }); */ - } - - - public cancel(): void { - this.router.navigate(['/datasets']); - } - - // filterdataRepositories(value: string): void { - - // this.filtereddataRepositories = undefined; - // if (value) { - // this.filtereddataRepositoriesAsync = true; - - // this.externalSourcesService.searchDMPOrganizations(value).pipe(takeUntil(this._destroyed)).subscribe(items => { - // this.filtereddataRepositories = items; - // this.filtereddataRepositoriesAsync = false; - - // // this.filteredOrganisations = items.filter((filteredObj: any) => { - // // return this.objectsModel ? this.objectsModel.indexOf(filteredObj) < 0 : true; - // // }); - - // }); - // } - // } - - // filterRegistries(value: string): void { - - // this.filteredRegistries = undefined; - // if (value) { - // this.filteredRegistriesAsync = true; - - // this.externalSourcesService.searchDMPResearchers(value).pipe(takeUntil(this._destroyed)).subscribe(items => { - // this.filteredRegistries = items; - // this.filteredRegistriesAsync = false; - - // // this.filteredOrganisations = items.filter((filteredObj: any) => { - // // return this.objectsModel ? this.objectsModel.indexOf(filteredObj) < 0 : true; - // // }); - - // }); - // } - // } - - // filterServices(value: string): void { - - // this.filteredServices = undefined; - // if (value) { - // this.filteredServicesAsync = true; - - // this.externalSourcesService.searchDatasetService(value).pipe(takeUntil(this._destroyed)).subscribe(items => { - // this.filteredServices = items; - // this.filteredServicesAsync = false; - - // // this.filteredOrganisations = items.filter((filteredObj: any) => { - // // return this.objectsModel ? this.objectsModel.indexOf(filteredObj) < 0 : true; - // // }); - - // }); - // } - // } -} diff --git a/dmp-frontend/src/app/datasets/listing/dataset-listing.component.html b/dmp-frontend/src/app/datasets/listing/dataset-listing.component.html deleted file mode 100644 index 1af6b4135..000000000 --- a/dmp-frontend/src/app/datasets/listing/dataset-listing.component.html +++ /dev/null @@ -1,97 +0,0 @@ -
-

{{'DATASET-LISTING.TITLE' | translate}} {{titlePrefix}}

- - - - - - - - - - - - {{'DATASET-LISTING.COLUMNS.NAME' | translate}} - {{row.label}} - - - - - {{'DATASET-LISTING.COLUMNS.PROJECT' | - translate}} - {{row.project}} - - - - - {{'DATASET-LISTING.COLUMNS.DMP' | - translate}} - {{row.dmp}} - - - - - {{'DATASET-LISTING.COLUMNS.PROFILE' | - translate}} - {{row.profile}} - - - - - {{'DATASET-LISTING.COLUMNS.STATUS' | translate}} - {{this.utilities.convertFromDatasetStatus(row.status)}} - - - - - - - - - - - - - - - - - {{'DATASET-LISTING.COLUMNS.DESCRIPTION' | translate}} - {{row.description}} - - - - - {{'DATASET-LISTING.COLUMNS.CREATED' | translate}} - {{row.created | date:'shortDate'}} - - - - - - - - - - - - - -
diff --git a/dmp-frontend/src/app/datasets/listing/dataset-listing.component.ts b/dmp-frontend/src/app/datasets/listing/dataset-listing.component.ts deleted file mode 100644 index b1c6c6088..000000000 --- a/dmp-frontend/src/app/datasets/listing/dataset-listing.component.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { DataSource } from '@angular/cdk/table'; -import { Component, OnInit, ViewChild } from '@angular/core'; -import { MatPaginator, MatSnackBar, MatSort, PageEvent } from '@angular/material'; -import { ActivatedRoute, Params, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { DatasetCriteria } from '../../models/criteria/dataset/DatasetCriteria'; -import { DataTableRequest } from '../../models/data-table/DataTableRequest'; -import { DatasetListingModel } from '../../models/datasets/DatasetListingModel'; -import { DataManagementPlanService } from '../../services/data-management-plan/data-management-plan.service'; -import { DatasetService } from '../../services/dataset/dataset.service'; -import { BreadcrumbItem } from '../../shared/components/breadcrumb/definition/breadcrumb-item'; -import { IBreadCrumbComponent } from '../../shared/components/breadcrumb/definition/IBreadCrumbComponent'; -import { DatasetCriteriaComponent } from '../../shared/components/criteria/datasets/datasets-criteria.component'; -import { JsonSerializer } from '../../utilities/JsonSerializer'; -import { Utilities } from '../../utilities/utilities'; - -@Component({ - selector: 'app-dataset-listing-component', - templateUrl: 'dataset-listing.component.html', - styleUrls: ['./dataset-listing.component.scss'], - providers: [Utilities] -}) -export class DatasetListingComponent extends BaseComponent implements OnInit, IBreadCrumbComponent { - - @ViewChild(MatPaginator) _paginator: MatPaginator; - @ViewChild(MatSort) sort: MatSort; - @ViewChild(DatasetCriteriaComponent) criteria: DatasetCriteriaComponent; - - breadCrumbs: Observable; - - dataSource: DatasetDataSource | null; - displayedColumns: String[] = ['label', 'project', 'dmp', 'profile', 'status', 'description', 'created']; - pageEvent: PageEvent; - titlePrefix: String; - dmpId: string; - - statuses = [ - { value: '0', viewValue: 'Active' }, - { value: '1', viewValue: 'Inactive' } - ]; - - constructor( - private datasetService: DatasetService, - private router: Router, - private languageService: TranslateService, - public snackBar: MatSnackBar, - public route: ActivatedRoute, - public dataManagementPlanService: DataManagementPlanService, - public utilities: Utilities - ) { - super(); - } - - - ngOnInit() { - - this.route.params - .pipe(takeUntil(this._destroyed)) - .subscribe(async (params: Params) => { - this.dmpId = params['dmpId']; - this.criteria.setCriteria(this.getDefaultCriteria(this.dmpId)); - this.refresh(); - this.criteria.setRefreshCallback(() => this.refresh()); - if (this.dmpId != null) { - const dmp = await this.dataManagementPlanService.getSingle(this.dmpId).toPromise(); - this.breadCrumbs = Observable.of([{ parentComponentName: 'DataManagementPlanEditorComponent', label: dmp.label, url: 'dmps/edit/' + this.dmpId }]); - if (params['dmpLabel'] !== undefined) { - this.titlePrefix = 'for ' + params['dmpLabel']; - } - } else { - this.breadCrumbs = Observable.of([]); - } - }); - } - - refresh() { - this.dataSource = new DatasetDataSource(this.datasetService, this._paginator, this.sort, this.languageService, this.snackBar, this.criteria, this.dmpId); - } - - rowClick(rowId: String) { - this.router.navigate(['/datasets/edit/' + rowId]); - } - - getDefaultCriteria(dmpId: String): DatasetCriteria { - const defaultCriteria = new DatasetCriteria(); - if (dmpId != null) { - defaultCriteria.dmpIds.push(dmpId); - } - return defaultCriteria; - } - - makeItPublic(id: String) { - this.datasetService.makeDatasetPublic(id) - .pipe(takeUntil(this._destroyed)) - .subscribe(); - } - -} - -export class DatasetDataSource extends DataSource { - - totalCount = 0; - isLoadingResults = false; - constructor( - private _service: DatasetService, - private _paginator: MatPaginator, - private _sort: MatSort, - private _languageService: TranslateService, - private _snackBar: MatSnackBar, - private _criteria: DatasetCriteriaComponent, - private dmpId: String - ) { - super(); - - } - - connect(): Observable { - const displayDataChanges = [ - this._paginator.page - //this._sort.matSortChange - ]; - - - return Observable.merge(...displayDataChanges) - .startWith(null) - .switchMap(() => { - setTimeout(() => { - this.isLoadingResults = true; - }); - const startIndex = this._paginator.pageIndex * this._paginator.pageSize; - let fields: Array = new Array(); - if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; } - const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); - request.criteria = this._criteria.criteria; - if (this.dmpId) { request.criteria.allVersions = true; } - return this._service.getPaged(request); - }) - /*.catch((error: any) => { - this._snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService }, - duration: 3000, - extraClasses: ['snackbar-warning'] - }); - //this._criteria.criteria.onCallbackError(error); - return Observable.of(null); - })*/ - .map(result => { - result.data = JsonSerializer.fromJSONArray(result.data, DatasetListingModel); - return result; - }) - .map(result => { - setTimeout(() => { - this.isLoadingResults = false; - }); - return result; - }) - .map(result => { - if (!result) { return []; } - if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; } - return result.data; - }); - } - - disconnect() { - // No-op - } -} diff --git a/dmp-frontend/src/app/dmp-profiles/dmp-profile-editor/dmp-profile-editor.component.html b/dmp-frontend/src/app/dmp-profiles/dmp-profile-editor/dmp-profile-editor.component.html deleted file mode 100644 index 1eefbacaa..000000000 --- a/dmp-frontend/src/app/dmp-profiles/dmp-profile-editor/dmp-profile-editor.component.html +++ /dev/null @@ -1,68 +0,0 @@ -
-
- - - {{'DMP-PROFILE-EDITOR.TITLE.NEW' | translate}} - {{formGroup.get('label').value}} - - - - - - - {{baseErrorModel.label}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - - -
- - -
- - - {{baseErrorModel.label}} - {{'GENERAL.VALIDATION.REQUIRED' - | translate}} - - - - {{ - getDMPProfileFieldTypeWithLanguage(fieldType) | translate}} - - {{baseErrorModel.type}} - {{'GENERAL.VALIDATION.REQUIRED' - | translate}} - - - - {{ - getDMPProfileFieldDataTypeWithLanguage(fieldDataType) | translate}} - - {{baseErrorModel.dataType}} - {{'GENERAL.VALIDATION.REQUIRED' - | translate}} - - - {{'DMP-PROFILE-EDITOR.FIELDS.REQUIRED' | translate}} - -
-
- -
-
-
- - - -
- -
-
-
-
diff --git a/dmp-frontend/src/app/dmp-profiles/dmp-profile-editor/dmp-profile-editor.component.scss b/dmp-frontend/src/app/dmp-profiles/dmp-profile-editor/dmp-profile-editor.component.scss deleted file mode 100644 index c1f0f8860..000000000 --- a/dmp-frontend/src/app/dmp-profiles/dmp-profile-editor/dmp-profile-editor.component.scss +++ /dev/null @@ -1,39 +0,0 @@ -.full-width { - width: 100%; -} - -.input-table { - table-layout: fixed; -} - -.table-card .mat-grid-tile { - background: rgba(0, 0, 0, 0.32); -} - -.dmp-profile-editor { - - .mat-form-field-full-width{ - mat-form-field { - width: 100%; - padding: 3px; - } - } - - - .mat-card { - margin: 16px 0; - } - - p { - margin: 16px; - } - - .left-button { - float: left; - } - - .description-area { - height: 100px; - } - -} diff --git a/dmp-frontend/src/app/dmp-profiles/dmp-profile-editor/dmp-profile-editor.component.ts b/dmp-frontend/src/app/dmp-profiles/dmp-profile-editor/dmp-profile-editor.component.ts deleted file mode 100644 index 1217beebe..000000000 --- a/dmp-frontend/src/app/dmp-profiles/dmp-profile-editor/dmp-profile-editor.component.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { AfterViewInit, Component, ViewEncapsulation } from '@angular/core'; -import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; -import { MatSnackBar } from '@angular/material'; -import { ActivatedRoute, Params, Router } from '@angular/router'; -import { TdDialogService } from '@covalent/core'; -import { TranslateService } from '@ngx-translate/core'; -import { takeUntil } from 'rxjs/operators'; -import { environment } from '../../../environments/environment'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { DataManagementPlanProfileModel } from '../../models/data-management-plan-profile/DataManagementPlanProfileModel'; -import { DataManagementProfileField, DMPProfileFieldDataType, DMPProfileType } from '../../models/data-management-plan-profile/DataManagementProfileField'; -import { BaseErrorModel } from '../../models/error/BaseErrorModel'; -import { DataManagementPlanProfileService } from '../../services/data-management-plan-profile/datamanagement-profile.service'; -import { SnackBarNotificationComponent } from '../../shared/components/notificaiton/snack-bar-notification.component'; -import { JsonSerializer } from '../../utilities/JsonSerializer'; -import { Utilities } from '../../utilities/utilities'; - - - -@Component({ - selector: 'app-dmp-profile-editor-component', - templateUrl: 'dmp-profile-editor.component.html', - styleUrls: ['./dmp-profile-editor.component.scss'], - providers: [DataManagementPlanProfileService, Utilities], - encapsulation: ViewEncapsulation.None -}) -export class DataManagementPlanProfileEditorComponent extends BaseComponent implements AfterViewInit { - - isNew = true; - dataManagementPlanProfileModel: DataManagementPlanProfileModel; - formGroup: FormGroup = null; - host = environment.Server; - baseErrorModel: BaseErrorModel; - constructor( - private dmpProfileService: DataManagementPlanProfileService, - private route: ActivatedRoute, - public snackBar: MatSnackBar, - public router: Router, - public language: TranslateService, - private dialogService: TdDialogService, - private utilities: Utilities - ) { - super(); - } - - ngAfterViewInit() { - this.route.params - .pipe(takeUntil(this._destroyed)) - .subscribe((params: Params) => { - const itemId = params['id']; - - if (itemId != null) { - this.isNew = false; - this.dmpProfileService.getSingle(itemId).map(data => data as DataManagementPlanProfileModel) - .pipe(takeUntil(this._destroyed)) - .subscribe(data => { - this.dataManagementPlanProfileModel = JsonSerializer.fromJSONObject(data, DataManagementPlanProfileModel); - this.baseErrorModel = this.dataManagementPlanProfileModel.errorModel; - this.formGroup = this.dataManagementPlanProfileModel.buildForm(); - }); - } else { - this.dataManagementPlanProfileModel = new DataManagementPlanProfileModel(); - this.baseErrorModel = this.dataManagementPlanProfileModel.errorModel; - - setTimeout(() => { - this.formGroup = this.dataManagementPlanProfileModel.buildForm(); - }); - } - }); - } - - formSubmit(): void { - this.touchAllFormFields(this.formGroup); - if (!this.isFormValid()) { return; } - this.onSubmit(); - } - - public isFormValid() { - return this.formGroup.valid; - } - - onSubmit(): void { - this.dmpProfileService.createDataManagementPlan(this.formGroup.value) - .pipe(takeUntil(this._destroyed)) - .subscribe( - complete => this.onCallbackSuccess(), - error => this.onCallbackError(error) - ); - } - - onCallbackSuccess(): void { - this.snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, - duration: 3000, - }); - this.router.navigate(['/dmp-profiles']); - } - - onCallbackError(errorResponse: any) { - this.setErrorModel(errorResponse.error); - this.validateAllFormFields(this.formGroup); - } - - public setErrorModel(errorModel: BaseErrorModel) { - Object.keys(errorModel).forEach(item => { - (this.dataManagementPlanProfileModel.errorModel)[item] = (errorModel)[item]; - }); - } - - public cancel(): void { - this.router.navigate(['/dmp-profiles']); - } - - - public touchAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.markAsTouched(); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.touchAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.touchAllFormFields(item); - }); - } - } - - public validateAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.updateValueAndValidity({ emitEvent: false }); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.validateAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.validateAllFormFields(item); - }); - } - } - - addField() { - (this.formGroup.get('definition').get('fields')).push(new DataManagementProfileField().buildForm()); - } - - getDMPProfileFieldDataTypeValues(): Number[] { - let keys: string[] = Object.keys(DMPProfileFieldDataType); - keys = keys.slice(0, keys.length / 2); - const values: Number[] = keys.map(Number); - return values; - } - - getDMPProfileFieldDataTypeWithLanguage(role: DMPProfileFieldDataType): string { - let result = ''; - this.language.get(this.utilities.convertFromDMPProfileDataType(role)) - .pipe(takeUntil(this._destroyed)) - .subscribe((value: string) => { - result = value; - }); - return result; - } - - getDMPProfileFieldTypeValues(): Number[] { - let keys: string[] = Object.keys(DMPProfileType); - keys = keys.slice(0, keys.length / 2); - const values: Number[] = keys.map(Number); - return values; - } - - getDMPProfileFieldTypeWithLanguage(role: DMPProfileType): string { - let result = ''; - this.language.get(this.utilities.convertFromDMPProfileType(role)) - .pipe(takeUntil(this._destroyed)) - .subscribe((value: string) => { - result = value; - }); - return result; - } -} diff --git a/dmp-frontend/src/app/dmp-profiles/dmp-profile-listing/dmp-profile-listing.component.html b/dmp-frontend/src/app/dmp-profiles/dmp-profile-listing/dmp-profile-listing.component.html deleted file mode 100644 index 5eeccbecc..000000000 --- a/dmp-frontend/src/app/dmp-profiles/dmp-profile-listing/dmp-profile-listing.component.html +++ /dev/null @@ -1,44 +0,0 @@ -
-

{{titlePrefix}} {{'DMP-PROFILE-LISTING.TITLE' | translate}}

- - - - - - - - - - - - {{'DMP-PROFILE-LISTING.COLUMNS.NAME' | translate}} - {{row.label}} - - - - - {{'DMP-PROFILE-LISTING.COLUMNS.STATUS' | translate}} - {{row.status}} - - - - - {{'DMP-PROFILE-LISTING.COLUMNS.CREATED' | translate}} - {{row.created | date:'shortDate'}} - - - - - - - - - - - - - - -
diff --git a/dmp-frontend/src/app/dmp-profiles/dmp-profile-listing/dmp-profile-listing.component.ts b/dmp-frontend/src/app/dmp-profiles/dmp-profile-listing/dmp-profile-listing.component.ts deleted file mode 100644 index ef3a02933..000000000 --- a/dmp-frontend/src/app/dmp-profiles/dmp-profile-listing/dmp-profile-listing.component.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { DataSource } from '@angular/cdk/table'; -import { Component, OnInit, ViewChild } from '@angular/core'; -import { MatPaginator, MatSnackBar, MatSort, PageEvent } from '@angular/material'; -import { ActivatedRoute, Params, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { DataManagementPlanProfileCriteria } from '../../models/criteria/dmp-profile/DataManagementPlanProfileCriteria'; -import { DataManagementPlanProfileListingModel } from '../../models/data-management-plan-profile/DataManagementPlanProfileListingModel'; -import { DataTableRequest } from '../../models/data-table/DataTableRequest'; -import { DataManagementPlanProfileService } from '../../services/data-management-plan-profile/datamanagement-profile.service'; -import { DataManagementPlanProfileCriteriaComponent } from '../../shared/components/criteria/datamanagementplanprofile/dmp-profile-criteria.component'; - -@Component({ - selector: 'app-dmp-profile-listing-component', - templateUrl: 'dmp-profile-listing.component.html', - styleUrls: ['./dmp-profile-listing.component.scss'], - providers: [DataManagementPlanProfileService] -}) -export class DataManagementPlanProfileListingComponent extends BaseComponent implements OnInit { - - @ViewChild(MatPaginator) _paginator: MatPaginator; - @ViewChild(MatSort) sort: MatSort; - @ViewChild(DataManagementPlanProfileCriteriaComponent) criteria: DataManagementPlanProfileCriteriaComponent; - - - dataSource: DatasetDataSource | null; - displayedColumns: String[] = ['label', 'status', 'created']; - pageEvent: PageEvent; - titlePrefix: String; - dmpId: String; - - statuses = [ - { value: '0', viewValue: 'Active' }, - { value: '1', viewValue: 'Inactive' } - ]; - - constructor( - private router: Router, - private languageService: TranslateService, - public snackBar: MatSnackBar, - public route: ActivatedRoute, - public dataManagementPlanService: DataManagementPlanProfileService - ) { - super(); - } - - - ngOnInit() { - this.route.params - .pipe(takeUntil(this._destroyed)) - .subscribe((params: Params) => { - this.dmpId = params['dmpId']; - this.criteria.setCriteria(this.getDefaultCriteria()); - this.refresh(); - this.criteria.setRefreshCallback(() => this.refresh()); - }); - } - - refresh() { - this.dataSource = new DatasetDataSource(this.dataManagementPlanService, this._paginator, this.sort, this.languageService, this.snackBar, this.criteria); - } - - rowClick(rowId: String) { - this.router.navigate(['dmp-profiles/' + rowId]); - } - - getDefaultCriteria(): DataManagementPlanProfileCriteria { - const defaultCriteria = new DataManagementPlanProfileCriteria(); - return defaultCriteria; - } - - // makeItPublic(id: String) { - // debugger; - // this.datasetService.makeDatasetPublic(id).pipe(takeUntil(this._destroyed)).subscribe(); - // } - -} - -export class DatasetDataSource extends DataSource { - - totalCount = 0; - isLoadingResults = false; - - constructor( - private _service: DataManagementPlanProfileService, - private _paginator: MatPaginator, - private _sort: MatSort, - private _languageService: TranslateService, - private _snackBar: MatSnackBar, - private _criteria: DataManagementPlanProfileCriteriaComponent - ) { - super(); - - } - - connect(): Observable { - const displayDataChanges = [ - this._paginator.page - //this._sort.matSortChange - ]; - - - return Observable.merge(...displayDataChanges) - .startWith(null) - .switchMap(() => { - setTimeout(() => { - this.isLoadingResults = true; - }); - const startIndex = this._paginator.pageIndex * this._paginator.pageSize; - let fields: Array = new Array(); - if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; } - const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); - request.criteria = this._criteria.criteria; - return this._service.getPaged(request); - }) - /*.catch((error: any) => { - this._snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService }, - duration: 3000, - extraClasses: ['snackbar-warning'] - }); - //this._criteria.criteria.onCallbackError(error); - return Observable.of(null); - })*/ - .map(result => { - setTimeout(() => { - this.isLoadingResults = false; - }); - return result; - }) - .map(result => { - if (!result) { return []; } - if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; } - return result.data; - }); - } - - disconnect() { - // No-op - } -} diff --git a/dmp-frontend/src/app/dmp-profiles/dmp-profile.module.ts b/dmp-frontend/src/app/dmp-profiles/dmp-profile.module.ts deleted file mode 100644 index c3185ea3e..000000000 --- a/dmp-frontend/src/app/dmp-profiles/dmp-profile.module.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { RouterModule } from '@angular/router'; -import { TranslateHttpLoader } from '@ngx-translate/http-loader'; -import { DatasetService } from '../services/dataset/dataset.service'; -import { DynamicFormModule } from '../form/dynamic-form.module'; -import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; -import { CommonModule } from '@angular/common'; -import { HttpClient, HttpClientModule } from '@angular/common/http'; -import { NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; - -import { SharedModule } from '../shared/shared.module'; -import { DataManagementPlanProfileRoutes } from './dmp-profile.routes'; -import { DataManagementPlanProfileEditorComponent } from './dmp-profile-editor/dmp-profile-editor.component'; -import { DataManagementPlanProfileListingComponent } from './dmp-profile-listing/dmp-profile-listing.component'; -@NgModule({ - imports: [ - CommonModule, - FormsModule, - HttpClientModule, - SharedModule, - RouterModule.forChild(DataManagementPlanProfileRoutes), - ReactiveFormsModule, - DynamicFormModule, - TranslateModule.forRoot({ - loader: { - provide: TranslateLoader, - useFactory: HttpLoaderFactory, - deps: [HttpClient] - } - }), - ], - - declarations: [ - DataManagementPlanProfileEditorComponent, - DataManagementPlanProfileListingComponent - ], - - exports: [ - DataManagementPlanProfileEditorComponent, - DataManagementPlanProfileListingComponent, - RouterModule - ], - providers: [ - DatasetService - ] -}) - -export class DataManagamentPlanProfileModule { - constructor(private translate: TranslateService) { - translate.setDefaultLang('en'); - translate.use('en'); - } -} - -export function HttpLoaderFactory(httpClient: HttpClient) { - return new TranslateHttpLoader(httpClient, 'assets/lang/', '.json'); -} diff --git a/dmp-frontend/src/app/dmp-profiles/dmp-profile.routes.ts b/dmp-frontend/src/app/dmp-profiles/dmp-profile.routes.ts deleted file mode 100644 index 5b0a4c02a..000000000 --- a/dmp-frontend/src/app/dmp-profiles/dmp-profile.routes.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { RouterModule, Routes } from '@angular/router'; -import { DataManagementPlanProfileListingComponent } from './dmp-profile-listing/dmp-profile-listing.component'; -import { DataManagementPlanProfileEditorComponent } from './dmp-profile-editor/dmp-profile-editor.component'; -import { AuthGuard } from '../shared/guards/auth.guard'; - -export const DataManagementPlanProfileRoutes: Routes = [ - { path: '', component: DataManagementPlanProfileListingComponent, canActivate: [AuthGuard] }, - { path: 'new', component: DataManagementPlanProfileEditorComponent, canActivate: [AuthGuard] }, - { path: ':id', component: DataManagementPlanProfileEditorComponent, canActivate: [AuthGuard] }, -]; diff --git a/dmp-frontend/src/app/dmps/dmps.module.ts b/dmp-frontend/src/app/dmps/dmps.module.ts deleted file mode 100644 index 8ef282837..000000000 --- a/dmp-frontend/src/app/dmps/dmps.module.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { AddResearchersComponent } from '../shared/components/add-researchers/add-researchers.component'; -import { DatasetWizardListingComponent } from './wizard/listing/dataset-wizard-listing.component'; -import { DataManagementPlanWizardEditorComponent } from './wizard/editor/dmp-wizard-editor.component'; -import { DataManagementPlanWizardComponent } from './wizard/dmp-wizard.component'; -import { TranslateHttpLoader } from '@ngx-translate/http-loader'; -import { BaseHttpService } from '../utilities/cite-http-service-module/base-http.service'; -import { InvitationAcceptedComponent } from '../shared/components/invitation-accepted/invitation-accepted.component'; -import { InvitationComponent } from '../shared/components/invitation/invitation.component'; -import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; -import { DataManagementPlanEditorComponent } from './editor/dmp-editor.component'; -import { DataManagementPlanListingComponent } from './listing/dmp-listing.component'; -import { DataManagementPlanRoutes } from './dmps.routes'; -import { HttpClient, HttpClientModule } from '@angular/common/http'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { CommonModule } from '@angular/common'; -import { CovalentDialogsModule } from '@covalent/core'; - -import { SharedModule } from '../shared/shared.module'; -import { NgModule } from '@angular/core'; -import { AvailableProfilesComponent } from '../shared/components/available-profiles/available-profiles.component'; -import { DynamicDmpFieldResolverComponent } from './editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component'; -import { DynamicFieldsProjectComponent } from './editor/dynamic-fields-project/dynamic-fields-project.component'; -import { DynamicFieldProjectComponent } from './editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component'; -import { BaseHttpModule } from '../utilities/cite-http-service-module/cite-http.module'; -import { DataManagementPlanService } from '../services/data-management-plan/data-management-plan.service'; -import { DataManagementPlanProfileService } from '../services/data-management-plan-profile/datamanagement-profile.service'; -import { ProjectService } from '../services/project/project.service'; -import { ExternalSourcesService } from '../services/external-sources/external-sources.service'; -import { MaterialModule } from '../shared/material/material.module'; -import { RouterModule } from '@angular/router'; -import { ResearcherService } from '../services/researchers/researchers.service'; -import { InvitationService } from '../services/invitation/invitation.service'; -import { DatasetService } from '../services/dataset/dataset.service'; -import { FlexLayoutModule } from '@angular/flex-layout'; -import { DMPFinaliseDialogComponent } from './editor/dmp-finalise-dialog/dmp-finalise-dialog.component'; - -@NgModule({ - imports: [ - CommonModule, - FormsModule, - HttpClientModule, - SharedModule, - MaterialModule, - RouterModule.forChild(DataManagementPlanRoutes), - ReactiveFormsModule, - TranslateModule.forRoot({ - loader: { - provide: TranslateLoader, - useFactory: HttpLoaderFactory, - deps: [HttpClient] - } - }), - CovalentDialogsModule - ], - - declarations: [ - DataManagementPlanListingComponent, - DataManagementPlanEditorComponent, - InvitationComponent, - InvitationAcceptedComponent, - DataManagementPlanWizardComponent, - DataManagementPlanWizardEditorComponent, - DatasetWizardListingComponent, - AddResearchersComponent, - AvailableProfilesComponent, - DynamicDmpFieldResolverComponent, - DynamicFieldsProjectComponent, - DynamicFieldProjectComponent, - DMPFinaliseDialogComponent - ], - - exports: [ - DataManagementPlanListingComponent, - DataManagementPlanEditorComponent, - InvitationComponent, - InvitationAcceptedComponent, - DataManagementPlanWizardComponent, - DataManagementPlanWizardEditorComponent, - DatasetWizardListingComponent, - AddResearchersComponent, - AvailableProfilesComponent, - DynamicFieldsProjectComponent, - DynamicFieldProjectComponent, - RouterModule, - DMPFinaliseDialogComponent - ], - entryComponents: [ - InvitationComponent, - AddResearchersComponent, - AvailableProfilesComponent, - DMPFinaliseDialogComponent - ], - providers: [ - ProjectService, - ResearcherService, - DatasetService, - InvitationService, - DataManagementPlanService, - ExternalSourcesService, - DataManagementPlanProfileService - ] -}) - -export class DataManagementPlanModule { - constructor(private translate: TranslateService) { - translate.setDefaultLang('en'); - translate.use('en'); - } -} - -export function HttpLoaderFactory(httpClient: HttpClient) { - return new TranslateHttpLoader(httpClient, 'assets/lang/', '.json'); -} diff --git a/dmp-frontend/src/app/dmps/dmps.routes.ts b/dmp-frontend/src/app/dmps/dmps.routes.ts deleted file mode 100644 index b11423076..000000000 --- a/dmp-frontend/src/app/dmps/dmps.routes.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { DataManagementPlanWizardComponent } from './wizard/dmp-wizard.component'; -import { DataManagementPlanEditorComponent } from './editor/dmp-editor.component'; -import { DataManagementPlanListingComponent } from './listing/dmp-listing.component'; -import { DatasetListingComponent } from '../datasets/listing/dataset-listing.component'; -import { RouterModule, Routes } from '@angular/router'; -import { InvitationAcceptedComponent } from '../shared/components/invitation-accepted/invitation-accepted.component'; - -export const DataManagementPlanRoutes: Routes = [ - { - path: '', - component: DataManagementPlanListingComponent, - data: { - breadcrumb: true - }, - }, - { - path: 'viewversions/:groupId', - component: DataManagementPlanListingComponent, - data: { - breadcrumb: true - }, - }, - { - path: 'project/:projectId', - component: DataManagementPlanListingComponent, - data: { - breadcrumb: true - }, - }, - { - path: 'edit/:id', - component: DataManagementPlanEditorComponent, - data: { - breadcrumb: true - }, - }, - { - path: 'new', - component: DataManagementPlanEditorComponent, - data: { - breadcrumbs: 'new' - } - }, - { - path: 'new_version/:id', - component: DataManagementPlanWizardComponent, - data: { - clone: false, - breadcrumb: true - }, - }, - { - path: 'clone/:id', - component: DataManagementPlanWizardComponent, - data: { - clone: false, - breadcrumb: true - }, - }, - { - path: 'invitation/:id', - component: InvitationAcceptedComponent, - data: { - breadcrumb: true - }, - } -]; diff --git a/dmp-frontend/src/app/dmps/editor/dmp-editor.component.html b/dmp-frontend/src/app/dmps/editor/dmp-editor.component.html deleted file mode 100644 index eead77c3b..000000000 --- a/dmp-frontend/src/app/dmps/editor/dmp-editor.component.html +++ /dev/null @@ -1,149 +0,0 @@ -
-
- {{'DMP-EDITOR.TITLE.NEW' | translate}} - -

{{formGroup?.get('label')?.value}}

-
-
-
- - -
-
-
-
-
- -
-
- -
-
- -
- - - - - - - - - -
-
-
-
- -
- - - {{baseErrorModel.label}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - - - - - {{errorModel.description}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - - -
- - -
- -
-
- - -
- -
-
-
- - - -
- - -
-
-
-
- - -
-
- -
-
-
- - - - - - - -
- -

Associated Users

- - person -
{{user.name}}
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
- -
diff --git a/dmp-frontend/src/app/dmps/editor/dmp-editor.component.ts b/dmp-frontend/src/app/dmps/editor/dmp-editor.component.ts deleted file mode 100644 index cc8bca3af..000000000 --- a/dmp-frontend/src/app/dmps/editor/dmp-editor.component.ts +++ /dev/null @@ -1,432 +0,0 @@ -import { AfterViewInit, Component, ViewContainerRef, ViewEncapsulation } from '@angular/core'; -import { FormControl, FormGroup } from '@angular/forms'; -import { MatDialog, MatSnackBar } from '@angular/material'; -import { ActivatedRoute, Params, Router } from '@angular/router'; -import { TdDialogService } from '@covalent/core'; -import { TranslateService } from '@ngx-translate/core'; -import * as FileSaver from 'file-saver'; -import { Observable } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { BaseCriteria } from '../../models/criteria/BaseCriteria'; -import { DatasetProfileCriteria } from '../../models/criteria/dataset-profile/DatasetProfileCriteria'; -import { DataManagementPlanProfileCriteria } from '../../models/criteria/dmp-profile/DataManagementPlanProfileCriteria'; -import { ProjectCriteria } from '../../models/criteria/project/ProjectCriteria'; -import { RequestItem } from '../../models/criteria/RequestItem'; -import { DataManagementPlanProfileListingModel } from '../../models/data-management-plan-profile/DataManagementPlanProfileListingModel'; -import { DataManagementPlanModel, DataManagementPlanStatus } from '../../models/data-managemnt-plans/DataManagementPlanModel'; -import { DatasetListingModel } from '../../models/datasets/DatasetListingModel'; -import { DatasetProfileModel } from '../../models/datasets/DatasetProfileModel'; -import { DmpUsersModel } from '../../models/dmpUsers/DmpUsersModel'; -import { BaseErrorModel } from '../../models/error/BaseErrorModel'; -import { ExternalSourcesItemModel } from '../../models/external-sources/ExternalSourcesItemModel'; -import { DataManagementPlanProfileService } from '../../services/data-management-plan-profile/datamanagement-profile.service'; -import { DataManagementPlanService } from '../../services/data-management-plan/data-management-plan.service'; -import { ExternalSourcesService } from '../../services/external-sources/external-sources.service'; -import { LanguageResolverService } from '../../services/language-resolver/language-resolver.service'; -import { ProjectService } from '../../services/project/project.service'; -import { AddResearchersComponent } from '../../shared/components/add-researchers/add-researchers.component'; -import { MultipleAutoCompleteConfiguration } from '../../shared/components/autocompletes/multiple/multiple-auto-complete-configuration'; -import { SingleAutoCompleteConfiguration } from '../../shared/components/autocompletes/single/single-auto-complete-configuration'; -import { AvailableProfilesComponent } from '../../shared/components/available-profiles/available-profiles.component'; -import { BreadcrumbItem } from '../../shared/components/breadcrumb/definition/breadcrumb-item'; -import { IBreadCrumbComponent } from '../../shared/components/breadcrumb/definition/IBreadCrumbComponent'; -import { SnackBarNotificationComponent } from '../../shared/components/notificaiton/snack-bar-notification.component'; -import { JsonSerializer } from '../../utilities/JsonSerializer'; -import { DMPFinaliseDialogComponent } from './dmp-finalise-dialog/dmp-finalise-dialog.component'; -import { Status } from '../../models/Status'; - -@Component({ - selector: 'app-dmp-editor-component', - templateUrl: 'dmp-editor.component.html', - styleUrls: ['./dmp-editor.component.scss'], - encapsulation: ViewEncapsulation.None -}) -export class DataManagementPlanEditorComponent extends BaseComponent implements AfterViewInit, IBreadCrumbComponent { - - editMode = false; - - breadCrumbs: Observable; - isNew = true; - textCtrl = new FormControl(); - dataManagementPlan: DataManagementPlanModel; - formGroup: FormGroup = null; - - filteringOrganisationsAsync = false; - filteringResearchersAsync = false; - filteredProfilesAsync = false; - filteredOrganisations: ExternalSourcesItemModel[]; - filteredResearchers: ExternalSourcesItemModel[]; - filteredProfiles: DatasetProfileModel[]; - - projectAutoCompleteConfiguration: SingleAutoCompleteConfiguration; - profilesAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; - organisationsAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; - researchersAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; - - createNewVersion; - associatedUsers: Array; - filteredOptions: Observable; - - constructor( - private dmpProfileService: DataManagementPlanProfileService, - private dataManagementPlanService: DataManagementPlanService, - private projectService: ProjectService, - private externalSourcesService: ExternalSourcesService, - private route: ActivatedRoute, - public snackBar: MatSnackBar, - public router: Router, - public language: TranslateService, - private _service: DataManagementPlanService, - public dialog: MatDialog, - private _dialogService: TdDialogService, - private _viewContainerRef: ViewContainerRef, - private languageResolverService: LanguageResolverService - ) { - super(); - this.filteredOptions = dmpProfileService.getAll({ criteria: new DataManagementPlanProfileCriteria() }); - } - - ngAfterViewInit() { - this.route.params - .pipe(takeUntil(this._destroyed)) - .subscribe((params: Params) => { - const itemId = params['id']; - - const projectRequestItem: RequestItem = new RequestItem(); - projectRequestItem.criteria = new ProjectCriteria(); - const organisationRequestItem: RequestItem = new RequestItem(); - organisationRequestItem.criteria = new BaseCriteria(); - - - - this.projectAutoCompleteConfiguration = { - filterFn: this.searchProject.bind(this), - items: this.searchProject(''), - displayFn: (item) => item['label'], - titleFn: (item) => item['label'], - //mapFn: (item) => new JsonSerializer().fromJSONArray(item, ProjectReference).map(item => item.toDropdownList()), - loadDataOnStart: true - }; - - this.profilesAutoCompleteConfiguration = { - filterFn: this.filterProfiles.bind(this), - initialItems: (excludedItems: any[]) => this.filterProfiles('').map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1)), - displayFn: (item) => item['label'], - titleFn: (item) => item['label'], - //mapFn: (item) => new JsonSerializer().fromJSONArray(item, ProjectReference).map(item => item.toDropdownList()), - loadDataOnStart: true - }; - - this.organisationsAutoCompleteConfiguration = { - filterFn: this.filterOrganisations.bind(this), - initialItems: (excludedItems: any[]) => this.filterOrganisations('').map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1)), - displayFn: (item) => item['name'], - titleFn: (item) => item['name'], - loadDataOnStart: true - }; - - this.researchersAutoCompleteConfiguration = { - filterFn: this.filterResearchers.bind(this), - initialItems: (excludedItems: any[]) => this.filterResearchers('').map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1)), - displayFn: (item) => item['name'], - titleFn: (item) => item['name'], - loadDataOnStart: true - }; - - if (itemId != null) { - this.isNew = false; - this.dataManagementPlanService.getSingle(itemId).map(data => data as DataManagementPlanModel) - .pipe(takeUntil(this._destroyed)) - .subscribe(async data => { - this.dataManagementPlan = JsonSerializer.fromJSONObject(data, DataManagementPlanModel); - this.formGroup = this.dataManagementPlan.buildForm(); - if (!this.editMode || this.dataManagementPlan.status === Status.Inactive) { this.formGroup.disable(); } - if (this.formGroup.get('profile') && this.formGroup.get('profile').value) { - this.textCtrl.patchValue(this.formGroup.get('profile').value); - } - this.breadCrumbs = Observable.of([ - { - parentComponentName: 'DataManagementPlanListingComponent', - label: 'DMPs', - url: 'dmps', - notFoundResolver: [await this.projectService.getSingle(this.dataManagementPlan.project.id).map(x => ({ label: x.label, url: '/projects/edit/' + x.id }) as BreadcrumbItem).toPromise()] - }] - ); - this.associatedUsers = data.associatedUsers; - }); - } else { - this.dataManagementPlan = new DataManagementPlanModel(); - setTimeout(async () => { - this.formGroup = this.dataManagementPlan.buildForm(); - if (this.formGroup.get('profile') && this.formGroup.get('profile').value) { - this.textCtrl.patchValue(this.formGroup.get('profile').value); - } - this.breadCrumbs = Observable.of([ - { - parentComponentName: 'DataManagementPlanListingComponent', - label: 'DMPs', - url: 'dmps', - } - ]); - }); - } - - }); - this.route - .queryParams - .pipe(takeUntil(this._destroyed)) - .subscribe(params => { - this.createNewVersion = params['clone']; - }); - } - - searchProject(query: string) { - const projectRequestItem: RequestItem = new RequestItem(); - projectRequestItem.criteria = new ProjectCriteria(); - projectRequestItem.criteria.like = query; - return this.projectService.getWithExternal(projectRequestItem); - } - - formSubmit(): void { - //this.touchAllFormFields(this.formGroup); - if (!this.isFormValid()) { return; } - this.onSubmit(); - } - - public isFormValid() { - return this.formGroup.valid; - } - - onSubmit(): void { - this.dataManagementPlanService.createDataManagementPlan(this.formGroup.value) - .pipe(takeUntil(this._destroyed)) - .subscribe( - complete => this.onCallbackSuccess(), - error => this.onCallbackError(error) - ); - } - - onCallbackSuccess(): void { - this.snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, - duration: 3000, - }); - this.router.navigate(['/dmps']); - } - - onCallbackError(error: any) { - this.setErrorModel(error.error); - //this.validateAllFormFields(this.formGroup); - } - - public setErrorModel(errorModel: BaseErrorModel) { - Object.keys(errorModel).forEach(item => { - (this.dataManagementPlan.errorModel)[item] = (errorModel)[item]; - }); - } - - public cancel(): void { - this.router.navigate(['/dmps']); - } - - public invite(): void { - this.router.navigate(['/invite/' + this.dataManagementPlan.id]); - } - - filterOrganisations(value: string): Observable { - - this.filteredOrganisations = undefined; - this.filteringOrganisationsAsync = true; - - return this.externalSourcesService.searchDMPOrganizations(value); - } - - filterResearchers(value: string): Observable { - - this.filteredResearchers = undefined; - this.filteringResearchersAsync = true; - - return this.externalSourcesService.searchDMPResearchers({ criteria: { name: value, like: null } }); - } - - filterProfiles(value: string): Observable { - - this.filteredProfiles = undefined; - this.filteredProfilesAsync = true; - - const request = new RequestItem(); - const criteria = new DatasetProfileCriteria(); - criteria.like = value; - request.criteria = criteria; - return this._service.searchDMPProfiles(request); - } - - addResearcher(rowId: any, rowName: any) { - const dialogRef = this.dialog.open(AddResearchersComponent, { - data: { - dmpId: rowId, - dmpName: rowName - } - }); - - } - - availableProfiles() { - const dialogRef = this.dialog.open(AvailableProfilesComponent, { - // height: '355px', - // width: '700px', - data: { - profiles: this.formGroup.get('profiles') - } - }); - - return false; - } - - openConfirm(dmpLabel, id): void { - this._dialogService.openConfirm({ - message: 'Are you sure you want to delete the "' + dmpLabel + '"', - disableClose: true || false, - viewContainerRef: this._viewContainerRef, - title: 'Confirm', - cancelButton: 'No', - acceptButton: 'Yes' - }).afterClosed() - .pipe(takeUntil(this._destroyed)) - .subscribe((accept: boolean) => { - if (accept) { - this.dataManagementPlanService.delete(id) - .pipe(takeUntil(this._destroyed)) - .subscribe(() => { - this.router.navigate(['/dmps']); - }); - } else { - // DO SOMETHING ELSE - } - }); - } - - - selectOption(option: any) { - this.dataManagementPlan.definition = null; - this.formGroup.get('profile').patchValue(option, { emitEvent: false }); - this.dmpProfileService.getSingle(option.id) - .pipe(takeUntil(this._destroyed)) - .subscribe(result => { - this.dataManagementPlan.definition = result.definition; - }); - } - - displayWith(item: any) { - if (!item) { return null; } - return item['label']; - } - - redirectToProject() { - this.router.navigate(['projects/edit/' + this.dataManagementPlan.project.id]); - } - - redirectToDatasets() { - this.router.navigate(['datasets/dmp/' + this.dataManagementPlan.id]); - } - - newVersion(id: String, label: String) { - this.router.navigate(['/dmps/new_version/' + id, { dmpLabel: label }]); - } - - clone(id: String) { - this.router.navigate(['/dmps/clone/' + id]); - } - - viewVersions(rowId: String, rowLabel: String) { - this.router.navigate(['/dmps/viewversions/' + rowId], { queryParams: { groupLabel: rowLabel } }); - } - - downloadXml(id: string) { - this.dataManagementPlanService.downloadXML(id) - .pipe(takeUntil(this._destroyed)) - .subscribe(response => { - const blob = new Blob([response.body], { type: 'application/xml' }); - const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition')); - - FileSaver.saveAs(blob, filename); - }); - } - - downloadDocx(id: string) { - this.dataManagementPlanService.downloadDocx(id) - .pipe(takeUntil(this._destroyed)) - .subscribe(response => { - const blob = new Blob([response.body], { type: 'application/octet-stream' }); - const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition')); - - FileSaver.saveAs(blob, filename); - }); - } - - downloadPDF(id: string) { - this.dataManagementPlanService.downloadPDF(id) - .pipe(takeUntil(this._destroyed)) - .subscribe(response => { - const blob = new Blob([response.body], { type: 'application/octet-stream' }); - const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition')); - - FileSaver.saveAs(blob, filename); - }); - } - - getFilenameFromContentDispositionHeader(header: string): string { - const regex: RegExp = new RegExp(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/g); - - const matches = header.match(regex); - let filename: string; - for (let i = 0; i < matches.length; i++) { - const match = matches[i]; - if (match.includes('filename="')) { - filename = match.substring(10, match.length - 1); - break; - } else if (match.includes('filename=')) { - filename = match.substring(9); - break; - } - } - return filename; - } - - public enableForm() { - if (this.formGroup.get('status').value !== DataManagementPlanStatus.Finalised) { - this.editMode = true; - this.formGroup.enable(); - } else { - this.dataManagementPlanService.unlock(this.formGroup.get('id').value) - .pipe(takeUntil(this._destroyed)) - .subscribe(x => { - this.editMode = true; - this.formGroup.get('status').patchValue(DataManagementPlanStatus.Draft); - this.formGroup.enable(); - }); - } - } - - public disableForm() { - this.editMode = false; - this.formGroup.disable(); - } - - saveAndFinalize() { - const dialogRef = this.dialog.open(DMPFinaliseDialogComponent, { - data: { - submitFunction: (items: DatasetListingModel[]) => { - this.formGroup.get('status').setValue('1'); - this.formGroup.addControl('datasets', new FormControl(items)); - this.formSubmit(); - dialogRef.close(); - }, - dmp: this.dataManagementPlan - } - }); - } - - -} diff --git a/dmp-frontend/src/app/dmps/editor/dmp-finalise-dialog/dmp-finalise-dialog.component.html b/dmp-frontend/src/app/dmps/editor/dmp-finalise-dialog/dmp-finalise-dialog.component.html deleted file mode 100644 index 669e15e03..000000000 --- a/dmp-frontend/src/app/dmps/editor/dmp-finalise-dialog/dmp-finalise-dialog.component.html +++ /dev/null @@ -1,31 +0,0 @@ -
-
-
-
-
- {{'DMP-FINALISE-DIALOG.ALREADY-FINALISED-DATASETS' | translate}} - - -
{{ dataset.label }}
-
-
-
-
- {{'DMP-FINALISE-DIALOG.FINALISE-TITLE' | translate}} - - - {{ dataset.label }} - - -
- {{'DMP-FINALISE-DIALOG.VALIDATION.AT-LEAST-ONE-DATASET-FINALISED' - | translate}} -
-
-
- -
-
-
diff --git a/dmp-frontend/src/app/dmps/editor/dmp-finalise-dialog/dmp-finalise-dialog.component.ts b/dmp-frontend/src/app/dmps/editor/dmp-finalise-dialog/dmp-finalise-dialog.component.ts deleted file mode 100644 index 62772d962..000000000 --- a/dmp-frontend/src/app/dmps/editor/dmp-finalise-dialog/dmp-finalise-dialog.component.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { Component, Inject, OnInit, ViewChild } from '@angular/core'; -import { AbstractControl, FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms'; -import { MatDialogRef, MatSelectionList, MAT_DIALOG_DATA } from '@angular/material'; -import { Router } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { DatasetCriteria } from '../../../models/criteria/dataset/DatasetCriteria'; -import { DataManagementPlanModel } from '../../../models/data-managemnt-plans/DataManagementPlanModel'; -import { DataTableRequest } from '../../../models/data-table/DataTableRequest'; -import { DatasetListingModel } from '../../../models/datasets/DatasetListingModel'; -import { DatasetStatus } from '../../../models/datasets/DatasetWizardModel'; -import { DatasetService } from '../../../services/dataset/dataset.service'; - -@Component({ - selector: 'app-dmp-finalise-dialog-component', - templateUrl: 'dmp-finalise-dialog.component.html', - -}) -export class DMPFinaliseDialogComponent extends BaseComponent implements OnInit { - - @ViewChild('datasetsDraftSelectionList') selectionList: MatSelectionList; - public formGroup: FormGroup; - public submitFunction: (items: DatasetListingModel[]) => any; - public dmp: DataManagementPlanModel; - public datasetsFinalised: DatasetListingModel[]; - public datasetsDraft: DatasetListingModel[]; - constructor( - public router: Router, - public dialogRef: MatDialogRef, - public dmpService: DatasetService, - @Inject(MAT_DIALOG_DATA) public data: any - ) { - super(); - this.submitFunction = data['submitFunction']; - this.dmp = data['dmp']; - } - - ngOnInit(): void { - this.initialiseDatasetFinalisedRequest(); - this.initialiseDMPFinalisedRequest(); - } - - initialiseDatasetFinalisedRequest() { - const request = new DataTableRequest(null, null, null); - request.criteria = new DatasetCriteria(); - request.criteria.dmpIds = [this.dmp.id]; - request.criteria.status = DatasetStatus.Finalised; - this.dmpService.getPaged(request).map(x => x.data) - .pipe(takeUntil(this._destroyed)) - .subscribe(result => { - this.datasetsFinalised = result; - this.createFormGroup(); - }); - } - - - initialiseDMPFinalisedRequest() { - const request = new DataTableRequest(null, null, null); - request.criteria = new DatasetCriteria(); - request.criteria.dmpIds = [this.dmp.id]; - request.criteria.status = DatasetStatus.Draft; - this.dmpService.getPaged(request).map(x => x.data) - .pipe(takeUntil(this._destroyed)) - .subscribe(result => { - this.datasetsDraft = result; - }); - } - - createFormGroup() { - this.formGroup = new FormBuilder().group({ - datasets: [this.datasetsFinalised, this.minLengthArray(1)] - }); - } - - onSubmit() { - //this.formGroup.get('datasets').patchValue(this.formGroup.get('datasets').value.push(this.selectionList.selectedOptions.selected.map(x => x.value))); - this.touchAllFormFields(this.formGroup); - if (!this.formGroup.valid) { return; } - this.submitFunction(this.formGroup.get('datasets').value); - } - - minLengthArray(min: number) { - return (c: AbstractControl): { [key: string]: any } => { - if (c.value.length >= min) { - return null; - } - return { 'minLengthArray': { valid: false } }; - }; - } - - public touchAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.markAsTouched(); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.touchAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.touchAllFormFields(item); - }); - } - } -} diff --git a/dmp-frontend/src/app/dmps/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.html b/dmp-frontend/src/app/dmps/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.html deleted file mode 100644 index 972942d61..000000000 --- a/dmp-frontend/src/app/dmps/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.html +++ /dev/null @@ -1,15 +0,0 @@ -
-
- - - - - - - - - - - -
-
\ No newline at end of file diff --git a/dmp-frontend/src/app/dmps/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.ts b/dmp-frontend/src/app/dmps/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.ts deleted file mode 100644 index ae779c2ff..000000000 --- a/dmp-frontend/src/app/dmps/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Component, ViewEncapsulation, AfterViewInit, Input, OnInit, OnDestroy } from '@angular/core'; -import { DataManagementPlanProfile } from '../../../models/data-management-plan-profile/DataManagementPlanProfile'; -import { DMPProfileFieldDataType, DMPProfileType } from '../../../models/data-management-plan-profile/DataManagementProfileField'; -import { FormGroup, FormBuilder, FormArray } from '@angular/forms'; -import { LanguageResolverService } from '../../../services/language-resolver/language-resolver.service'; - -@Component({ - selector: 'app-dynamic-dmp-field-resolver', - templateUrl: 'dynamic-dmp-field-resolver.component.html', - styleUrls: ['./dynamic-dmp-field-resolver.component.scss'], - encapsulation: ViewEncapsulation.None -}) -export class DynamicDmpFieldResolverComponent implements OnInit, OnDestroy { - - - DMPProfileFieldDataType = DMPProfileFieldDataType; - DMPProfileType = DMPProfileType; - - @Input() - dataManagementPlanProfile: DataManagementPlanProfile; - - @Input() - formGroup: FormGroup; - - ngOnInit(): void { - this.formGroup.addControl('properties', new FormBuilder().group([])); - (this.formGroup.get('properties')).addControl('fields', new FormBuilder().array([])); - - this.dataManagementPlanProfile.fields.forEach(item => { - (this.formGroup.get('properties').get('fields')).push(new FormBuilder().group({ - id: [item.id], - value: [item.value] - })); - }); - } - - ngOnDestroy(): void { - this.formGroup.removeControl('properties'); - } -} diff --git a/dmp-frontend/src/app/dmps/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.ts b/dmp-frontend/src/app/dmps/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.ts deleted file mode 100644 index 63c93bcca..000000000 --- a/dmp-frontend/src/app/dmps/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { Component, ViewEncapsulation, OnInit, Input, ViewChild } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { DataManagementPlanService } from '../../../../services/data-management-plan/data-management-plan.service'; -import { RequestItem } from '../../../../models/criteria/RequestItem'; -import { DynamicFieldProjectCriteria, DynamicFieldProjectCriteriaDependencies } from '../../../../models/dynamic-field-project/DynamicFieldProjectCriteria'; -import { AutoCompleteComponent } from '../../../../shared/components/auto-complete/auto-complete.component'; -import { DynamicFieldDependency } from '../../../../models/data-managemnt-plans/DynamicFieldDependency'; -import { LanguageResolverService } from '../../../../services/language-resolver/language-resolver.service'; -import { AutoCompleteConfiguration } from '../../../../shared/components/auto-complete/AutoCompleteConfiguration'; - -@Component({ - selector: 'app-dynamic-field-project', - templateUrl: 'dynamic-field-project.component.html', - styleUrls: ['./dynamic-field-project.component.scss'], - encapsulation: ViewEncapsulation.None -}) -export class DynamicFieldProjectComponent implements OnInit { - - constructor(private languageResolverService: LanguageResolverService, private dmpService: DataManagementPlanService) { } - - @Input() - dependencies: Array; - - @Input() - formGroup: FormGroup; - - @ViewChild(AutoCompleteComponent) - autocomplete: AutoCompleteComponent; - - autoCompleteConfiguration: AutoCompleteConfiguration; - - ngOnInit(): void { - const requestItem = new RequestItem(); - requestItem.criteria = { id: this.formGroup.get('id').value, dynamicFields: this.buildDependencies() }; - this.autoCompleteConfiguration = new AutoCompleteConfiguration(this.dmpService.getDynamicField.bind(this.dmpService), requestItem); - } - - hasUnResolvedDependencies() { - if (this.dependencies == null || this.dependencies.length === 0) { - if (this.formGroup.get('value').disabled) { - this.updateConfiguration(); - this.formGroup.get('value').enable({ onlySelf: true, emitEvent: false }); - } - return false; - } - for (let i = 0; i < this.dependencies.length; i++) { - if (!this.dependencies[i].get('value').value) { - this.formGroup.get('value').disable({ onlySelf: true, emitEvent: false }); - return true; - } - } - if (this.formGroup.get('value').disabled) { - this.updateConfiguration(); - this.formGroup.get('value').enable({ onlySelf: true, emitEvent: false }); - } - return false; - } - - updateConfiguration() { - const requestItem = new RequestItem(); - requestItem.criteria = { id: this.formGroup.get('id').value, dynamicFields: this.buildDependencies() }; - this.autoCompleteConfiguration = new AutoCompleteConfiguration(this.dmpService.getDynamicField.bind(this.dmpService), requestItem); - this.autocomplete.inputData = this.autoCompleteConfiguration; - } - - buildDependencies(): Array { - if (!this.dependencies || this.dependencies.length === 0) { return []; } - const dependencies = new Array(); - for (let i = 0; i < this.dependencies.length; i++) { - dependencies.push({ property: this.dependencies[i].get('id').value, value: this.assignFunction(this.dependencies[i].get('value').value) }); - } - return dependencies; - } - - displayFunction(item: any): any { - if (!item) { return null; } - return item['label']; - } - - assignFunction(item: any): any { - if (!item) { return null; } - return item['id']; - } -} diff --git a/dmp-frontend/src/app/dmps/editor/dynamic-fields-project/dynamic-fields-project.component.ts b/dmp-frontend/src/app/dmps/editor/dynamic-fields-project/dynamic-fields-project.component.ts deleted file mode 100644 index d862b8ba6..000000000 --- a/dmp-frontend/src/app/dmps/editor/dynamic-fields-project/dynamic-fields-project.component.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Component, ViewEncapsulation, OnInit, OnDestroy, Input } from '@angular/core'; -import { FormGroup, FormArray } from '@angular/forms'; -import { DynamicFieldDependency } from '../../../models/data-managemnt-plans/DynamicFieldDependency'; - -@Component({ - selector: 'app-dynamic-fields-project', - templateUrl: 'dynamic-fields-project.component.html', - styleUrls: ['./dynamic-fields-project.component.scss'], - encapsulation: ViewEncapsulation.None -}) -export class DynamicFieldsProjectComponent implements OnInit { - - @Input() - formGroup: FormGroup; - - ngOnInit(): void { - } - - findDependencies(id: number) { - const formGroupDependencies: Array = new Array(); - const dynamicFieldDependency: DynamicFieldDependency[] = (this.formGroup.get('dynamicFields')).at(id).get('dependencies').value; - if (dynamicFieldDependency.length > 0) { - dynamicFieldDependency.forEach(item => { - const length = (this.formGroup.get('dynamicFields')).length; - for (let i = 0; i < length; i++) { - const formGroup = (this.formGroup.get('dynamicFields')).at(i); - if (formGroup.get('id').value === item.id) { formGroupDependencies.push(formGroup); } - } - }); - } - return formGroupDependencies; - } -} diff --git a/dmp-frontend/src/app/dmps/listing/dmp-listing.component.html b/dmp-frontend/src/app/dmps/listing/dmp-listing.component.html deleted file mode 100644 index d0e16a003..000000000 --- a/dmp-frontend/src/app/dmps/listing/dmp-listing.component.html +++ /dev/null @@ -1,91 +0,0 @@ -
-

{{'DMP-LISTING.TITLE' | translate}} {{titlePrefix}}

- - - - - - - - - - - - {{'DMP-LISTING.COLUMNS.NAME' | translate}} - {{row.label}} - - - - - {{'DMP-LISTING.COLUMNS.PROJECT' | - translate}} - {{row.project}} - - - - - {{'DMP-LISTING.COLUMNS.STATUS' | translate}} - {{this.utilities.convertFromDMPStatus(row.status)}} - - - - - {{'DMP-LISTING.COLUMNS.CREATION-TIME' | translate}} - {{row.creationTime | date:'shortDate'}} - - - - - {{'DMP-LISTING.COLUMNS.ORGANISATIONS' | translate}} - {{row.organisations}} - - - - - {{'DMP-LISTING.COLUMNS.LATEST_VERSION' | translate}} - {{row.version}} - - - - - {{'DMP-LISTING.COLUMNS.DATASETS' | translate}} - - - - - - - {{'DMP-LISTING.COLUMNS.ACTIONS' | translate}} - - - - - - - - - - - - - - - - - - - - -
diff --git a/dmp-frontend/src/app/dmps/listing/dmp-listing.component.scss b/dmp-frontend/src/app/dmps/listing/dmp-listing.component.scss deleted file mode 100644 index f28168d87..000000000 --- a/dmp-frontend/src/app/dmps/listing/dmp-listing.component.scss +++ /dev/null @@ -1,35 +0,0 @@ -.mat-table { - margin: 24px; -} - -.mat-fab-bottom-right { - top: auto !important; - right: 20px !important; - bottom: 10px !important; - left: auto !important; - position: fixed !important; -} - -.full-width { - width: 100%; -} - -.mat-card { - margin: 16px 0; -} - -.mat-row { - cursor: pointer; -} - -mat-row:hover { - background-color: lightgray; -} - -mat-row:nth-child(odd){ - background-color:#eef0fb; - } - -h3{ - margin-top: 0px; -} diff --git a/dmp-frontend/src/app/dmps/listing/dmp-listing.component.ts b/dmp-frontend/src/app/dmps/listing/dmp-listing.component.ts deleted file mode 100644 index de2fbb0fa..000000000 --- a/dmp-frontend/src/app/dmps/listing/dmp-listing.component.ts +++ /dev/null @@ -1,204 +0,0 @@ -import { DataSource } from '@angular/cdk/table'; -import { Component, OnInit, ViewChild } from '@angular/core'; -import { MatDialog, MatPaginator, MatSnackBar, MatSort } from '@angular/material'; -import { ActivatedRoute, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { DataManagementPlanCriteria } from '../../models/criteria/data-management-plan/DataManagementPlanCriteria'; -import { DataManagementPlanListingModel } from '../../models/data-managemnt-plans/DataManagementPlanListingModel'; -import { DataTableRequest } from '../../models/data-table/DataTableRequest'; -import { ProjectModel } from '../../models/projects/ProjectModel'; -import { DataManagementPlanService } from '../../services/data-management-plan/data-management-plan.service'; -import { BreadcrumbItem } from '../../shared/components/breadcrumb/definition/breadcrumb-item'; -import { IBreadCrumbComponent } from '../../shared/components/breadcrumb/definition/IBreadCrumbComponent'; -import { DataManagementPlanCriteriaComponent } from '../../shared/components/criteria/data-management-plan/dmp-criteria.component'; -import { InvitationComponent } from '../../shared/components/invitation/invitation.component'; -import { JsonSerializer } from '../../utilities/JsonSerializer'; -import { Utilities } from '../../utilities/utilities'; - -@Component({ - selector: 'app-dmp-listing-component', - templateUrl: 'dmp-listing.component.html', - styleUrls: ['./dmp-listing.component.scss'], - providers: [Utilities] -}) -export class DataManagementPlanListingComponent extends BaseComponent implements OnInit, IBreadCrumbComponent { - - @ViewChild(MatPaginator) _paginator: MatPaginator; - @ViewChild(MatSort) sort: MatSort; - @ViewChild(DataManagementPlanCriteriaComponent) criteria: DataManagementPlanCriteriaComponent; - - breadCrumbs: Observable = Observable.of([]); - dataSource: DataManagementPlanDataSource | null; - displayedColumns: String[] = ['name', 'project', 'status', 'creationTime', 'organisations', 'version', 'datasets', 'actions']; - itemId: string; - projectId: string; - showProject: boolean; - titlePrefix: string; - constructor( - private dataManagementPlanService: DataManagementPlanService, - private router: Router, - private route: ActivatedRoute, - private languageService: TranslateService, - public snackBar: MatSnackBar, - public dialog: MatDialog, - public utilities: Utilities - ) { - super(); - } - - ngOnInit() { - this.route.params - .pipe(takeUntil(this._destroyed)) - .subscribe(async params => { - let projectLabel; - if (params['projectId']) { - this.projectId = params['projectId']; - this.showProject = false; - const project = new ProjectModel(); - project.id = this.projectId; - this.criteria.setCriteria({ like: null, projects: [project], groupIds: null, allVersions: false }); - this.refresh(); - projectLabel = this.route.snapshot.queryParams.projectLabel; - this.breadCrumbs = Observable.of([{ parentComponentName: 'ProjectEditorComponent', label: projectLabel, url: '/projects/edit/' + this.projectId }]); - this.criteria.setRefreshCallback(() => this.refresh()); - } else { - this.itemId = params['groupId']; - this.showProject = true; - const breadCrumbs = []; - - if (this.itemId) { - const dmplabel = this.route.snapshot.queryParams.groupLabel; - breadCrumbs.push( - { parentComponentName: null, label: 'DMPs', url: '/dmps' }, - ); - } - //else breadCrumbs.push({ parentComponentName: null, label: 'DMPs', url: "/dmps" }) - this.breadCrumbs = Observable.of(breadCrumbs); - - this.criteria.setCriteria(this.getDefaultCriteria()); - this.refresh(); - this.criteria.setRefreshCallback(() => this.refresh()); - } - - if (this.projectId != null) { - if (projectLabel !== undefined) { - this.titlePrefix = 'for ' + projectLabel; - } - } - }); - - } - - refresh() { - this.dataSource = new DataManagementPlanDataSource(this.dataManagementPlanService, this._paginator, this.sort, this.languageService, this.snackBar, this.criteria, this.itemId); - } - - rowClick(rowId: String) { - this.router.navigate(['/dmps/edit/' + rowId]); - } - - addDataset(rowId: String) { - this.router.navigate(['/datasets/new/' + rowId]); - } - - showDatasets(rowId: String, rowLabel: String) { - this.router.navigate(['/datasets/dmp/' + rowId, { dmpLabel: rowLabel }]); - } - - viewVersions(rowId: String, rowLabel: String) { - this.router.navigate(['/dmps/viewversions/' + rowId], { queryParams: { groupLabel: rowLabel } }); - } - - getDefaultCriteria(): DataManagementPlanCriteria { - const defaultCriteria = new DataManagementPlanCriteria(); - return defaultCriteria; - } - - openShareDialog(rowId: any, rowName: any) { - const dialogRef = this.dialog.open(InvitationComponent, { - height: '200px', - width: '700px', - data: { - dmpId: rowId, - dmpName: rowName - } - }); - } -} - -export class DataManagementPlanDataSource extends DataSource { - - totalCount = 0; - isLoadingResults = false; - constructor( - private _service: DataManagementPlanService, - private _paginator: MatPaginator, - private _sort: MatSort, - private _languageService: TranslateService, - private _snackBar: MatSnackBar, - private _criteria: DataManagementPlanCriteriaComponent, - private itemId - ) { - super(); - } - - connect(): Observable { - const displayDataChanges = [ - this._paginator.page - ]; - - return Observable.merge(...displayDataChanges) - .startWith(null) - .switchMap(() => { - setTimeout(() => { - this.isLoadingResults = true; - }); - const startIndex = this._paginator.pageIndex * this._paginator.pageSize; - let fields: Array = new Array(); - if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; } - const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); - request.criteria = this._criteria.formGroup.value; - if (this.itemId) { - request.criteria.groupIds = [this.itemId]; - request.criteria.allVersions = true; - } - return this._service.getPaged(request); - }) - /*.catch((error: any) => { - this._snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService }, - duration: 3000, - extraClasses: ['snackbar-warning'] - }); - return Observable.of(null); - })*/ - .map(result => { - result.data = JsonSerializer.fromJSONArray(result.data, DataManagementPlanListingModel); - return result; - }) - .map(result => { - setTimeout(() => { - this.isLoadingResults = false; - }); - return result; - }) - .map(result => { - if (!result) { return []; } - if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; } - return result.data.map(item => { - item['datasets'].map(dmp => { - dmp.url = 'datasets/edit/' + dmp.url; - dmp.all = 'datasets/dmp/' + item.id; - return dmp; - }); - return item; - }); - }); - } - - disconnect() { - } -} diff --git a/dmp-frontend/src/app/dmps/wizard/dmp-wizard.component.html b/dmp-frontend/src/app/dmps/wizard/dmp-wizard.component.html deleted file mode 100644 index 93ec8b314..000000000 --- a/dmp-frontend/src/app/dmps/wizard/dmp-wizard.component.html +++ /dev/null @@ -1,19 +0,0 @@ -
- - - {{'DMP-WIZARD.FIRST-STEP.DMP' | translate}} - - - - - {{'DMP-WIZARD.FIRST-STEP.DATASETS' | translate}} - - - - -
diff --git a/dmp-frontend/src/app/dmps/wizard/dmp-wizard.component.ts b/dmp-frontend/src/app/dmps/wizard/dmp-wizard.component.ts deleted file mode 100644 index ba0dc9fea..000000000 --- a/dmp-frontend/src/app/dmps/wizard/dmp-wizard.component.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { MatSnackBar } from '@angular/material'; -import { ActivatedRoute, Params, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { DataManagementPlanModel } from '../../models/data-managemnt-plans/DataManagementPlanModel'; -import { BaseErrorModel } from '../../models/error/BaseErrorModel'; -import { DataManagementPlanService } from '../../services/data-management-plan/data-management-plan.service'; -import { BreadcrumbItem } from '../../shared/components/breadcrumb/definition/breadcrumb-item'; -import { IBreadCrumbComponent } from '../../shared/components/breadcrumb/definition/IBreadCrumbComponent'; -import { SnackBarNotificationComponent } from '../../shared/components/notificaiton/snack-bar-notification.component'; -import { JsonSerializer } from '../../utilities/JsonSerializer'; - -@Component({ - selector: 'app-dmp-wizard-component', - templateUrl: 'dmp-wizard.component.html', - styleUrls: ['./dmp-wizard.component.scss'], -}) -export class DataManagementPlanWizardComponent extends BaseComponent implements OnInit, IBreadCrumbComponent { - breadCrumbs: Observable; - constructor( - private dataManagementPlanService: DataManagementPlanService, - private language: TranslateService, - public snackBar: MatSnackBar, - public route: ActivatedRoute, - private router: Router - ) { super(); } - - public itemId: string; - public dataManagementPlan: DataManagementPlanModel; - public formGroup: FormGroup; - public isClone: boolean; - - ngOnInit(): void { - - this.route.params - .pipe(takeUntil(this._destroyed)) - .subscribe((params: Params) => { - this.itemId = params['id']; - this.dataManagementPlanService.getSingle(this.itemId).map(data => data as DataManagementPlanModel) - .pipe(takeUntil(this._destroyed)) - .subscribe(data => { - this.dataManagementPlan = JsonSerializer.fromJSONObject(data, DataManagementPlanModel); - this.isClone = this.route.snapshot.data.clone; - if (this.isClone === false) { this.dataManagementPlan.version = this.dataManagementPlan.version + 1; } - this.formGroup = this.dataManagementPlan.buildForm(); - }); - }); - } - - - submit() { - if (this.isClone) { - this.dataManagementPlanService.clone(this.formGroup.getRawValue(), this.itemId) - .pipe(takeUntil(this._destroyed)) - .subscribe( - complete => this.onCallbackSuccess(), - error => this.onCallbackError(error) - ); - } else { - this.dataManagementPlanService.newVersion(this.formGroup.getRawValue(), this.itemId) - .pipe(takeUntil(this._destroyed)) - .subscribe( - complete => this.onCallbackSuccess(), - error => this.onCallbackError(error) - ); - } - } - - onCallbackSuccess(): void { - this.snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, - duration: 3000, - }); - this.router.navigate(['/dmps']); - } - - onCallbackError(error: any) { - this.setErrorModel(error.error); - //this.validateAllFormFields(this.formGroup); - } - - public setErrorModel(errorModel: BaseErrorModel) { - Object.keys(errorModel).forEach(item => { - // (this.dataManagementPlan.errorModel)[item] = (errorModel)[item]; - }); - } - - -} diff --git a/dmp-frontend/src/app/dmps/wizard/editor/dmp-wizard-editor.component.html b/dmp-frontend/src/app/dmps/wizard/editor/dmp-wizard-editor.component.html deleted file mode 100644 index 29120353d..000000000 --- a/dmp-frontend/src/app/dmps/wizard/editor/dmp-wizard-editor.component.html +++ /dev/null @@ -1,72 +0,0 @@ -
-
- - - - - {{baseErrorModel.label}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - - - - - {{errorModel.description}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - - -
- - -
-
-
- - -
- -
-
-
-
- - -
-
-
-
- - -
-
- -
-
-
- - - - - - - -

Associated Users

- - person -
{{user.name}}
-
-
-
-
-
- -
diff --git a/dmp-frontend/src/app/dmps/wizard/editor/dmp-wizard-editor.component.ts b/dmp-frontend/src/app/dmps/wizard/editor/dmp-wizard-editor.component.ts deleted file mode 100644 index 23bfd1bd4..000000000 --- a/dmp-frontend/src/app/dmps/wizard/editor/dmp-wizard-editor.component.ts +++ /dev/null @@ -1,194 +0,0 @@ -import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { MatSnackBar } from '@angular/material'; -import { ActivatedRoute, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { BaseCriteria } from '../../../models/criteria/BaseCriteria'; -import { DatasetProfileCriteria } from '../../../models/criteria/dataset-profile/DatasetProfileCriteria'; -import { ProjectCriteria } from '../../../models/criteria/project/ProjectCriteria'; -import { RequestItem } from '../../../models/criteria/RequestItem'; -import { DatasetProfileModel } from '../../../models/datasets/DatasetProfileModel'; -import { DmpUsersModel } from '../../../models/dmpUsers/DmpUsersModel'; -import { BaseErrorModel } from '../../../models/error/BaseErrorModel'; -import { ExternalSourcesItemModel } from '../../../models/external-sources/ExternalSourcesItemModel'; -import { DataManagementPlanService } from '../../../services/data-management-plan/data-management-plan.service'; -import { ExternalSourcesService } from '../../../services/external-sources/external-sources.service'; -import { LanguageResolverService } from '../../../services/language-resolver/language-resolver.service'; -import { ProjectService } from '../../../services/project/project.service'; -import { MultipleAutoCompleteConfiguration } from '../../../shared/components/autocompletes/multiple/multiple-auto-complete-configuration'; -import { SingleAutoCompleteConfiguration } from '../../../shared/components/autocompletes/single/single-auto-complete-configuration'; -import { SnackBarNotificationComponent } from '../../../shared/components/notificaiton/snack-bar-notification.component'; - -@Component({ - selector: 'app-dmp-wizard-editor-component', - templateUrl: 'dmp-wizard-editor.component.html', - styleUrls: ['./dmp-wizard-editor.component.scss'], - encapsulation: ViewEncapsulation.None -}) -export class DataManagementPlanWizardEditorComponent extends BaseComponent implements OnInit { - - - isNew = true; - @Input() formGroup: FormGroup = null; - - filteringOrganisationsAsync = false; - filteringResearchersAsync = false; - filteredProfilesAsync = false; - filteredOrganisations: ExternalSourcesItemModel[]; - filteredResearchers: ExternalSourcesItemModel[]; - filteredProfiles: DatasetProfileModel[]; - - projectAutoCompleteConfiguration: SingleAutoCompleteConfiguration; - profilesAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; - organisationsAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; - researchersAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; - createNewVersion; - associatedUsers: Array; - labelDisabled = false; - - constructor( - private dataManagementPlanService: DataManagementPlanService, - private projectService: ProjectService, - private externalSourcesService: ExternalSourcesService, - private route: ActivatedRoute, - public snackBar: MatSnackBar, - public router: Router, - public language: TranslateService, - private _service: DataManagementPlanService, - private languageResolverService: LanguageResolverService - ) { - super(); - } - - ngOnInit() { - - const projectRequestItem: RequestItem = new RequestItem(); - projectRequestItem.criteria = new ProjectCriteria(); - this.projectAutoCompleteConfiguration = { - filterFn: this.searchProject.bind(this.projectService), - items: this.searchProject(''), - displayFn: (item) => item['label'], - titleFn: (item) => item['label'], - //mapFn: (item) => new JsonSerializer().fromJSONArray(item, ProjectReference).map(item => item.toDropdownList()), - loadDataOnStart: true - }; - - this.profilesAutoCompleteConfiguration = { - filterFn: this.filterProfiles.bind(this), - initialItems: (excludedItems: any[]) => this.filterProfiles('').map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1)), - displayFn: (item) => item['label'], - titleFn: (item) => item['label'], - //mapFn: (item) => new JsonSerializer().fromJSONArray(item, ProjectReference).map(item => item.toDropdownList()), - loadDataOnStart: true - }; - - this.organisationsAutoCompleteConfiguration = { - filterFn: this.filterOrganisations.bind(this), - initialItems: (excludedItems: any[]) => this.filterOrganisations('').map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1)), - displayFn: (item) => item['name'], - titleFn: (item) => item['name'], - loadDataOnStart: true - }; - - this.researchersAutoCompleteConfiguration = { - filterFn: this.filterResearchers.bind(this), - initialItems: (excludedItems: any[]) => this.filterResearchers('').map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1)), - displayFn: (item) => item['name'], - titleFn: (item) => item['name'], - loadDataOnStart: true - }; - - const organisationRequestItem: RequestItem = new RequestItem(); - organisationRequestItem.criteria = new BaseCriteria(); - - this.route.data - .pipe(takeUntil(this._destroyed)) - .subscribe(value => { - if (value.clone === false && this.formGroup.get('label').value) { - this.labelDisabled = true; - } - this.formGroup.controls['version'].disable(); - }); - } - - searchProject(query: string) { - const projectRequestItem: RequestItem = new RequestItem(); - projectRequestItem.criteria = new ProjectCriteria(); - projectRequestItem.criteria.like = query; - return this.projectService.getWithExternal(projectRequestItem); - } - - formSubmit(): void { - //this.touchAllFormFields(this.formGroup); - if (!this.isFormValid()) { return; } - this.onSubmit(); - } - - public isFormValid() { - return this.formGroup.valid; - } - - onSubmit(): void { - this.dataManagementPlanService.createDataManagementPlan(this.formGroup.getRawValue()) - .pipe(takeUntil(this._destroyed)) - .subscribe( - complete => this.onCallbackSuccess(), - error => this.onCallbackError(error) - ); - } - - onCallbackSuccess(): void { - this.snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, - duration: 3000, - }); - this.router.navigate(['/dmps']); - } - - onCallbackError(error: any) { - this.setErrorModel(error.error); - //this.validateAllFormFields(this.formGroup); - } - - public setErrorModel(errorModel: BaseErrorModel) { - Object.keys(errorModel).forEach(item => { - // (this.dataManagementPlan.errorModel)[item] = (errorModel)[item]; - }); - } - - public cancel(): void { - this.router.navigate(['/dmps']); - } - - filterOrganisations(value: string): Observable { - - this.filteredOrganisations = undefined; - this.filteringOrganisationsAsync = true; - - return this.externalSourcesService.searchDMPOrganizations(value); - } - - filterResearchers(value: string): Observable { - - this.filteredResearchers = undefined; - this.filteringResearchersAsync = true; - - return this.externalSourcesService.searchDMPResearchers({ criteria: { name: value, like: null } }); - } - - filterProfiles(value: string): Observable { - - this.filteredProfiles = undefined; - this.filteredProfilesAsync = true; - - const request = new RequestItem(); - const criteria = new DatasetProfileCriteria(); - criteria.like = value; - request.criteria = criteria; - return this._service.searchDMPProfiles(request); - } - -} diff --git a/dmp-frontend/src/app/dmps/wizard/listing/dataset-wizard-listing.component.scss b/dmp-frontend/src/app/dmps/wizard/listing/dataset-wizard-listing.component.scss deleted file mode 100644 index 2688cb118..000000000 --- a/dmp-frontend/src/app/dmps/wizard/listing/dataset-wizard-listing.component.scss +++ /dev/null @@ -1,35 +0,0 @@ -.mat-table { - margin: 24px; -} - -.mat-fab-bottom-right { - top: auto !important; - right: 20px !important; - bottom: 10px !important; - left: auto !important; - position: fixed !important; -} - -.full-width { - width: 100%; -} - -.mat-card { - margin: 16px 0; -} - -.mat-row { - cursor: pointer; -} - -mat-row:hover { - background-color: lightgray; -} - -// mat-row:nth-child(even){ -// background-color:red; -// } - -mat-row:nth-child(odd){ - background-color:#eef0fb; - } \ No newline at end of file diff --git a/dmp-frontend/src/app/dmps/wizard/listing/dataset-wizard-listing.component.ts b/dmp-frontend/src/app/dmps/wizard/listing/dataset-wizard-listing.component.ts deleted file mode 100644 index 81d670480..000000000 --- a/dmp-frontend/src/app/dmps/wizard/listing/dataset-wizard-listing.component.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { SelectionModel } from '@angular/cdk/collections'; -import { Component, Input, OnInit, ViewChild } from '@angular/core'; -import { FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms'; -import { MatPaginator, MatSnackBar, MatSort } from '@angular/material'; -import { ActivatedRoute, Params, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { DatasetCriteria } from '../../../models/criteria/dataset/DatasetCriteria'; -import { DataTableRequest } from '../../../models/data-table/DataTableRequest'; -import { DatasetListingModel } from '../../../models/datasets/DatasetListingModel'; -import { DataManagementPlanService } from '../../../services/data-management-plan/data-management-plan.service'; -import { DatasetService } from '../../../services/dataset/dataset.service'; -import { DatasetCriteriaComponent } from '../../../shared/components/criteria/datasets/datasets-criteria.component'; -import { JsonSerializer } from '../../../utilities/JsonSerializer'; - -@Component({ - selector: 'app-dataset-wizard-listing-component', - templateUrl: 'dataset-wizard-listing.component.html', - styleUrls: ['./dataset-wizard-listing.component.scss'], -}) -export class DatasetWizardListingComponent extends BaseComponent implements OnInit { - - @ViewChild(MatPaginator) _paginator: MatPaginator; - @ViewChild(MatSort) sort: MatSort; - @ViewChild(DatasetCriteriaComponent) criteria: DatasetCriteriaComponent; - - - titlePrefix: String; - datasets: DatasetListingModel[] = []; - - @Input() dmpId: String; - @Input() formGroup: FormGroup; - selection = new SelectionModel(true, []); - - statuses = [ - { value: '0', viewValue: 'Active' }, - { value: '1', viewValue: 'Inactive' } - ]; - - constructor( - private datasetService: DatasetService, - private router: Router, - private languageService: TranslateService, - public snackBar: MatSnackBar, - public route: ActivatedRoute, - public dataManagementPlanService: DataManagementPlanService - ) { - super(); - } - - - ngOnInit() { - this.route.params - .pipe(takeUntil(this._destroyed)) - .subscribe((params: Params) => { - if (this.dmpId != null) { - if (params['dmpLabel'] !== undefined) { - this.titlePrefix = 'for ' + params['dmpLabel']; - } - } - }); - const request: DataTableRequest = new DataTableRequest(null, null, null); - request.criteria = new DatasetCriteria(); - request.criteria.dmpIds = [this.dmpId]; - this.datasetService.getPaged(request) - .pipe(takeUntil(this._destroyed)) - .subscribe(items => { - this.datasets = JsonSerializer.fromJSONArray(items.data, DatasetListingModel); - }); - this.formGroup.addControl('datasets', new FormBuilder().array(new Array())); - } - - selectionChanged(event, selectedItems) { - this.formGroup.removeControl('datasets'); - this.formGroup.addControl('datasets', new FormBuilder().array(new Array())); - selectedItems.selectedOptions.selected.forEach(element => { - (this.formGroup.get('datasets')).push(new FormBuilder().group({ id: element.value })); - }); - } -} diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.ts b/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.ts deleted file mode 100644 index 7da2cd68c..000000000 --- a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { ActivatedRoute } from '@angular/router'; -import { AutocompleteLookupItem } from '../../../models/auto-complete/AutocompleteLookupItem'; -import { RequestItem } from '../../../models/criteria/RequestItem'; -import { Field } from '../../../models/Field'; -import { DatasetProfileService } from '../../../services/dataset-profile.service'; -import { AutoCompleteConfiguration } from '../../../shared/components/auto-complete/AutoCompleteConfiguration'; -declare var $: any; - - -@Component({ - selector: 'app-df-autocomplete', - templateUrl: './autocomplete-remote.component.html', - styleUrls: ['./autocomplete-remote.component.css'] -}) -export class AutocompleteRemoteComponent implements OnInit/* , ControlValueAccessor */ { - - - @Input() field: Field; - @Input() disabled = false; - @Input() form: FormGroup; - - public autoCompleteConfiguration: AutoCompleteConfiguration; - public loading: boolean; - public datasetId; - public values: any[] = new Array(); - public typeaheadMS = 1400; - - constructor(private datasetProfileService: DatasetProfileService, route: ActivatedRoute) { - this.datasetId = route.snapshot.params['id']; - } - - - ngOnInit() { - const autocompleteRequestItem: RequestItem = new RequestItem(); - autocompleteRequestItem.criteria = new AutocompleteLookupItem(); - autocompleteRequestItem.criteria.fieldID = this.field.id; - autocompleteRequestItem.criteria.profileID = this.datasetId; - this.autoCompleteConfiguration = new AutoCompleteConfiguration(this.datasetProfileService.queryAutocomplete.bind(this.datasetProfileService), autocompleteRequestItem); - - } - - displayWith(item: any) { - if (!item) { return null; } - if (typeof item === 'string') { item = this.transform(item); } - return item['label']; - } - - assign(item: any) { - if (!item) { return null; } - return this.transform(item); - } - - transform(item: any) { - if (typeof item === 'string') { return JSON.parse(item); } else { return JSON.stringify(item); } - } -} - diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-boolean-decision/dynamic-field-boolean-decision.component.html b/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-boolean-decision/dynamic-field-boolean-decision.component.html deleted file mode 100644 index 040305675..000000000 --- a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-boolean-decision/dynamic-field-boolean-decision.component.html +++ /dev/null @@ -1,5 +0,0 @@ - - Yes -
- No -
diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-boolean-decision/dynamic-field-boolean-decision.component.ts b/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-boolean-decision/dynamic-field-boolean-decision.component.ts deleted file mode 100644 index 7f9b166da..000000000 --- a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-boolean-decision/dynamic-field-boolean-decision.component.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { FormGroup } from '@angular/forms'; -import { Field } from '../../../models/Field'; -import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; - -@Component({ - selector: 'app-df-boolean-decision', - templateUrl: './dynamic-field-boolean-decision.component.html', - styleUrls: [ - './dynamic-field-boolean-decision.component.css' - ], - encapsulation: ViewEncapsulation.None -}) -export class DynamicFieldBooleanDecisionComponent implements OnInit { - @Input() field: Field; - @Input() form: FormGroup; - - ngOnInit() { - - } -} diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-checkbox/dynamic-field-checkbox.html b/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-checkbox/dynamic-field-checkbox.html deleted file mode 100644 index fd9c9ebaf..000000000 --- a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-checkbox/dynamic-field-checkbox.html +++ /dev/null @@ -1 +0,0 @@ -{{field.data.label}} diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-checkbox/dynamic-field-checkbox.ts b/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-checkbox/dynamic-field-checkbox.ts deleted file mode 100644 index bf9f658c6..000000000 --- a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-checkbox/dynamic-field-checkbox.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { Field } from '../../../models/Field'; - -@Component({ - selector: 'app-df-checkbox', - templateUrl: './dynamic-field-checkbox.html', - styleUrls: [ - './dynamic-field-checkbox.css' - ] -}) -export class DynamicFieldCheckBoxComponent implements OnInit { - - @Input() field: Field; - @Input() form: FormGroup; - - ngOnInit(): void { - if (this.form.get('value').value === null) { this.form.get('value').patchValue(false); } - } -} diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-dropdown/dynamic-field-dropdown.css b/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-dropdown/dynamic-field-dropdown.css deleted file mode 100644 index 9709a9aea..000000000 --- a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-dropdown/dynamic-field-dropdown.css +++ /dev/null @@ -1,3 +0,0 @@ -.dynamic-field-dropdown { - width: 100%; -} diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-dropdown/dynamic-field-dropdown.html b/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-dropdown/dynamic-field-dropdown.html deleted file mode 100644 index 3f8b30484..000000000 --- a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-dropdown/dynamic-field-dropdown.html +++ /dev/null @@ -1,6 +0,0 @@ - - - {{opt.label}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-dropdown/dynamic-field-dropdown.ts b/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-dropdown/dynamic-field-dropdown.ts deleted file mode 100644 index 73bca7303..000000000 --- a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-dropdown/dynamic-field-dropdown.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { FormGroup } from '@angular/forms'; -import { Field } from '../../../models/Field'; -import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; - -@Component({ - selector: 'app-df-dropdown', - templateUrl: './dynamic-field-dropdown.html', - styleUrls: [ - './dynamic-field-dropdown.css' - ] -}) -export class DynamicFieldDropdownComponent implements OnInit { - @Input() field: Field; - @Input() form: FormGroup; - - ngOnInit() { - - } - - assign(item: any) { - if (!item) { return null; } - return this.transform(item); - } - - transform(item: any) { - if (typeof item === 'string') { return JSON.parse(item); } else { return JSON.stringify(item); } - } -} diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-radiobox/dynamic-field-radiobox.component.css b/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-radiobox/dynamic-field-radiobox.component.css deleted file mode 100644 index 3eeae76a7..000000000 --- a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-radiobox/dynamic-field-radiobox.component.css +++ /dev/null @@ -1,9 +0,0 @@ -.radio-label { - margin-left: 10px; -} -.mat-radio-group .mat-radio-inline { - display: flex; -} -.radio-button{ - margin-right: 15px; -} \ No newline at end of file diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-radiobox/dynamic-field-radiobox.component.html b/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-radiobox/dynamic-field-radiobox.component.html deleted file mode 100644 index 84ea39f02..000000000 --- a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-radiobox/dynamic-field-radiobox.component.html +++ /dev/null @@ -1,9 +0,0 @@ -
- -
- {{option.label}} -
-
-
- - \ No newline at end of file diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-radiobox/dynamic-field-radiobox.component.ts b/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-radiobox/dynamic-field-radiobox.component.ts deleted file mode 100644 index 3985106e7..000000000 --- a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-radiobox/dynamic-field-radiobox.component.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { FormGroup } from '@angular/forms'; -import { Field } from '../../../models/Field'; -import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; - - -@Component({ - selector: 'app-df-radiobox', - templateUrl: './dynamic-field-radiobox.component.html', - styleUrls: [ - './dynamic-field-radiobox.component.css' - ], - encapsulation: ViewEncapsulation.None -}) -export class DynamicFieldRadioBoxComponent implements OnInit { - @Input() field: Field; - @Input() form: FormGroup; - - ngOnInit() { - - } -} diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-form-field.component.css b/dmp-frontend/src/app/form/dynamic-fields/dynamic-form-field.component.css deleted file mode 100644 index e28a671b5..000000000 --- a/dmp-frontend/src/app/form/dynamic-fields/dynamic-form-field.component.css +++ /dev/null @@ -1,2 +0,0 @@ -.dynamic-form-field { -} \ No newline at end of file diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-form-field.component.html b/dmp-frontend/src/app/form/dynamic-fields/dynamic-form-field.component.html deleted file mode 100644 index bebcc257c..000000000 --- a/dmp-frontend/src/app/form/dynamic-fields/dynamic-form-field.component.html +++ /dev/null @@ -1,146 +0,0 @@ -
- - - - -
{{field.description}}
-
- {{field.extendedDescription}} -
- - - - {{'GENERAL.VALIDATION.REQUIRED' - | translate}} - - -
- -
- -
-
- -
-
- - - - - - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - - - - - - -
- - - - -
- - - - - - - - - - - - - - diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-form-field.component.ts b/dmp-frontend/src/app/form/dynamic-fields/dynamic-form-field.component.ts deleted file mode 100644 index 50d7b67cf..000000000 --- a/dmp-frontend/src/app/form/dynamic-fields/dynamic-form-field.component.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Component, Input, OnChanges, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { ActivatedRoute } from '@angular/router'; -import { Subscription } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { Field } from '../../models/Field'; -import { VisibilityRulesService } from '../../utilities/visibility-rules/visibility-rules.service'; - -@Component({ - selector: 'app-df-field', - templateUrl: './dynamic-form-field.component.html', - // styles: ['.checkBoxLabelCustom {font-weight: 700;}'] - styleUrls: [ - './dynamic-form-field.component.css' - ] -}) -export class DynamicFormFieldComponent extends BaseComponent implements OnInit, OnChanges, OnDestroy { - @Input() field: Field; - form: FormGroup; - - change: Subscription; - trackByFn = (index, item) => item ? item['id'] : null; - - constructor( - private route: ActivatedRoute, - public visibilityRulesService: VisibilityRulesService - ) { - super(); - } - - ngOnInit() { - if (this.field) { - this.form = this.visibilityRulesService.getFormGroup(this.field.id); - this.change = this.form.get('value').valueChanges - .pipe(takeUntil(this._destroyed)) - .subscribe(item => { - this.visibilityRulesService.updateValueAndVisibility(this.field.id); - }); - } - } - - ngOnChanges(changeRecord) { - - } - - ngOnDestroy(): void { - //Called once, before the instance is destroyed. - //Add 'implements OnDestroy' to the class. - if (this.change) { this.change.unsubscribe(); } - } - - clearInput() { - } - - get isValid() { - return this.form.get('value').valid; - } - get isValidRequired() { - return this.form.get('value').hasError('required'); - } - get isValidPattern() { - return this.form.get('value').hasError('pattern'); - } - get isValidCustom() { - return this.form.get('value').hasError('forbiddenName'); - } -} diff --git a/dmp-frontend/src/app/form/dynamic-form-composite-field/dynamic-form-composite-field.html b/dmp-frontend/src/app/form/dynamic-form-composite-field/dynamic-form-composite-field.html deleted file mode 100644 index a3dad5cfe..000000000 --- a/dmp-frontend/src/app/form/dynamic-form-composite-field/dynamic-form-composite-field.html +++ /dev/null @@ -1,47 +0,0 @@ -
- -
-
-
{{compositeField.numbering}} - {{compositeField.title}} - -
-
{{compositeField.description}}
-
- {{compositeField.extendedDescription}} -
- -
-
-
-
-
{{compositeField.numbering}}{{compositeField.title}}
-
-
{{compositeField.description}}
-
- {{compositeField.extendedDescription}} -
-
- - -
- -
-
- -
-
-
-
-
-
-
-
diff --git a/dmp-frontend/src/app/form/dynamic-form-composite-field/dynamic-form-composite-field.ts b/dmp-frontend/src/app/form/dynamic-form-composite-field/dynamic-form-composite-field.ts deleted file mode 100644 index 7ead1b9b1..000000000 --- a/dmp-frontend/src/app/form/dynamic-form-composite-field/dynamic-form-composite-field.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { VisibilityRulesService } from '../../utilities/visibility-rules/visibility-rules.service'; -import { CompositeField } from '../../models/CompositeField'; -import { FormGroup, FormArray } from '@angular/forms'; -import { Component, Input, OnInit, ViewEncapsulation, ChangeDetectionStrategy } from '@angular/core'; -import { Field } from '../../models/Field'; -import { MarkForConsiderationService } from '../../utilities/mark-for-considerations/mark-for-consideration.service'; -import { FormFocusService } from '../../utilities/form-focus-service/form-focus.service'; -@Component({ - selector: 'app-df-composite-field', - templateUrl: './dynamic-form-composite-field.html', - styleUrls: [ - './dynamic-form-composite-field.css' - ] -}) -export class DynamicFormCompositeFieldComponent implements OnInit { - - @Input() compositeField: CompositeField; - form: FormGroup; - trackByFn = (index, item) => item ? item['id'] : null; - - constructor( - private visibilityRulesService: VisibilityRulesService, - private markForConsiderationService: MarkForConsiderationService, - private formFocusService: FormFocusService - ) { - } - - ngOnInit() { - if (this.compositeField) { - this.form = this.visibilityRulesService.getFormGroup(this.compositeField.id); - } - } - - addMultipleField(fieldIndex: number) { - const field: Field = this.compositeField.fields[fieldIndex].cloneForMultiplicity(fieldIndex, ''); - this.compositeField.fields[fieldIndex].multiplicityItems.push(field); - ((this.form.get('fields').get('' + fieldIndex).get('multiplicityItems'))).push(field.buildForm()); - } - - markForConsideration() { - this.markForConsiderationService.markForConsideration(this.compositeField); - } -} diff --git a/dmp-frontend/src/app/form/dynamic-form-group/dynamic-form-group.component.css b/dmp-frontend/src/app/form/dynamic-form-group/dynamic-form-group.component.css deleted file mode 100644 index 2f19bc1c6..000000000 --- a/dmp-frontend/src/app/form/dynamic-form-group/dynamic-form-group.component.css +++ /dev/null @@ -1,22 +0,0 @@ -.hide{ - display:none; -} - -.show { - display:block; -} - -.group-component { - /* border:1px solid grey; - border-radius: 2px; - padding: 10px; - margin-bottom: 10px; */ -} - -.group-extended-desc { - color: lightslategray; -} - -.content-left-margin { - /* margin-left: 10px; */ -} \ No newline at end of file diff --git a/dmp-frontend/src/app/form/dynamic-form-group/dynamic-form-group.component.html b/dmp-frontend/src/app/form/dynamic-form-group/dynamic-form-group.component.html deleted file mode 100644 index 81afb7efb..000000000 --- a/dmp-frontend/src/app/form/dynamic-form-group/dynamic-form-group.component.html +++ /dev/null @@ -1,20 +0,0 @@ -
-
- -
- - -
-
- -
-
-
-
-
diff --git a/dmp-frontend/src/app/form/dynamic-form-group/dynamic-form-group.component.spec.ts b/dmp-frontend/src/app/form/dynamic-form-group/dynamic-form-group.component.spec.ts deleted file mode 100644 index 25cf5070f..000000000 --- a/dmp-frontend/src/app/form/dynamic-form-group/dynamic-form-group.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; - -import { DynamicFormGroupComponent } from './dynamic-form-group.component'; - -describe('DynamicFormGroupComponent', () => { - let component: DynamicFormGroupComponent; - let fixture: ComponentFixture; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ DynamicFormGroupComponent ] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(DynamicFormGroupComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should be created', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/dmp-frontend/src/app/form/dynamic-form-group/dynamic-form-group.component.ts b/dmp-frontend/src/app/form/dynamic-form-group/dynamic-form-group.component.ts deleted file mode 100644 index 3c0a7060e..000000000 --- a/dmp-frontend/src/app/form/dynamic-form-group/dynamic-form-group.component.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; -import { FormArray, FormGroup } from '@angular/forms'; -import { CompositeField } from '../../models/CompositeField'; -import { FieldGroup } from '../../models/FieldGroup'; -import { VisibilityRulesService } from '../../utilities/visibility-rules/visibility-rules.service'; - - -@Component({ - selector: 'app-df-group', - templateUrl: './dynamic-form-group.component.html', - styleUrls: ['./dynamic-form-group.component.css'], - encapsulation: ViewEncapsulation.None, -}) -export class DynamicFormGroupComponent implements OnInit { - @Input() group: FieldGroup; - form: FormGroup; - @Input() pathName: string; - - @Input() path: string; - trackByFn = (index, item) => item ? item['id'] : null; - constructor(public visibilityRulesService: VisibilityRulesService) { - } - - ngOnInit() { - if (this.group) { - this.form = this.visibilityRulesService.getFormGroup(this.group.id); - } - } - - - addMultipleField(fieldsetIndex: number) { - const compositeField: CompositeField = this.group.compositeFields[fieldsetIndex].cloneForMultiplicity(fieldsetIndex); - this.group.compositeFields[fieldsetIndex].multiplicityItems.push(compositeField); - ((this.form.get('compositeFields').get('' + fieldsetIndex).get('multiplicityItems'))).push(compositeField.buildForm()); - } - - addFieldSet() { - - } - -} diff --git a/dmp-frontend/src/app/form/dynamic-form-section/dynamic-form-section.html b/dmp-frontend/src/app/form/dynamic-form-section/dynamic-form-section.html deleted file mode 100644 index d070257ba..000000000 --- a/dmp-frontend/src/app/form/dynamic-form-section/dynamic-form-section.html +++ /dev/null @@ -1,43 +0,0 @@ -
- - - - -
{{section.numbering}} {{section.title}}
-
- -

{{section.description}}

- -
-
- -
-
-
- -
- -
-
- - - - -
- -
-
-
-
-
-
- -
-
-
-
-
diff --git a/dmp-frontend/src/app/form/dynamic-form-section/dynamic-form-section.ts b/dmp-frontend/src/app/form/dynamic-form-section/dynamic-form-section.ts deleted file mode 100644 index 7989671bb..000000000 --- a/dmp-frontend/src/app/form/dynamic-form-section/dynamic-form-section.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { VisibilityRulesService } from '../../utilities/visibility-rules/visibility-rules.service'; -import { FormGroup, Form, FormArray } from '@angular/forms'; -import { Component, Input, OnInit, ViewEncapsulation, ChangeDetectionStrategy, AfterViewInit } from '@angular/core'; -import { CompositeField } from '../../models/CompositeField'; -import { Section } from '../../models/Section'; -import { FormFocusService } from '../../utilities/form-focus-service/form-focus.service'; - - -@Component({ - selector: 'app-df-section', - templateUrl: './dynamic-form-section.html', - styleUrls: [ - './dynamic-form-section.scss' - ] -}) -export class DynamicFormSectionComponent implements OnInit, AfterViewInit { - - @Input() section: Section; - form: FormGroup; - @Input() pathName: string; - @Input() path: string; - trackByFn = (index, item) => item ? item['id'] : null; - constructor( - public visibilityRulesService: VisibilityRulesService, - private formFocusService: FormFocusService - ) { } - - ngOnInit() { - if (this.section) { - this.form = this.visibilityRulesService.getFormGroup(this.section.id); - } - } - - ngAfterViewInit() { - this.visibilityRulesService.triggerVisibilityEvaluation(); - } - - addMultipleField(fieldsetIndex: number) { - const compositeField: CompositeField = this.section.compositeFields[fieldsetIndex].cloneForMultiplicity(fieldsetIndex); - this.section.compositeFields[fieldsetIndex].multiplicityItems.push(compositeField); - ((this.form.get('compositeFields').get('' + fieldsetIndex).get('multiplicityItems'))).push(compositeField.buildForm()); - } - - isElementVisible(fieldSet: CompositeField): boolean { - if (!fieldSet) { return false; } - for (let i = 0; i < fieldSet.fields.length; i++) { - if (fieldSet.fields[i]) { - return true; - } - } - return false; - } - - next(compositeField: CompositeField) { - this.formFocusService.focusNext(compositeField); - } -} diff --git a/dmp-frontend/src/app/form/dynamic-form.module.ts b/dmp-frontend/src/app/form/dynamic-form.module.ts deleted file mode 100644 index 342fd7ef3..000000000 --- a/dmp-frontend/src/app/form/dynamic-form.module.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { TranslateHttpLoader } from '@ngx-translate/http-loader'; -import { PaginationService } from '../services/pagination.service'; -import { VisibilityRulesService } from '../utilities/visibility-rules/visibility-rules.service'; -import { DynamicFieldCheckBoxComponent } from './dynamic-fields/dynamic-field-checkbox/dynamic-field-checkbox'; -import { ProgressBarComponent } from './pprogress-bar/progress-bar.component'; -import { TableOfContentsFieldComponent } from './tableOfContents/table-of-content-field/table-of-content-field.component'; -import { DynamicFormSectionComponent } from './dynamic-form-section/dynamic-form-section'; -import { DynamicFieldDropdownComponent } from './dynamic-fields/dynamic-field-dropdown/dynamic-field-dropdown'; -import { AutocompleteRemoteComponent } from './dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component'; -import { - TableOfContentsSectionComponent, -} from './tableOfContents/table-of-content-section/table-of-content-section.component'; -import { TableOfContentsGroupComponent } from './tableOfContents/table-of-content-group/table-of-content-group.component'; -import { - TableOfContentsFieldSetComponent, -} from './tableOfContents/table-of-content-fieldset/table-of-content-fieldset.component'; -import { DynamicFieldRadioBoxComponent } from './dynamic-fields/dynamic-field-radiobox/dynamic-field-radiobox.component'; -import { TableOfContentsComponent } from './tableOfContents/table-of-contents.component'; -import { - DynamicFieldBooleanDecisionComponent, -} from './dynamic-fields/dynamic-field-boolean-decision/dynamic-field-boolean-decision.component'; -import { DynamicFormGroupComponent } from './dynamic-form-group/dynamic-form-group.component'; -import { DynamicFormCompositeFieldComponent } from './dynamic-form-composite-field/dynamic-form-composite-field'; -import { DynamicFormFieldComponent } from './dynamic-fields/dynamic-form-field.component'; -import { DynamicFormComponent } from './dynamic-form/dynamic-form.component'; -import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; -import { SharedModule } from '../shared/shared.module'; -import { HttpClient, HttpClientModule } from '@angular/common/http'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { DatasetProfileAdmin } from '../services/datasetProfileAdmin/datasetProfileAfmin.service'; -import { DatasetProfileService } from '../services/dataset-profile.service'; -import { DatasetWizardService } from '../services/dataset-wizard/dataset-wizard.service'; -import { DynamicFormPendingQuestionsDisplayComponent } from './helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component'; -import { MarkForConsiderationService } from '../utilities/mark-for-considerations/mark-for-consideration.service'; -import { FormFocusService } from '../utilities/form-focus-service/form-focus.service'; - - -@NgModule({ - imports: [ - CommonModule, - FormsModule, - HttpClientModule, - SharedModule, - ReactiveFormsModule, - TranslateModule.forRoot({ - loader: { - provide: TranslateLoader, - useFactory: HttpLoaderFactory, - deps: [HttpClient] - } - }), - ], - - declarations: [ - DynamicFormComponent, - DynamicFormFieldComponent, - DynamicFormGroupComponent, - DynamicFormCompositeFieldComponent, - DynamicFieldBooleanDecisionComponent, - DynamicFieldRadioBoxComponent, - DynamicFormPendingQuestionsDisplayComponent, - TableOfContentsComponent, - TableOfContentsFieldSetComponent, - TableOfContentsGroupComponent, - TableOfContentsSectionComponent, - AutocompleteRemoteComponent, - DynamicFieldDropdownComponent, - DynamicFormSectionComponent, - TableOfContentsFieldComponent, - ProgressBarComponent, - DynamicFieldCheckBoxComponent, - ], - - exports: [ - DynamicFormComponent, - DynamicFormFieldComponent, - DynamicFormGroupComponent, - DynamicFormCompositeFieldComponent, - DynamicFieldBooleanDecisionComponent, - DynamicFieldRadioBoxComponent, - DynamicFormPendingQuestionsDisplayComponent, - TableOfContentsComponent, - TableOfContentsFieldSetComponent, - TableOfContentsGroupComponent, - TableOfContentsSectionComponent, - AutocompleteRemoteComponent, - DynamicFieldDropdownComponent, - DynamicFormSectionComponent, - TableOfContentsFieldComponent, - ProgressBarComponent, - DynamicFieldCheckBoxComponent, - ], - providers: [ - VisibilityRulesService, - PaginationService, - DatasetProfileService, - DatasetProfileAdmin, - DatasetWizardService, - MarkForConsiderationService, - FormFocusService - ] -}) - -export class DynamicFormModule { } - -export function HttpLoaderFactory(httpClient: HttpClient) { - return new TranslateHttpLoader(httpClient, 'assets/lang/', '.json'); -} diff --git a/dmp-frontend/src/app/form/dynamic-form/dynamic-form.component.html b/dmp-frontend/src/app/form/dynamic-form/dynamic-form.component.html deleted file mode 100644 index 6dc65b15e..000000000 --- a/dmp-frontend/src/app/form/dynamic-form/dynamic-form.component.html +++ /dev/null @@ -1,39 +0,0 @@ -
-
- - - - - - - - - -
- - -
-
- - {{page.title}} -
- -
-
-
-
-
- -
- -
-
diff --git a/dmp-frontend/src/app/form/dynamic-form/dynamic-form.component.ts b/dmp-frontend/src/app/form/dynamic-form/dynamic-form.component.ts deleted file mode 100644 index eca299da6..000000000 --- a/dmp-frontend/src/app/form/dynamic-form/dynamic-form.component.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { AfterViewInit, Component, Input, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { MatStepper } from '@angular/material'; -import { ActivatedRoute, Router } from '@angular/router'; -import 'rxjs/add/operator/switchMap'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { CompositeField } from '../../models/CompositeField'; -import { DatasetProfileDefinitionModel } from '../../models/DatasetProfileDefinitionModel'; -import { DatasetWizardModel } from '../../models/datasets/DatasetWizardModel'; -import { Pair } from '../../models/helpers/Pair'; -import { Rule } from '../../models/Rule'; -import { Section } from '../../models/Section'; -import '../../utilities/enhancers/flatJoinOn'; -import { FormFocusService } from '../../utilities/form-focus-service/form-focus.service'; -import { JsonSerializer } from '../../utilities/JsonSerializer'; -import { VisibilityRulesService } from '../../utilities/visibility-rules/visibility-rules.service'; - -@Component({ - selector: 'app-dynamic-form', - templateUrl: './dynamic-form.component.html', - styleUrls: [ - './dynamic-form.component.scss' - ], - providers: [ - FormFocusService - ] -}) -export class DynamicFormComponent extends BaseComponent implements OnInit, AfterViewInit { - - pathName: string; - pages: Array; - activeStepperIndex = 1; - visibleSidebar = false; - datasetProfileDefinitionModel: DatasetProfileDefinitionModel; - private progressbar = false; - private currentPageIndex = 0; - @ViewChild('stepper') stepper: MatStepper; - - @Input() dataModel: DatasetWizardModel = new DatasetWizardModel(); - @Input() path: string; - @Input() form: FormGroup; - id: string; - trackByFn = (index, item) => item ? item['id'] : null; - pageTrackByFn = (index, item) => item['id']; - - // @Input() datasetId: string; - - constructor( - private router: Router, - private route: ActivatedRoute, - private visibilityRulesService: VisibilityRulesService, - private formFocusService: FormFocusService - ) { - super(); - //this.datasetId = route.snapshot.params['id']; - } - - getSubForm(subformName) { - return this.form.controls[subformName]; - } - - - ngOnInit() { - - const rules: Rule[] = JsonSerializer.fromJSONArray(this.dataModel.datasetProfileDefinition.rules, Rule); - this.visibilityRulesService.formGroup = this.form; - this.visibilityRulesService.buildVisibilityRules(rules); - this.datasetProfileDefinitionModel = this.dataModel.datasetProfileDefinition; - this.visibilityRulesService.setModel(this.datasetProfileDefinitionModel); - - this.createPagination(); - this.progressbar = true; - - const sections: Pair[] = this.datasetProfileDefinitionModel.pages.map(page => new Pair(page.sections, page.ordinal)).filter(x => x); - const compositeFields: Pair[] = sections.map(section => new Pair(section.left.flatMap(sec => sec.compositeFields), section.right)).filter(x => x); - const nestedSections: Pair[] = sections.map(section => new Pair(section.left.flatMap(x => x.sections), section.right)).filter(x => x); - const nestedCompositeFields: Pair[] = nestedSections.map(section => new Pair(section.left.flatMap(x => x.compositeFields), section.right)).filter(x => x); - const compositeFieldsUnion: Pair[] = compositeFields.concat(nestedCompositeFields); - - //const fields = compositeFieldsUnion.flatJoinOn(x => x.right); - this.formFocusService.setFields(compositeFieldsUnion); - this.route.fragment - .pipe(takeUntil(this._destroyed)) - .subscribe((fragment: string) => { - const self = this; - setTimeout(function () { self.scrollTo(fragment); }); - }); - } - - ngAfterViewInit() { - this.visibilityRulesService.triggerVisibilityEvaluation(); - this.route.queryParams - .pipe(takeUntil(this._destroyed)) - .subscribe((params) => { - if (params && 'page' in params) { - this.changeCurrentPage(params['page']); - } - }); - } - - - toggleSidebar() { - this.visibleSidebar = !this.visibleSidebar; - } - - shouldDisplaySection(section: Section): Boolean { - return (section.page) === this.currentPageIndex; - } - - createPagination() { - - } - - changePageIndex(index: any) { - this.router.navigate([this.route.snapshot.url[0] + '/' + this.route.snapshot.url[1]], { queryParams: { page: this.pages[index - 1] } }); - } - - scrollTo(sectionID: string) { - if (!sectionID) { return; } - const element = document.querySelector('#' + sectionID); - if (!element) { return; } - element.scrollIntoView(); - this.visibleSidebar = true; - } - - changeCurrentPage(pageString: string) { - //if (!pageString) { return; } - const page = parseInt(pageString); - /*if (isNaN(page)) { return; } - const pageIndex = this.pages.indexOf(page); - if (pageIndex === -1) { return; }*/ - this.stepper.selectedIndex = page; - } -} diff --git a/dmp-frontend/src/app/form/fields/dropdown/field-dropdown.css b/dmp-frontend/src/app/form/fields/dropdown/field-dropdown.css deleted file mode 100644 index bf67b66d0..000000000 --- a/dmp-frontend/src/app/form/fields/dropdown/field-dropdown.css +++ /dev/null @@ -1 +0,0 @@ -@CHARSET "UTF-8"; \ No newline at end of file diff --git a/dmp-frontend/src/app/form/fields/dropdown/field-dropdown.html b/dmp-frontend/src/app/form/fields/dropdown/field-dropdown.html deleted file mode 100644 index 8954454ab..000000000 --- a/dmp-frontend/src/app/form/fields/dropdown/field-dropdown.html +++ /dev/null @@ -1,3 +0,0 @@ - \ No newline at end of file diff --git a/dmp-frontend/src/app/form/fields/dropdown/field-dropdown.ts b/dmp-frontend/src/app/form/fields/dropdown/field-dropdown.ts deleted file mode 100644 index 1c5d760d6..000000000 --- a/dmp-frontend/src/app/form/fields/dropdown/field-dropdown.ts +++ /dev/null @@ -1,9 +0,0 @@ - -export class DropdownField { - controlType = 'dropdown'; - options: { key: string, value: string }[] = []; - - constructor(options: {} = {}) { - this.options = options['options'] || []; - } -} diff --git a/dmp-frontend/src/app/form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.html b/dmp-frontend/src/app/form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.html deleted file mode 100644 index 56c01029f..000000000 --- a/dmp-frontend/src/app/form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.html +++ /dev/null @@ -1,4 +0,0 @@ -
- - -
diff --git a/dmp-frontend/src/app/form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.ts b/dmp-frontend/src/app/form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.ts deleted file mode 100644 index 60a3d2d9e..000000000 --- a/dmp-frontend/src/app/form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Component, ViewEncapsulation, OnInit, Input } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { VisibilityRulesService } from '../../../utilities/visibility-rules/visibility-rules.service'; -import { JsonSerializer } from '../../../utilities/JsonSerializer'; -import { Rule } from '../../../models/Rule'; -import { DatasetWizardModel } from '../../../models/datasets/DatasetWizardModel'; -import { DatasetProfileDefinitionModel } from '../../../models/DatasetProfileDefinitionModel'; -import { Section } from '../../../models/Section'; -import { CompositeField } from '../../../models/CompositeField'; -import '../../../utilities/enhancers/flatMap'; -import { Field } from '../../../models/Field'; -import { MarkForConsiderationService } from '../../../utilities/mark-for-considerations/mark-for-consideration.service'; -@Component({ - selector: 'app-dynamic-form-pending-questions-display', - templateUrl: './dynamic-form-pending-questions-display.component.html', - styleUrls: [ - './dynamic-form-pending-questions-display.component.scss' - ], - providers: [ - ], - encapsulation: ViewEncapsulation.None, -}) -export class DynamicFormPendingQuestionsDisplayComponent implements OnInit { - - constructor( - private visibilityRulesService: VisibilityRulesService, - private markForConsideration: MarkForConsiderationService) { - } - - datasetProfileDefinitionModel: DatasetProfileDefinitionModel; - - @Input() - form: FormGroup; - - @Input() dataModel: DatasetWizardModel = new DatasetWizardModel(); - - fields: CompositeField[]; - - ngOnInit(): void { - const rules: Rule[] = JsonSerializer.fromJSONArray(this.dataModel.datasetProfileDefinition.rules, Rule); - this.datasetProfileDefinitionModel = this.dataModel.datasetProfileDefinition; - const sections: Section[] = this.datasetProfileDefinitionModel.pages.flatMap(page => page.sections).filter(x => x); - const compositeFields: CompositeField[] = sections.flatMap(section => section.compositeFields).filter(x => x); - const nestedSections: Section[] = sections.flatMap(section => section.sections).filter(x => x); - const nestedCompositeFiels: CompositeField[] = nestedSections.flatMap(section => section.compositeFields).filter(x => x); - const compositeFieldsUnion = compositeFields.concat(nestedCompositeFiels); - //const fields: Field[] = compositeFields.flatMap(composite => composite.fields).concat(nestedCompositeFiels.flatMap(composite => composite.fields)); - const fields = compositeFieldsUnion.filter(compositeField => this.visibilityRulesService.checkElementVisibility(compositeField.id)) - .filter(compositeField => compositeField.fields.filter(x => x && x.validationRequired && this.visibilityRulesService.getFormGroup(x.id).value == null).length > 0); - fields.forEach(x => this.markForConsideration.markForConsideration(x)); - } -} diff --git a/dmp-frontend/src/app/form/pagination/pagination-service.ts b/dmp-frontend/src/app/form/pagination/pagination-service.ts deleted file mode 100644 index 87e3d6e4d..000000000 --- a/dmp-frontend/src/app/form/pagination/pagination-service.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Injectable } from '@angular/core'; -@Injectable() -export class PaginationService { - - private currentPageIndex: number; - - public setCurrentIndex(currentPageIndex: number): void { - this.currentPageIndex = currentPageIndex; - } - - public getCurrentIndex(): number { - return this.currentPageIndex; - } - - public isElementVisible(elementPage: number): boolean { - return elementPage === this.currentPageIndex; //TODO - } -} diff --git a/dmp-frontend/src/app/form/pprogress-bar/progress-bar.component.html b/dmp-frontend/src/app/form/pprogress-bar/progress-bar.component.html deleted file mode 100644 index bd0007c86..000000000 --- a/dmp-frontend/src/app/form/pprogress-bar/progress-bar.component.html +++ /dev/null @@ -1,5 +0,0 @@ - - -
- -
diff --git a/dmp-frontend/src/app/form/pprogress-bar/progress-bar.component.ts b/dmp-frontend/src/app/form/pprogress-bar/progress-bar.component.ts deleted file mode 100644 index b257100a3..000000000 --- a/dmp-frontend/src/app/form/pprogress-bar/progress-bar.component.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; -import { FormArray, FormGroup } from '@angular/forms'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { VisibilityRulesService } from '../../utilities/visibility-rules/visibility-rules.service'; - -@Component({ - selector: 'app-progress-bar', - templateUrl: './progress-bar.component.html', - styles: ['.alwaysVisible .ui-progressbar-label { display:block!important; }'], - encapsulation: ViewEncapsulation.None -}) -export class ProgressBarComponent extends BaseComponent implements OnInit { - @Input() formGroup: FormGroup; - @Input() public progressValueAccuracy = 1; - determinateProgressValue: number; - - constructor(private visibilityRulesService: VisibilityRulesService) { super(); } - - public value = 0; - ngOnInit() { - this.calculateValueForProgressbar(); - this.formGroup - .valueChanges - .pipe(takeUntil(this._destroyed)) - .subscribe(control => { - this.calculateValueForProgressbar(); - }); - } - - calculateValueForProgressbar() { - const progressSoFar = this.countFormControlsWithValue(this.formGroup); - const total = this.getFormControlDepthLength(this.formGroup); - const perc = (progressSoFar / total) * 100; - this.value = Number.parseFloat(perc.toPrecision(this.progressValueAccuracy)); - } - - countFormControlsWithValue(form: FormGroup): number { - let value = 0; - Object.keys(form.controls).forEach(key => { - const control = form.controls[key]; - if (control instanceof FormGroup) { value += this.countFormControlsWithValue(control); } else if (control instanceof FormArray) { - const formArray = (control); - for (let i = 0; i < formArray.length; i++) { - value += this.countFormControlsWithValue(formArray.get('' + i)); - } - } else if (key === 'value' && control.value != null && control.value !== '') { value++; } - }); - return value; - } - - getFormControlDepthLength(form: FormGroup): number { - let value = 0; - Object.keys(form.controls).forEach(key => { - const control = form.controls[key]; - if (control instanceof FormGroup) { value += this.getFormControlDepthLength(control); } else if (control instanceof FormArray) { - const formArray = (control); - for (let i = 0; i < formArray.length; i++) { - if (formArray.get('' + i).value && this.visibilityRulesService.checkElementVisibility(formArray.get('' + i).value.id)) { - value += this.getFormControlDepthLength(formArray.get('' + i)); - } - } - } else if (key === 'value' && this.visibilityRulesService.checkElementVisibility(form.controls['id'].value)) { - value++; - } - }); - return value; - } -} diff --git a/dmp-frontend/src/app/form/tableOfContents/table-of-content-field/table-of-content-field.component.ts b/dmp-frontend/src/app/form/tableOfContents/table-of-content-field/table-of-content-field.component.ts deleted file mode 100644 index 41915ee23..000000000 --- a/dmp-frontend/src/app/form/tableOfContents/table-of-content-field/table-of-content-field.component.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { VisibilityRulesService } from '../../../utilities/visibility-rules/visibility-rules.service'; -import { BaseTableOfContent } from '../base-table-of-content.component'; -import { CompositeField } from '../../../models/CompositeField'; -import { Field } from '../../../models/Field'; -import { Section } from '../../../models/Section'; -import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; -import { Router, ActivatedRoute } from '@angular/router'; - - -@Component({ - selector: 'app-table-of-contents-field', - templateUrl: './table-of-content-field.component.html', - providers: [] -}) -export class TableOfContentsFieldComponent extends BaseTableOfContent { - @Input() model: Field; - @Input() index: number; - @Input() public path: string; - @Input() public page: number; - constructor(public router: Router, public route: ActivatedRoute, private visibilityRulesService: VisibilityRulesService) { - super(router, route); - } -} diff --git a/dmp-frontend/src/app/form/tableOfContents/table-of-content-fieldset/table-of-content-fieldset.component.ts b/dmp-frontend/src/app/form/tableOfContents/table-of-content-fieldset/table-of-content-fieldset.component.ts deleted file mode 100644 index 9d6fe2f96..000000000 --- a/dmp-frontend/src/app/form/tableOfContents/table-of-content-fieldset/table-of-content-fieldset.component.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { VisibilityRulesService } from '../../../utilities/visibility-rules/visibility-rules.service'; -import { BaseTableOfContent } from '../base-table-of-content.component'; -import { CompositeField } from '../../../models/CompositeField'; -import { FieldGroup } from '../../../models/FieldGroup'; -import { Section } from '../../../models/Section'; -import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; -import { Router, ActivatedRoute } from '@angular/router'; - -//import * as $ from '../../../../node_modules/jquery/dist/jquery' - - -@Component({ - selector: 'app-table-of-contents-fieldset', - templateUrl: './table-of-content-fieldset.component.html', - providers: [] -}) -export class TableOfContentsFieldSetComponent extends BaseTableOfContent { - - @Input() model: CompositeField; - @Input() index: number; - @Input() public path: string; - @Input() public page: number; - constructor(public router: Router, public route: ActivatedRoute, private visibilityRulesService: VisibilityRulesService) { - super(router, route); - } -} diff --git a/dmp-frontend/src/app/form/tableOfContents/table-of-content-group/table-of-content-group.component.ts b/dmp-frontend/src/app/form/tableOfContents/table-of-content-group/table-of-content-group.component.ts deleted file mode 100644 index 265156ff2..000000000 --- a/dmp-frontend/src/app/form/tableOfContents/table-of-content-group/table-of-content-group.component.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { VisibilityRulesService } from '../../../utilities/visibility-rules/visibility-rules.service'; -import { BaseTableOfContent } from '../base-table-of-content.component'; -import { FieldGroup } from '../../../models/FieldGroup'; -import { Section } from '../../../models/Section'; -import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; -import { Router, ActivatedRoute } from '@angular/router'; -//import * as $ from '../../../../node_modules/jquery/dist/jquery' - - -@Component({ - selector: 'app-table-of-contents-group', - templateUrl: './table-of-content-group.component.html', - providers: [] -}) -export class TableOfContentsGroupComponent extends BaseTableOfContent { - - @Input() model: FieldGroup; - @Input() index: number; - @Input() public path: string; - @Input() public page: number; - /* @Output() - setPage:EventEmitter = new EventEmitter(); - - */ - constructor(public router: Router, public route: ActivatedRoute, private visibilityRulesService: VisibilityRulesService) { - super(router, route); - } - - -} diff --git a/dmp-frontend/src/app/form/tableOfContents/table-of-content-section/table-of-content-section.component.ts b/dmp-frontend/src/app/form/tableOfContents/table-of-content-section/table-of-content-section.component.ts deleted file mode 100644 index 103dc8580..000000000 --- a/dmp-frontend/src/app/form/tableOfContents/table-of-content-section/table-of-content-section.component.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { VisibilityRulesService } from '../../../utilities/visibility-rules/visibility-rules.service'; -import { BaseTableOfContent } from '../base-table-of-content.component'; -import { Section } from '../../../models/Section'; -import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; -import { ActivatedRouteSnapshot, Router, ActivatedRoute } from '@angular/router'; - -//import * as $ from '../../../../node_modules/jquery/dist/jquery' - - -@Component({ - selector: 'app-table-of-contents-section', - templateUrl: './table-of-content-section.component.html', - providers: [] -}) -export class TableOfContentsSectionComponent extends BaseTableOfContent implements OnInit { - - @Input() model: Section; - @Input() index: number; - @Input() public path: string; - @Input() public page: number; - constructor(public router: Router, public route: ActivatedRoute, private visibilityRulesService: VisibilityRulesService) { - super(router, route); - } - ngOnInit() { - - } - -} diff --git a/dmp-frontend/src/app/form/tableOfContents/table-of-contents.component.ts b/dmp-frontend/src/app/form/tableOfContents/table-of-contents.component.ts deleted file mode 100644 index f35b2fc9a..000000000 --- a/dmp-frontend/src/app/form/tableOfContents/table-of-contents.component.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { DatasetProfileDefinitionModel } from '../../models/DatasetProfileDefinitionModel'; -import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; - -//import * as $ from '../../../../node_modules/jquery/dist/jquery' - -//import * as scroll from '../../../assets/jquery.scrollTo.min.js'; - -@Component({ - selector: 'app-table-of-content', - templateUrl: './table-of-contents.component.html', - styleUrls: ['./toc.component.css'], - providers: [] -}) -export class TableOfContentsComponent implements OnInit { - - @Input() - public model: DatasetProfileDefinitionModel; - public path = ''; - /* @Output() - setPage:EventEmitter = new EventEmitter(); - - */ - ngOnInit() { - - } - -} diff --git a/dmp-frontend/src/app/homepage/homepage.component.html b/dmp-frontend/src/app/homepage/homepage.component.html deleted file mode 100644 index 397a3ae5a..000000000 --- a/dmp-frontend/src/app/homepage/homepage.component.html +++ /dev/null @@ -1,85 +0,0 @@ -
-
-
-
-
-

{{ 'HOMEPAGE.OPEN-DMPS.STATS' | translate }}

-

{{ 'HOMEPAGE.MY-DMPS.STATS' | translate }}

-
-
-
-
-
-
-
- - - - - - {{'RECENT-ACTIVITY.MY-TITLE-DMP' | translate}} - - - - - -

- {{activity.label}} -

-

- {{activity.timestamp | date:'shortDate'}} -

-
-
-
-
-
-
- - - - - - {{'RECENT-ACTIVITY.MY-TITLE-PROJECT' | translate}} - - - - - -

- {{activity.label}} -

-

- {{activity.timestamp | date:'shortDate'}} -

-
-
-
-
-
-
- - - - - - {{'RECENT-ACTIVITY.MY-TITLE-DATASET' | translate}} - - - - - -

- {{activity.label}} -

-

- {{activity.timestamp | date:'shortDate'}} -

-
-
-
-
-
-
-
-
diff --git a/dmp-frontend/src/app/homepage/homepage.component.scss b/dmp-frontend/src/app/homepage/homepage.component.scss deleted file mode 100644 index 38c6a62df..000000000 --- a/dmp-frontend/src/app/homepage/homepage.component.scss +++ /dev/null @@ -1,59 +0,0 @@ - .card { - padding: 25px 20px 20px 20px; - display: flex; - flex-direction: column; - align-items: center; - } - - .card h6, - p { - color: #999; - } - - .icon { - margin-top: 20px; - width: 130px; - height: 130px; - border: 1px solid #e5e5e5; - border-radius: 50%; - display: flex; - justify-content: center; - align-items: center; - } - - .icon i { - font-size: 55px; - color: #e91e63; - } - - .card-title { - margin-top: 30px; - margin-bottom: 3px; - } - - .card-description { - margin-bottom: 20px; - } - - .card-dataset { - display: flex; - flex-direction: column; - padding: 20px; - position: relative; - margin-top: 40px; - } - - .card { - box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.14); - border-radius: 6px; - color: rgba(0, 0, 0, 0.87); - background: #fff; - } - - .card-raised { - box-shadow: 0 10px 30px -12px rgba(0, 0, 0, 0.42), 0 4px 25px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); - } - - .full-width { - width: 100%; - } diff --git a/dmp-frontend/src/app/homepage/homepage.component.ts b/dmp-frontend/src/app/homepage/homepage.component.ts deleted file mode 100644 index e500293b6..000000000 --- a/dmp-frontend/src/app/homepage/homepage.component.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { FormControl } from '@angular/forms'; -import { ActivatedRoute, Router } from '@angular/router'; -import { Observable } from 'rxjs/internal/Observable'; -import { takeUntil } from 'rxjs/operators'; -import { DashboardService } from '../../app/services/dashboard/dashboard.service'; -import { BaseComponent } from '../core/common/base/base.component'; -import { ProjectCriteria } from '../models/criteria/project/ProjectCriteria'; -import { RequestItem } from '../models/criteria/RequestItem'; -import { DashboardStatisticsModel } from '../models/dashboard/DashboardStatisticsModel'; -import { SearchBarItem } from '../models/dashboard/SearchBarItem'; -import { AuthService } from '../services/auth/auth.service'; -import { ProjectService } from '../services/project/project.service'; -import { UserReferenceService } from '../services/user-reference/user-reference-data.service'; -import { SingleAutoCompleteConfiguration } from '../shared/components/autocompletes/single/single-auto-complete-configuration'; -import { SearchBarType } from '../shared/components/search-bar/types/search-bar-type'; -import { RecentActivityTypes } from '../users/activity/RecentActivityTypes'; -import { JsonSerializer } from '../utilities/JsonSerializer'; - -@Component({ - selector: 'app-homepage', - templateUrl: './homepage.component.html', - styleUrls: ['./homepage.component.scss'], - providers: [ProjectService, UserReferenceService] -}) -export class HomepageComponent extends BaseComponent implements OnInit { - - public userInfo: any; - datasetActivities: any[]; - projectActivities: any[]; - dmpActivities: any[]; - public dashboardStatisticsData: DashboardStatisticsModel = new DashboardStatisticsModel(); - public formControl = new FormControl(); - projectAutoCompleteConfiguration: SingleAutoCompleteConfiguration; - public searchControl = new FormControl(); - filteredOptions: Observable; - RecentActivityTypes = RecentActivityTypes; - public search = false; - - constructor( - private route: ActivatedRoute, - private router: Router, - private projectService: ProjectService, - private dashBoardService: DashboardService, - private authentication: AuthService, - private userReferenceService: UserReferenceService - - ) { - super(); - this.dashboardStatisticsData.totalDataManagementPlanCount = 0; - this.dashboardStatisticsData.totalDataSetCount = 0; - this.dashboardStatisticsData.totalProjectCount = 0; - } - - - ngOnInit() { - - if (this.isAuthenticated()) { - this.userReferenceService.getRecentActivity() - .pipe(takeUntil(this._destroyed)) - .subscribe(response => { - this.datasetActivities = response['recentDatasetActivities']; - this.dmpActivities = response['recentDmpActivities']; - this.projectActivities = response['recentProjectActivities']; - }); - } - - this.projectAutoCompleteConfiguration = { - filterFn: this.searchProject.bind(this), - items: this.searchProject(''), - displayFn: (item) => item['label'], - titleFn: (item) => item['label'], - //mapFn: (item) => new JsonSerializer().fromJSONArray(item, ProjectReference).map(item => item.toDropdownList()), - loadDataOnStart: true - }; - - if (!this.isAuthenticated()) { - this.dashBoardService.getStatistics() - .pipe(takeUntil(this._destroyed)) - .subscribe(results => { - //let data = results['payload']; - this.dashboardStatisticsData = JsonSerializer.fromJSONObject(results, DashboardStatisticsModel); - }); - } else { - this.dashBoardService.getStatisticsSpecificuser() - .pipe(takeUntil(this._destroyed)) - .subscribe(results => { - this.dashboardStatisticsData = JsonSerializer.fromJSONObject(results, DashboardStatisticsModel); - }); - } - - this.filteredOptions = this.searchControl.valueChanges.flatMap(x => { - return this.dashBoardService.searchUserItems(x); - }); - } - - public isAuthenticated(): boolean { - return !(!this.authentication.current()); - } - - searchProject(query: string) { - const projectRequestItem: RequestItem = new RequestItem(); - projectRequestItem.criteria = new ProjectCriteria(); - projectRequestItem.criteria.like = query; - return this.projectService.getWithExternal(projectRequestItem); - } - - redirect(id: string, type: RecentActivityTypes) { - switch (type) { - case RecentActivityTypes.PROJECT: { - this.router.navigate(['projects/edit/' + id]); - return; - } - case RecentActivityTypes.DATASET: { - this.router.navigate(['datasets/edit/' + id]); - return; - } - case RecentActivityTypes.DMP: { - this.router.navigate(['dmps/edit/' + id]); - return; - } - default: throw new Error('Unsupported Activity Type '); - } - - } - - onOptionSelected(event: any) { - const selectedSearchBarItem = event.option.value; - if (selectedSearchBarItem.type === SearchBarType.DATASET) { this.router.navigate(['datasets/edit/' + selectedSearchBarItem.id]); } - if (selectedSearchBarItem.type === SearchBarType.PROJECT) { this.router.navigate(['projects/edit/' + selectedSearchBarItem.id]); } - if (selectedSearchBarItem.type === SearchBarType.DATAMANAGEMENTPLAN) { this.router.navigate(['dmps/edit/' + selectedSearchBarItem.id]); } - } -} diff --git a/dmp-frontend/src/app/library/auto-complete/auto-complete-custom-validator.ts b/dmp-frontend/src/app/library/auto-complete/auto-complete-custom-validator.ts new file mode 100644 index 000000000..1d69ddf1e --- /dev/null +++ b/dmp-frontend/src/app/library/auto-complete/auto-complete-custom-validator.ts @@ -0,0 +1,13 @@ +import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'; + +export function ValidJsonValidator(): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + try { + if (typeof control.value !== 'object') { JSON.parse(control.value); } + } catch (e) { + return { 'invalidJson': { value: true } }; + } + return null; + }; +} + diff --git a/dmp-frontend/src/app/library/auto-complete/auto-complete-group.ts b/dmp-frontend/src/app/library/auto-complete/auto-complete-group.ts new file mode 100644 index 000000000..385e13947 --- /dev/null +++ b/dmp-frontend/src/app/library/auto-complete/auto-complete-group.ts @@ -0,0 +1,4 @@ +export class AutoCompleteGroup { + public title: string; + public items: any[]; +} diff --git a/dmp-frontend/src/app/library/auto-complete/auto-complete.module.ts b/dmp-frontend/src/app/library/auto-complete/auto-complete.module.ts new file mode 100644 index 000000000..00a7b0ff2 --- /dev/null +++ b/dmp-frontend/src/app/library/auto-complete/auto-complete.module.ts @@ -0,0 +1,24 @@ +import { NgModule } from '@angular/core'; +import { CommonFormsModule } from '../../common/forms/common-forms.module'; +import { CommonUiModule } from '../../common/ui/common-ui.module'; +import { MultipleAutoCompleteComponent } from './multiple/multiple-auto-complete.component'; +import { SingleAutoCompleteComponent } from './single/single-auto-complete.component'; + + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule + ], + declarations: [ + SingleAutoCompleteComponent, + MultipleAutoCompleteComponent + ], + exports: [ + SingleAutoCompleteComponent, + MultipleAutoCompleteComponent + ] +}) +export class AutoCompleteModule { + constructor() { } +} diff --git a/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete-configuration.ts b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete-configuration.ts new file mode 100644 index 000000000..5eedff7a5 --- /dev/null +++ b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete-configuration.ts @@ -0,0 +1,23 @@ +import { Observable } from 'rxjs'; +import { AutoCompleteGroup } from '../auto-complete-group'; + +export interface MultipleAutoCompleteConfiguration { + // Delay for performing the request. Default: 200ms. + requestDelay?: number; + // Min characters for the filtering to be applied. Default: 1. + minFilteringChars?: number; + // Load and present items from start, without user query. Default: true. + loadDataOnStart?: boolean; + // Static or initial items. + initialItems?: (excludedItems: any[]) => Observable; + // Data retrieval function + filterFn?: (searchQuery: string, excludedItems: any[]) => Observable; + // Property formating for input + displayFn?: (item: any) => string; + // Function to group results in the drop down + groupingFn?: (items: any[]) => AutoCompleteGroup[]; + // Display function for the drop down title + titleFn?: (item: any) => string; + // Display function for the drop down subtitle + subtitleFn?: (item: any) => string; +} diff --git a/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.html b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.html new file mode 100644 index 000000000..ccaa21360 --- /dev/null +++ b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.html @@ -0,0 +1,28 @@ +
+ + + {{this._displayFn(selectedItem)}} + cancel + + + + + + + + + {{_titleFn(item)}} +
+ {{_subtitleFn(item)}} +
+
+
+ + + {{_titleFn(item)}} +
+ {{_subtitleFn(item)}} +
+
+
+
diff --git a/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.scss b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.scss new file mode 100644 index 000000000..59bdf7561 --- /dev/null +++ b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.scss @@ -0,0 +1,22 @@ +.multiple-auto-complete { + margin-left: inherit; + margin-right: inherit; + + .multi-chip-list { + padding-left: 0; + } + + .multi-loading-bar { + padding-right: 0; + padding-left: 0; + } + + .not-loading { + display: none; + } +} + +.two-line-mat-option { + height: 3.5em; + line-height: 1.2em; +} diff --git a/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.ts b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.ts new file mode 100644 index 000000000..7996fc178 --- /dev/null +++ b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.ts @@ -0,0 +1,273 @@ +import { FocusMonitor } from '@angular/cdk/a11y'; +import { COMMA, ENTER } from '@angular/cdk/keycodes'; +import { Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Optional, Output, Self, ViewChild } from '@angular/core'; +import { ControlValueAccessor, NgControl } from '@angular/forms'; +import { MatAutocompleteSelectedEvent, MatAutocompleteTrigger, MatChipInputEvent, MatFormFieldControl } from '@angular/material'; +import { Observable, of as observableOf, Subject } from 'rxjs'; +import { debounceTime, distinctUntilChanged, map, mergeMap, startWith, tap } from 'rxjs/operators'; +import { AutoCompleteGroup } from '../auto-complete-group'; +import { MultipleAutoCompleteConfiguration } from './multiple-auto-complete-configuration'; + +@Component({ + selector: 'app-multiple-auto-complete', + templateUrl: './multiple-auto-complete.component.html', + styleUrls: ['./multiple-auto-complete.component.scss'], + providers: [{ provide: MatFormFieldControl, useExisting: MultipleAutoCompleteComponent }] +}) +export class MultipleAutoCompleteComponent implements OnInit, MatFormFieldControl, ControlValueAccessor, OnDestroy { + + static nextId = 0; + + separatorKeysCodes = [ENTER, COMMA]; + + @Input() configuration: MultipleAutoCompleteConfiguration; + // Selected Option Event + @Output() optionSelected: EventEmitter = new EventEmitter(); + // Removed Option Event + @Output() optionRemoved: EventEmitter = new EventEmitter(); + + id = `multiple-autocomplete-${MultipleAutoCompleteComponent.nextId++}`; + stateChanges = new Subject(); + focused = false; + errorState = false; + controlType = 'multiple-autocomplete'; + describedBy = ''; + _inputValue: string; + _inputSubject = new Subject(); + loading = false; + _items: Observable; + _groupedItems: Observable; + private requestDelay = 200; //ms + private minFilteringChars = 1; + private loadDataOnStart = true; + visible = true; + selectable = true; + removable = true; + addOnBlur = false; + + get empty() { + return !this._inputValue || this._inputValue.length === 0; + } + + get shouldLabelFloat() { return this.focused || !this.empty; } + + @Input() + get placeholder() { return this._placeholder; } + set placeholder(placeholder) { + this._placeholder = placeholder; + this.stateChanges.next(); + } + private _placeholder: string; + + @Input() + get required() { return this._required; } + set required(req) { + this._required = !!(req); + this.stateChanges.next(); + } + private _required = false; + + @Input() + get disabled() { return this._disabled; } + set disabled(dis) { + this._disabled = !!(dis); + this.stateChanges.next(); + } + private _disabled = false; + + @Input() + get value(): any | null { + return this._selectedValue; + } + set value(value: any | null) { + this._selectedValue = value; + this._inputValue = value; + this.stateChanges.next(); + } + private _selectedValue; + + + + + + @ViewChild('textInput') textInput: ElementRef; + @ViewChild(MatAutocompleteTrigger) autocomplete: MatAutocompleteTrigger; + + + + + constructor( + private fm: FocusMonitor, + private elRef: ElementRef, + @Optional() @Self() public ngControl: NgControl) { + + fm.monitor(elRef.nativeElement, true).subscribe((origin) => { + this.focused = !!origin; + this.stateChanges.next(); + }); + + if (this.ngControl != null) { + // Setting the value accessor directly (instead of using + // the providers) to avoid running into a circular import. + this.ngControl.valueAccessor = this; + } + } + + ngOnInit() { + + } + + filter(query: string): Observable { + // If loadDataOnStart is enabled and query is empty we return the initial items. + if (this.isNullOrEmpty(query) && this.loadDataOnStart) { + return this.configuration.initialItems(this.value || []) || observableOf([]); + } else if (query && query.length >= this.minFilteringChars) { + if (this.configuration.filterFn) { + return this.configuration.filterFn(query, this.value || []); + } else { + return this.configuration.initialItems(this.value || []) || observableOf([]); + } + } else { + return observableOf([]); + } + } + + isNullOrEmpty(query: string): boolean { + return typeof query !== 'string' || query === null || query.length === 0; + } + + _displayFn(item: any): string { + if (this.configuration.displayFn && item) { return this.configuration.displayFn(item); } + return item; + } + + _titleFn(item: any): string { + if (this.configuration.titleFn && item) { return this.configuration.titleFn(item); } + return item; + } + + _subtitleFn(item: any): string { + if (this.configuration.subtitleFn && item) { return this.configuration.subtitleFn(item); } + return null; + } + + _requestDelay(): number { + return this.configuration.requestDelay || this.requestDelay; + } + + _minFilteringChars(): number { + return this.configuration.minFilteringChars || this.minFilteringChars; + } + + _loadDataOnStart(): boolean { + return this.configuration.loadDataOnStart || this.loadDataOnStart; + } + + _chipItems(): any[] { + return this.value || []; + } + + _optionSelected(event: MatAutocompleteSelectedEvent) { + const newValue = this.value || []; + newValue.push(event.option.value); + this._setValue(newValue); + this.stateChanges.next(); + this.optionSelected.emit(newValue); + } + + private _setValue(value: any) { + this.value = value; + this.pushChanges(this.value); + } + + _onInputFocus() { + // We set the items observable on focus to avoid the request being executed on component load. + if (!this._items) { + this._items = this._inputSubject.pipe( + startWith(null), + debounceTime(this.requestDelay), + distinctUntilChanged(), + tap(() => { this.loading = true; }), + mergeMap(query => { + // If its a valid object, a selection just made and the object is set as the value of the form control. That means we should fire an extra request to the server. + if (this._isValidObject(query)) { return observableOf([]); } + + // Since the object is changed we need to clear any existing selections, except for the first time. + if (query !== null) { this.pushChanges(null); } + return this.filter(query); + }), + tap(() => { this.loading = false; })); + + if (this.configuration.groupingFn) { this._groupedItems = this._items.pipe(map(items => this.configuration.groupingFn(items))); } + } + } + + _inputValueChange(value: string) { + this._inputValue = value; + this._inputSubject.next(value); + this.stateChanges.next(); + } + + _isValidObject(value: any): boolean { + try { + if (!value) { return false; } + if (typeof value !== 'object') { JSON.parse(value); } + } catch (e) { + return false; + } + return true; + } + + _removeSelectedItem(item: any): void { + const index = this.value.indexOf(item); + if (index >= 0) { + this.value.splice(index, 1); + this.optionRemoved.emit(item); + } + this.textInput.nativeElement.focus(); + this.pushChanges(this.value); + } + + _onInputClick(item: any) { + if (!this.autocomplete.panelOpen) { + this.autocomplete.openPanel(); + } + } + + _addItem(event: MatChipInputEvent): void { + // const input = event.input; + // const value = event.value; + // // Add our fruit + // if ((value || '').trim()) { + // this.selectedItems.push(value.trim()); + // } + // // Reset the input value + // if (input) { + // input.value = ''; + // } + // this.inputFormControl.setValue(null); + } + + onChange = (_: any) => { }; + onTouched = () => { }; + writeValue(value: any): void { this.value = value || ''; } + pushChanges(value: any) { this.onChange(value); } + registerOnChange(fn: (_: any) => {}): void { this.onChange = fn; } + registerOnTouched(fn: () => {}): void { this.onTouched = fn; } + setDisabledState(isDisabled: boolean): void { } + + setDescribedByIds(ids: string[]) { + this.describedBy = ids.join(' '); + } + + onContainerClick(event: MouseEvent) { + if ((event.target as Element).tagName.toLowerCase() !== 'input') { + this.elRef.nativeElement.querySelector('input').focus(); + } + } + + ngOnDestroy() { + this.stateChanges.complete(); + this.fm.stopMonitoring(this.elRef.nativeElement); + } +} diff --git a/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete-configuration.ts b/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete-configuration.ts new file mode 100644 index 000000000..b59a366fe --- /dev/null +++ b/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete-configuration.ts @@ -0,0 +1,25 @@ +import { Observable } from 'rxjs'; +import { AutoCompleteGroup } from '../auto-complete-group'; + +export interface SingleAutoCompleteConfiguration { + // Delay for performing the request. Default: 200ms. + requestDelay?: number; + // Min characters for the filtering to be applied. Default: 1. + minFilteringChars?: number; + // Load and present items from start, without user query. Default: true. + loadDataOnStart?: boolean; + // Static or initial items. + initialItems?: (data?:any) => Observable; + // Data retrieval function + filterFn?: (searchQuery: string, data?:any) => Observable; + // Property formating for input + displayFn?: (item: any) => string; + // Property formating for dropdown + groupingFn?: (items: any[]) => AutoCompleteGroup[]; + // Property formating for dropdown + titleFn?: (item: any) => string; + // Property formating for dropdown + subtitleFn?: (item: any) => string; + //Extra data passed to query function + extraData?: any; +} diff --git a/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.html b/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.html new file mode 100644 index 000000000..894fb3a9a --- /dev/null +++ b/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.html @@ -0,0 +1,24 @@ +
+ + + + + + + + {{_titleFn(item)}} +
+ {{_subtitleFn(item)}} +
+
+
+ + + + {{_titleFn(item)}} +
+ {{_subtitleFn(item)}} +
+
+
+
diff --git a/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.scss b/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.scss new file mode 100644 index 000000000..2366b5a74 --- /dev/null +++ b/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.scss @@ -0,0 +1,13 @@ +.auto-complete { + margin-left: inherit; + margin-right: inherit; + + .not-loading { + display: none; + } +} + +.two-line-mat-option { + height: 3.5em; + line-height: 1.2em; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.ts b/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.ts new file mode 100644 index 000000000..e54d4c532 --- /dev/null +++ b/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.ts @@ -0,0 +1,219 @@ +import { FocusMonitor } from '@angular/cdk/a11y'; +import { Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Optional, Output, Self } from '@angular/core'; +import { ControlValueAccessor, NgControl } from '@angular/forms'; +import { MatAutocompleteSelectedEvent, MatFormFieldControl } from '@angular/material'; +import { Observable, of as observableOf, Subject } from 'rxjs'; +import { debounceTime, distinctUntilChanged, map, mergeMap, startWith, tap } from 'rxjs/operators'; +import { AutoCompleteGroup } from '../auto-complete-group'; +import { SingleAutoCompleteConfiguration } from './single-auto-complete-configuration'; + + +@Component({ + selector: 'app-single-auto-complete', + templateUrl: './single-auto-complete.component.html', + styleUrls: ['./single-auto-complete.component.scss'], + providers: [{ provide: MatFormFieldControl, useExisting: SingleAutoCompleteComponent }], +}) +export class SingleAutoCompleteComponent implements OnInit, MatFormFieldControl, ControlValueAccessor, OnDestroy { + + static nextId = 0; + + @Input() configuration: SingleAutoCompleteConfiguration; + // Selected Option Event + @Output() optionSelected: EventEmitter = new EventEmitter(); + + id = `single-autocomplete-${SingleAutoCompleteComponent.nextId++}`; + stateChanges = new Subject(); + focused = false; + errorState = false; + controlType = 'single-autocomplete'; + describedBy = ''; + _inputValue: string; + _inputSubject = new Subject(); + loading = false; + _items: Observable; + _groupedItems: Observable; + private requestDelay = 200; //ms + private minFilteringChars = 1; + private loadDataOnStart = true; + + get empty() { + return !this._inputValue || this._inputValue.length === 0; + } + + get shouldLabelFloat() { return this.focused || !this.empty; } + + @Input() + get placeholder() { return this._placeholder; } + set placeholder(placeholder) { + this._placeholder = placeholder; + this.stateChanges.next(); + } + private _placeholder: string; + + @Input() + get required() { return this._required; } + set required(req) { + this._required = !!(req); + this.stateChanges.next(); + } + private _required = false; + + @Input() + get disabled() { return this._disabled; } + set disabled(dis) { + this._disabled = !!(dis); + this.stateChanges.next(); + } + private _disabled = false; + + @Input() + get value(): any | null { + return this._selectedValue; + } + set value(value: any | null) { + this._selectedValue = value; + this._inputValue = value; + this.stateChanges.next(); + } + private _selectedValue; + + constructor( + private fm: FocusMonitor, + private elRef: ElementRef, + @Optional() @Self() public ngControl: NgControl) { + + fm.monitor(elRef.nativeElement, true).subscribe((origin) => { + this.focused = !!origin; + this.stateChanges.next(); + }); + + if (this.ngControl != null) { + // Setting the value accessor directly (instead of using + // the providers) to avoid running into a circular import. + this.ngControl.valueAccessor = this; + } + } + + ngOnInit() { + + } + + filter(query: string): Observable { + // If loadDataOnStart is enabled and query is empty we return the initial items. + if (this.isNullOrEmpty(query) && this.loadDataOnStart) { + return this.configuration.initialItems(this.configuration.extraData) || observableOf([]); + } else if (query && query.length >= this.minFilteringChars) { + if (this.configuration.filterFn) { + return this.configuration.filterFn(query, this.configuration.extraData); + } else { + return this.configuration.initialItems(this.configuration.extraData) || observableOf([]); + } + } else { + return observableOf([]); + } + } + + isNullOrEmpty(query: string): boolean { + return typeof query !== 'string' || query === null || query.length === 0; + } + + _displayFn(item: any): string { + if (this.configuration.displayFn && item) { return this.configuration.displayFn(item); } + return item; + } + + _titleFn(item: any): string { + if (this.configuration.titleFn && item) { return this.configuration.titleFn(item); } + return item; + } + + _subtitleFn(item: any): string { + if (this.configuration.subtitleFn && item) { return this.configuration.subtitleFn(item); } + return null; + } + + _requestDelay(): number { + return this.configuration.requestDelay || this.requestDelay; + } + + _minFilteringChars(): number { + return this.configuration.minFilteringChars || this.minFilteringChars; + } + + _loadDataOnStart(): boolean { + return this.configuration.loadDataOnStart || this.loadDataOnStart; + } + + _optionSelected(event: MatAutocompleteSelectedEvent) { + this._setValue(event.option.value); + this.stateChanges.next(); + this.optionSelected.emit(event.option.value); + } + + private _setValue(value: any) { + this.value = value; + this.pushChanges(this.value); + } + + _onInputFocus() { + // We set the items observable on focus to avoid the request being executed on component load. + if (!this._items) { + this._items = this._inputSubject.pipe( + startWith(null), + debounceTime(this.requestDelay), + distinctUntilChanged(), + tap(() => { this.loading = true; }), + mergeMap(query => { + // If its a valid object, a selection just made and the object is set as the value of the form control. That means we should fire an extra request to the server. + if (this._isValidObject(query)) { return observableOf([]); } + + // Since the object is changed we need to clear any existing selections, except for the first time. + if (query !== null) { this.pushChanges(null); } + return this.filter(query); + }), + tap(() => { this.loading = false; })); + + if (this.configuration.groupingFn) { this._groupedItems = this._items.pipe(map(items => this.configuration.groupingFn(items))); } + } + } + + _inputValueChange(value: string) { + this._inputValue = value; + this._inputSubject.next(value); + this.stateChanges.next(); + } + + _isValidObject(value: any): boolean { + try { + if (!value) { return false; } + if (typeof value !== 'object') { JSON.parse(value); } + } catch (e) { + return false; + } + return true; + } + + onChange = (_: any) => { }; + onTouched = () => { }; + writeValue(value: any): void { this.value = value || ''; } + pushChanges(value: any) { this.onChange(value); } + registerOnChange(fn: (_: any) => {}): void { this.onChange = fn; } + registerOnTouched(fn: () => {}): void { this.onTouched = fn; } + setDisabledState(isDisabled: boolean): void { this.disabled = isDisabled; } + + setDescribedByIds(ids: string[]) { + this.describedBy = ids.join(' '); + } + + onContainerClick(event: MouseEvent) { + if ((event.target as Element).tagName.toLowerCase() !== 'input') { + this.elRef.nativeElement.querySelector('input').focus(); + } + } + + ngOnDestroy() { + this.stateChanges.complete(); + this.fm.stopMonitoring(this.elRef.nativeElement); + } +} diff --git a/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.html b/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.html new file mode 100644 index 000000000..d5c8cbb2a --- /dev/null +++ b/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.html @@ -0,0 +1,10 @@ +
+
+ {{ data.message }} +
+
+
+
+
+
+
diff --git a/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.scss b/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.scss new file mode 100644 index 000000000..bc873f932 --- /dev/null +++ b/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.scss @@ -0,0 +1,5 @@ +.confirmation-dialog { + .confirmation-message { + padding-bottom: 20px; + } +} diff --git a/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.ts b/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.ts new file mode 100644 index 000000000..e6a62a9c5 --- /dev/null +++ b/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.ts @@ -0,0 +1,24 @@ +import { Component, Inject } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; + +@Component({ + selector: 'app-confirmation-dialog', + templateUrl: './confirmation-dialog.component.html', + styleUrls: ['./confirmation-dialog.component.scss'] +}) +export class ConfirmationDialogComponent { + + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any + ) { + } + + cancel() { + this.dialogRef.close(false); + } + + confirm() { + this.dialogRef.close(true); + } +} diff --git a/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.module.ts b/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.module.ts new file mode 100644 index 000000000..cda63242d --- /dev/null +++ b/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { CommonUiModule } from '../../common/ui/common-ui.module'; +import { ConfirmationDialogComponent } from './confirmation-dialog.component'; + +@NgModule({ + imports: [CommonUiModule], + declarations: [ConfirmationDialogComponent], + exports: [ConfirmationDialogComponent], + entryComponents: [ConfirmationDialogComponent] +}) +export class ConfirmationDialogModule { + constructor() { } +} diff --git a/dmp-frontend/src/app/library/notification/notification.component.html b/dmp-frontend/src/app/library/notification/notification.component.html new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/dmp-frontend/src/app/library/notification/notification.component.html @@ -0,0 +1 @@ + diff --git a/dmp-frontend/src/app/library/notification/notification.component.scss b/dmp-frontend/src/app/library/notification/notification.component.scss new file mode 100644 index 000000000..1203c5d5a --- /dev/null +++ b/dmp-frontend/src/app/library/notification/notification.component.scss @@ -0,0 +1,15 @@ +.snack-bar-notification--success { + background-color: #4CAF50 !important; +} + +.snack-bar-notification--error { + background-color: #B13636 !important; +} + +.snack-bar-notification--warning { + background-color: #B13636 !important; +} + +.snack-bar-notification--info { + background-color: #B13636 !important; +} diff --git a/dmp-frontend/src/app/library/notification/notification.component.ts b/dmp-frontend/src/app/library/notification/notification.component.ts new file mode 100644 index 000000000..a42d08a62 --- /dev/null +++ b/dmp-frontend/src/app/library/notification/notification.component.ts @@ -0,0 +1,54 @@ +import { Component, OnInit } from '@angular/core'; +import { MatDialog, MatSnackBar } from '@angular/material'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../core/common/base/base.component'; +import { UiNotificationService, UiNotificationType, PopupNotification, SnackBarNotification, SnackBarNotificationLevel } from '../../core/services/notification/ui-notification-service'; +import { PopupNotificationDialogComponent } from './popup/popup-notification.component'; +import { SnackBarNotificationComponent } from './snack-bar/snack-bar-notification.component'; + +@Component({ + selector: 'app-notification', + templateUrl: './notification.component.html', + styleUrls: ['./notification.component.scss'] +}) +export class NotificationComponent extends BaseComponent implements OnInit { + + constructor( + private snackBar: MatSnackBar, + private dialog: MatDialog, + private uiNotificationService: UiNotificationService + ) { + super(); + } + + ngOnInit() { + this.uiNotificationService.getNotificationObservable().pipe(takeUntil(this._destroyed)).subscribe(notification => { + switch (notification.type) { + case UiNotificationType.SnackBar: + const snackBarNotification: SnackBarNotification = notification as SnackBarNotification; + this.snackBar.openFromComponent(SnackBarNotificationComponent, { + data: snackBarNotification, + duration: snackBarNotification.duration, + panelClass: [this.getSnackBarLevelClass(snackBarNotification.level)] + }); + break; + case UiNotificationType.Popup: + const popupNotification: PopupNotification = notification as PopupNotification; + this.dialog.open(PopupNotificationDialogComponent, { + data: popupNotification + }); + break; + } + }); + } + + private getSnackBarLevelClass(level: SnackBarNotificationLevel): string { + switch (level) { + case SnackBarNotificationLevel.Warning: return 'snack-bar-notification--warning'; + case SnackBarNotificationLevel.Error: return 'snack-bar-notification--error'; + case SnackBarNotificationLevel.Success: return 'snack-bar-notification--success'; + default: return 'snack-bar-notification--info'; + } + + } +} diff --git a/dmp-frontend/src/app/library/notification/notification.module.ts b/dmp-frontend/src/app/library/notification/notification.module.ts new file mode 100644 index 000000000..7d7a194d5 --- /dev/null +++ b/dmp-frontend/src/app/library/notification/notification.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from '@angular/core'; +import { CommonUiModule } from '../../common/ui/common-ui.module'; +import { NotificationComponent } from './notification.component'; +import { PopupNotificationDialogComponent } from './popup/popup-notification.component'; +import { SnackBarNotificationComponent } from './snack-bar/snack-bar-notification.component'; + +@NgModule({ + imports: [ + CommonUiModule + ], + declarations: [ + NotificationComponent, + SnackBarNotificationComponent, + PopupNotificationDialogComponent, + ], + exports: [ + NotificationComponent + ], + entryComponents: [ + SnackBarNotificationComponent, + PopupNotificationDialogComponent, + ] +}) +export class NotificationModule { + constructor() { } +} diff --git a/dmp-frontend/src/app/library/notification/popup/popup-notification.component.html b/dmp-frontend/src/app/library/notification/popup/popup-notification.component.html new file mode 100644 index 000000000..47795943f --- /dev/null +++ b/dmp-frontend/src/app/library/notification/popup/popup-notification.component.html @@ -0,0 +1,5 @@ +

{{notification.title}}

+{{notification.message}} + + + diff --git a/dmp-frontend/src/app/library/notification/popup/popup-notification.component.ts b/dmp-frontend/src/app/library/notification/popup/popup-notification.component.ts new file mode 100644 index 000000000..84a11666a --- /dev/null +++ b/dmp-frontend/src/app/library/notification/popup/popup-notification.component.ts @@ -0,0 +1,16 @@ +import { Component, Inject } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { PopupNotification } from '../../../core/services/notification/ui-notification-service'; + +@Component({ + selector: 'app-popup-notification-dialog', + templateUrl: './popup-notification.component.html' +}) +export class PopupNotificationDialogComponent { + + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public notification: PopupNotification + ) { + } +} diff --git a/dmp-frontend/src/app/shared/components/notificaiton/snack-bar-notification.component.html b/dmp-frontend/src/app/library/notification/snack-bar/snack-bar-notification.component.html similarity index 100% rename from dmp-frontend/src/app/shared/components/notificaiton/snack-bar-notification.component.html rename to dmp-frontend/src/app/library/notification/snack-bar/snack-bar-notification.component.html diff --git a/dmp-frontend/src/app/library/notification/snack-bar/snack-bar-notification.component.ts b/dmp-frontend/src/app/library/notification/snack-bar/snack-bar-notification.component.ts new file mode 100644 index 000000000..2af227f3c --- /dev/null +++ b/dmp-frontend/src/app/library/notification/snack-bar/snack-bar-notification.component.ts @@ -0,0 +1,15 @@ +import { Component, Inject } from '@angular/core'; +import { MAT_SNACK_BAR_DATA } from '@angular/material'; +import { SnackBarNotification } from '../../../core/services/notification/ui-notification-service'; + +@Component({ + selector: 'app-snack-bar-notification', + templateUrl: './snack-bar-notification.component.html' +}) + +export class SnackBarNotificationComponent { + message: string; + constructor(@Inject(MAT_SNACK_BAR_DATA) public data: SnackBarNotification) { + this.message = data.message; + } +} diff --git a/dmp-frontend/src/app/library/url-listing/url-listing-item.ts b/dmp-frontend/src/app/library/url-listing/url-listing-item.ts new file mode 100644 index 000000000..6fd4c5639 --- /dev/null +++ b/dmp-frontend/src/app/library/url-listing/url-listing-item.ts @@ -0,0 +1,6 @@ + +export class UrlListingItem { + public label: string; + public url: string; + public all: string; +} diff --git a/dmp-frontend/src/app/shared/components/url-listing/url-listing.component.html b/dmp-frontend/src/app/library/url-listing/url-listing.component.html similarity index 100% rename from dmp-frontend/src/app/shared/components/url-listing/url-listing.component.html rename to dmp-frontend/src/app/library/url-listing/url-listing.component.html diff --git a/dmp-frontend/src/app/library/url-listing/url-listing.component.ts b/dmp-frontend/src/app/library/url-listing/url-listing.component.ts new file mode 100644 index 000000000..62a524c5b --- /dev/null +++ b/dmp-frontend/src/app/library/url-listing/url-listing.component.ts @@ -0,0 +1,26 @@ +import { Component, Input } from "@angular/core"; +import { Router } from "@angular/router"; +import { UrlListingItem } from "./url-listing-item"; + +@Component({ + selector: 'app-url-listing', + templateUrl: './url-listing.component.html' +}) +export class UrlListingComponent { + + @Input() items: UrlListingItem[]; + @Input() parameters: any + @Input() urlLimit: number = 3; + + constructor( + private router: Router + ) { } + + ngOnInit() { + + } + + navigate(link: string) { + this.router.navigate([link], { queryParams: this.parameters }); + } +} diff --git a/dmp-frontend/src/app/library/url-listing/url-listing.module.ts b/dmp-frontend/src/app/library/url-listing/url-listing.module.ts new file mode 100644 index 000000000..c0112e256 --- /dev/null +++ b/dmp-frontend/src/app/library/url-listing/url-listing.module.ts @@ -0,0 +1,20 @@ +import { NgModule } from '@angular/core'; +import { CommonUiModule } from '../../common/ui/common-ui.module'; +import { FormattingModule } from '../../core/formatting.module'; +import { UrlListingComponent } from './url-listing.component'; + +@NgModule({ + imports: [ + CommonUiModule, + FormattingModule + ], + declarations: [ + UrlListingComponent + ], + exports: [ + UrlListingComponent + ] +}) +export class UrlListingModule { + constructor() { } +} diff --git a/dmp-frontend/src/app/models/BaseModel.ts b/dmp-frontend/src/app/models/BaseModel.ts deleted file mode 100644 index 50f9540fd..000000000 --- a/dmp-frontend/src/app/models/BaseModel.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { FormBuilder } from '@angular/forms'; -export abstract class BaseModel { - public formBuilder: FormBuilder = new FormBuilder(); -} diff --git a/dmp-frontend/src/app/models/CompositeField.ts b/dmp-frontend/src/app/models/CompositeField.ts deleted file mode 100644 index b255b4255..000000000 --- a/dmp-frontend/src/app/models/CompositeField.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { FormGroup } from '@angular/forms'; -import { JsonSerializer } from '../utilities/JsonSerializer'; -import { Serializable } from './interfaces/Serializable'; -import { BaseModel } from './BaseModel'; -import { Field } from './Field'; -import { Multiplicity } from './Multiplicity'; -export class CompositeField extends BaseModel implements Serializable { - public fields: Array = new Array(); - public ordinal: number; - public id: string; - public numbering: string; - public multiplicity: Multiplicity; - public multiplicityItems: Array = new Array(); - public title: string; - public description: string; - public extendedDescription: string; - public hasCommentField: boolean; - public commentFieldValue: string; - - fromJSONObject(item: any): CompositeField { - - this.fields = JsonSerializer.fromJSONArray(item.fields, Field); - this.ordinal = item.ordinal; - this.id = item.id; - this.title = item.title; - this.numbering = item.numbering; - this.description = item.description; - this.extendedDescription = item.extendedDescription; - this.hasCommentField = item.hasCommentField; - this.commentFieldValue = item.commentFieldValue; - this.multiplicity = JsonSerializer.fromJSONObject(item.multiplicity, Multiplicity); - //this.multiplicity = new Multiplicity(); - //this.multiplicity.max = 2; - if (item.multiplicityItems) {this.multiplicityItems = JsonSerializer.fromJSONArray(item.multiplicityItems, CompositeField); } - return this; - } - - buildForm(): FormGroup { - const formGroup = this.formBuilder.group({ - id: this.id, - ordinal: this.ordinal, - title: this.title, - description: this.description, - extendedDescription: this.extendedDescription, - hasCommentField: this.hasCommentField, - commentFieldValue: this.commentFieldValue - }); - - const fieldsFormArray = new Array(); - this.fields.forEach(item => { - const form: FormGroup = item.buildForm(); - fieldsFormArray.push(form); - }); - formGroup.addControl('fields', this.formBuilder.array(fieldsFormArray)); - - const multiplicityItemsFormArray = new Array(); - this.multiplicityItems.forEach(item => { - const form: FormGroup = item.buildForm(); - multiplicityItemsFormArray.push(form); - }); - formGroup.addControl('multiplicityItems', this.formBuilder.array(multiplicityItemsFormArray)); - - return formGroup; - } - - cloneForMultiplicity(index: number): CompositeField { - const newItem: CompositeField = new CompositeField(); - newItem.id = 'multiple_' + this.id + '_' + index; - this.fields.forEach(field => { - newItem.fields.push(field.cloneForMultiplicity(this.fields.indexOf(field), newItem.id + '_')); - }); - newItem.ordinal = this.ordinal; - - return newItem; - } -} diff --git a/dmp-frontend/src/app/models/DataField/AutocompleteData.ts b/dmp-frontend/src/app/models/DataField/AutocompleteData.ts deleted file mode 100644 index e59ee0cde..000000000 --- a/dmp-frontend/src/app/models/DataField/AutocompleteData.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { DataField } from './DataField'; -import { FormGroup } from '@angular/forms'; -import { ListingItem } from '../common/ListingItem'; -import { JsonSerializer } from '../../utilities/JsonSerializer'; - -export class AutocompleteData extends DataField { - - public type: string; - public url: string; - public optionsRoot: string; - public autoCompleteOptions: ListingItem = new ListingItem(); - - buildForm(): FormGroup { - const formGroup = this.formBuilder.group({ - label: [this.label], - type: [this.type], - url: [this.url], - optionsRoot: [this.optionsRoot] - }); - formGroup.addControl('autoCompleteOptions', this.autoCompleteOptions.buildForm()); - return formGroup; - } - - fromJSONObject(item: any): AutocompleteData { - this.type = item.type; - this.url = item.url; - this.label = item.label; - this.optionsRoot = item.optionsRoot; - this.autoCompleteOptions = JsonSerializer.fromJSONObject(item.autoCompleteOptions, ListingItem); - return this; - } -} diff --git a/dmp-frontend/src/app/models/DataField/BooleanDecisionData.ts b/dmp-frontend/src/app/models/DataField/BooleanDecisionData.ts deleted file mode 100644 index 39287bcf2..000000000 --- a/dmp-frontend/src/app/models/DataField/BooleanDecisionData.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataField } from './DataField'; -import { FormGroup } from '@angular/forms'; -export class BooleanDecisionData extends DataField { - - buildForm(): FormGroup { - const formGroup = this.formBuilder.group({ - label: this.label - }); - return formGroup; - } - - fromJSONObject(item: any): BooleanDecisionData { - this.label = item.label; - return this; - } -} diff --git a/dmp-frontend/src/app/models/DataField/CheckBoxData.ts b/dmp-frontend/src/app/models/DataField/CheckBoxData.ts deleted file mode 100644 index 13fbb82b6..000000000 --- a/dmp-frontend/src/app/models/DataField/CheckBoxData.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataField } from './DataField'; -import { FormGroup } from '@angular/forms'; -export class CheckBoxData extends DataField { - - buildForm(): FormGroup { - const formGroup = this.formBuilder.group({ - label: this.label - }); - return formGroup; - } - - fromJSONObject(item: any): CheckBoxData { - this.label = item.label; - return this; - } -} diff --git a/dmp-frontend/src/app/models/DataField/DataField.ts b/dmp-frontend/src/app/models/DataField/DataField.ts deleted file mode 100644 index ec3a64563..000000000 --- a/dmp-frontend/src/app/models/DataField/DataField.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { BaseModel } from '../BaseModel'; -import { FormGenerator } from '../interfaces/FormGenerator'; -import { Serializable } from '../interfaces/Serializable'; -import { FormGroup } from '@angular/forms'; -export abstract class DataField extends BaseModel implements Serializable, FormGenerator { - public label: string; - - buildForm(): FormGroup { - throw new Error('Build Form Is not not correctly overriden'); - } - - fromJSONObject(item: any): T { - throw new Error('From Json Object is not correctly overriden'); - } - -} diff --git a/dmp-frontend/src/app/models/DataField/FreeTextData.ts b/dmp-frontend/src/app/models/DataField/FreeTextData.ts deleted file mode 100644 index b6e5ccb2f..000000000 --- a/dmp-frontend/src/app/models/DataField/FreeTextData.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataField } from './DataField'; -import { FormGroup } from '@angular/forms'; -export class FreeTextData extends DataField { - - buildForm(): FormGroup { - const formGroup = this.formBuilder.group({ - label: this.label - }); - return formGroup; - } - - fromJSONObject(item: any): FreeTextData { - this.label = item.label; - return this; - } -} diff --git a/dmp-frontend/src/app/models/DataField/RadioBoxData.ts b/dmp-frontend/src/app/models/DataField/RadioBoxData.ts deleted file mode 100644 index 1c131bca1..000000000 --- a/dmp-frontend/src/app/models/DataField/RadioBoxData.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { JsonSerializer } from '../../utilities/JsonSerializer'; -import { DataField } from './DataField'; -import { ListingItem } from '../common/ListingItem'; -import { FormGroup } from '@angular/forms'; - -export class RadioBoxData extends DataField { - public options: Array; - - buildForm(): FormGroup { - const formGroup = this.formBuilder.group({ - label: [this.label] - }); - const optionsFormArray = new Array(); - if (this.options) { - this.options.forEach(item => { - const form: FormGroup = item.buildForm(); - optionsFormArray.push(form); - }); - } - formGroup.addControl('options', this.formBuilder.array(optionsFormArray)); - return formGroup; - } - - fromJSONObject(item: any): RadioBoxData { - this.options = JsonSerializer.fromJSONArray(item.options, ListingItem); - this.label = item.label; - return this; - } -} diff --git a/dmp-frontend/src/app/models/DataField/TextArea.ts b/dmp-frontend/src/app/models/DataField/TextArea.ts deleted file mode 100644 index 316765a56..000000000 --- a/dmp-frontend/src/app/models/DataField/TextArea.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataField } from './DataField'; -import { FormGroup } from '@angular/forms'; -export class TextArea extends DataField - {{errorModel.description}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - - -
-
-
- -
-
-
- -
-
- -
-
-
- - - - - diff --git a/dmp-frontend/src/app/projects/editor/project-editor.component.scss b/dmp-frontend/src/app/projects/editor/project-editor.component.scss deleted file mode 100644 index 02908edb8..000000000 --- a/dmp-frontend/src/app/projects/editor/project-editor.component.scss +++ /dev/null @@ -1,21 +0,0 @@ -.project-editor { - - .project-editor-header-actions { - display: flex; - align-items: center; - } - - - .logo-table { - table-layout: fixed; - display: inline-block; - - td { - padding: 3px; - } - } - - .hidden { - display: none; - } -} diff --git a/dmp-frontend/src/app/projects/editor/project-editor.component.ts b/dmp-frontend/src/app/projects/editor/project-editor.component.ts deleted file mode 100644 index 6a00f65f7..000000000 --- a/dmp-frontend/src/app/projects/editor/project-editor.component.ts +++ /dev/null @@ -1,208 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; -import { MatSnackBar } from '@angular/material'; -import { ActivatedRoute, Params, Router } from '@angular/router'; -import { TdDialogService } from '@covalent/core'; -import { TranslateService } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; -import { environment } from '../../../environments/environment'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { BaseErrorModel } from '../../models/error/BaseErrorModel'; -import { ProjectModel, ProjectType } from '../../models/projects/ProjectModel'; -import { ProjectFileUploaderService } from '../../services/files/project-file-uploader.service'; -import { LanguageResolverService } from '../../services/language-resolver/language-resolver.service'; -import { ProjectService } from '../../services/project/project.service'; -import { BreadcrumbItem } from '../../shared/components/breadcrumb/definition/breadcrumb-item'; -import { IBreadCrumbComponent } from '../../shared/components/breadcrumb/definition/IBreadCrumbComponent'; -import { SnackBarNotificationComponent } from '../../shared/components/notificaiton/snack-bar-notification.component'; -import { JsonSerializer } from '../../utilities/JsonSerializer'; - -@Component({ - selector: 'app-project-editor-component', - templateUrl: 'project-editor.component.html', - styleUrls: ['./project-editor.component.scss'] -}) -export class ProjectEditorComponent extends BaseComponent implements OnInit, IBreadCrumbComponent { - - breadCrumbs: Observable = Observable.of([]); - isNew = true; - project: ProjectModel; - formGroup: FormGroup = null; - host = environment.Server; - editMode = false; - constructor( - private projectService: ProjectService, - private route: ActivatedRoute, - public snackBar: MatSnackBar, - public router: Router, - public language: TranslateService, - private dialogService: TdDialogService, - private uploaderService: ProjectFileUploaderService, - private languageResolverService: LanguageResolverService - ) { - super(); - } - - ngOnInit() { - this.route.params - .pipe(takeUntil(this._destroyed)) - .subscribe((params: Params) => { - const itemId = params['id']; - - if (itemId != null) { - this.isNew = false; - this.projectService.getSingle(itemId).map(data => data as ProjectModel) - .pipe(takeUntil(this._destroyed)) - .subscribe(data => { - this.project = JsonSerializer.fromJSONObject(data, ProjectModel); - this.formGroup = this.project.buildForm(null, this.project.type === ProjectType.External || !this.editMode); - this.breadCrumbs = Observable.of([ - { parentComponentName: 'ProjectListingComponent', label: 'Projects', url: '/projects' }, - ]); - }); - } else { - this.breadCrumbs = Observable.of([ - { parentComponentName: 'ProjectListingComponent', label: 'Projects', url: '/projects' }, - ]); - this.project = new ProjectModel(); - setTimeout(() => { - this.formGroup = this.project.buildForm(); - }); - } - }); - } - - formSubmit(): void { - this.touchAllFormFields(this.formGroup); - if (!this.isFormValid()) { return; } - this.onSubmit(); - } - - public isFormValid() { - return this.formGroup.valid; - } - - onSubmit(): void { - this.projectService.createProject(this.formGroup.value) - .pipe(takeUntil(this._destroyed)) - .subscribe( - complete => this.onCallbackSuccess(), - error => this.onCallbackError(error) - ); - } - - onCallbackSuccess(): void { - this.snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, - duration: 3000, - }); - this.router.navigate(['/projects']); - } - - onCallbackError(errorResponse: any) { - this.setErrorModel(errorResponse.error.payload); - this.validateAllFormFields(this.formGroup); - } - - public setErrorModel(errorModel: BaseErrorModel) { - Object.keys(errorModel).forEach(item => { - (this.project.errorModel)[item] = (errorModel)[item]; - }); - } - - public cancel(): void { - this.router.navigate(['/projects']); - } - - public delete(): void { - this.language.get('GENERAL.DELETE-CONFIRMATION') - .pipe(takeUntil(this._destroyed)) - .subscribe((messages: any) => { - this.dialogService.openConfirm({ - message: messages.MESSAGE, - title: messages.TITLE, - cancelButton: messages.NEGATIVE, - acceptButton: messages.POSITIVE - }).afterClosed() - .pipe(takeUntil(this._destroyed)) - .subscribe((accept: boolean) => { - if (accept) { - this.projectService.inactivate(this.project.id) - .pipe(takeUntil(this._destroyed)) - .subscribe( - complete => { this.router.navigate(['/projects']); }, - error => this.onCallbackError(error) - ); - } - }); - }); - } - - public touchAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.markAsTouched(); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.touchAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.touchAllFormFields(item); - }); - } - } - - public validateAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.updateValueAndValidity({ emitEvent: false }); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.validateAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.validateAllFormFields(item); - }); - } - } - - public enableForm() { - if (!this.isExternalProject()) { - this.editMode = true; - this.formGroup.enable(); - } - } - - public disableForm() { - this.editMode = false; - this.formGroup.disable(); - } - - public goToProjectDmps() { - this.router.navigate(['dmps/project/' + this.project.id], { queryParams: { projectLabel: this.project.label } }); - } - - public isExternalProject() { - return this.project.type === ProjectType.External; - } - - public previewImage(event): void { - const fileList: FileList | File = event.target.files; - - const formdata: FormData = new FormData(); - - if (fileList instanceof FileList) { - for (let i = 0; i < fileList.length; i++) { - formdata.append('file', fileList[i]); - } - } else { - formdata.append('file', fileList); - } - this.uploaderService.uploadFile(formdata) - .pipe(takeUntil(this._destroyed)) - .subscribe(files => this.formGroup.get('files').patchValue(files)); - } -} diff --git a/dmp-frontend/src/app/projects/listing/project-listing.component.html b/dmp-frontend/src/app/projects/listing/project-listing.component.html deleted file mode 100644 index a432d0645..000000000 --- a/dmp-frontend/src/app/projects/listing/project-listing.component.html +++ /dev/null @@ -1,72 +0,0 @@ -
-

{{languageResolverService.getBy('listingTitle') | translate}}

- - - - - - -
- - - - - {{'PROJECT-LISTING.COLUMNS.AVATAR' | translate}} - - - - - - - {{'PROJECT-LISTING.COLUMNS.NAME' | translate}} - {{row.label}} - - - - - {{'PROJECT-LISTING.COLUMNS.ABBREVIATION' | - translate}} - {{row.abbreviation}} - - - - - {{'PROJECT-LISTING.COLUMNS.START' | translate}} - {{row.startDate | date:'shortDate'}} - - - - - {{'PROJECT-LISTING.COLUMNS.END' | translate}} - {{row.endDate | date:'shortDate'}} - - - - - {{'PROJECT-LISTING.COLUMNS.DMPS' | translate}} - - - - - - - - - - - - - - - -
-
-
- - -
diff --git a/dmp-frontend/src/app/projects/listing/project-listing.component.scss b/dmp-frontend/src/app/projects/listing/project-listing.component.scss deleted file mode 100644 index df793ff4f..000000000 --- a/dmp-frontend/src/app/projects/listing/project-listing.component.scss +++ /dev/null @@ -1,31 +0,0 @@ - h3 { - margin-top: 0px; - } - - .mat-fab-bottom-right { - top: auto !important; - right: 20px !important; - bottom: 10px !important; - left: auto !important; - position: fixed !important; - } - - .full-width { - width: 100%; - } - - .mat-card { - margin: 16px 0; - } - - .mat-row { - cursor: pointer; - } - - mat-row:hover { - background-color: lightgray; - } - - mat-row:nth-child(odd) { - background-color: #eef0fb; - } diff --git a/dmp-frontend/src/app/projects/listing/project-listing.component.ts b/dmp-frontend/src/app/projects/listing/project-listing.component.ts deleted file mode 100644 index ea44bcb58..000000000 --- a/dmp-frontend/src/app/projects/listing/project-listing.component.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { DataSource } from '@angular/cdk/table'; -import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; -import { MatPaginator, MatSnackBar, MatSort } from '@angular/material'; -import { Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; -import { environment } from '../../../environments/environment'; -import { ProjectCriteria } from '../../models/criteria/project/ProjectCriteria'; -import { DataTableRequest } from '../../models/data-table/DataTableRequest'; -import { ProjectListingModel } from '../../models/projects/ProjectListingModel'; -import { ProjectStateType } from '../../models/projects/ProjectStateType'; -import { LanguageResolverService } from '../../services/language-resolver/language-resolver.service'; -import { ProjectService } from '../../services/project/project.service'; -import { BreadcrumbItem } from '../../shared/components/breadcrumb/definition/breadcrumb-item'; -import { IBreadCrumbComponent } from '../../shared/components/breadcrumb/definition/IBreadCrumbComponent'; -import { ProjectCriteriaComponent } from '../../shared/components/criteria/projects/projects-criteria.component'; -import { JsonSerializer } from '../../utilities/JsonSerializer'; - -@Component({ - selector: 'app-project-listing-component', - templateUrl: 'project-listing.component.html', - styleUrls: ['./project-listing.component.scss'], - encapsulation: ViewEncapsulation.None -}) -export class ProjectListingComponent implements OnInit, IBreadCrumbComponent { - - public breadCrumbs: Observable = Observable.of([]); - - @ViewChild(MatPaginator) _paginator: MatPaginator; - @ViewChild(MatSort) sort: MatSort; - @ViewChild(ProjectCriteriaComponent) criteria: ProjectCriteriaComponent; - - host = environment.Server; - dataSource: ProjectDataSource | null; - displayedColumns: String[] = ['avatar', 'name', 'abbreviation', 'start', 'end', 'dmps']; - - constructor( - public projectService: ProjectService, - public router: Router, - public languageService: TranslateService, - public snackBar: MatSnackBar, - public languageResolverService: LanguageResolverService - ) { - - } - - ngOnInit() { - this.breadCrumbs = Observable.of([]); - - this.criteria.setCriteria(this.getDefaultCriteria()); - this.refresh(); - this.criteria.setRefreshCallback(() => this.refresh()); - } - - refresh() { - this.dataSource = new ProjectDataSource(this.projectService, this._paginator, this.sort, this.languageService, this.snackBar, this.criteria); - } - - rowClick(rowId: String) { - this.router.navigate(['/projects/edit/' + rowId]); - } - - getDefaultCriteria(): ProjectCriteria { - const defaultCriteria = new ProjectCriteria(); - defaultCriteria.projectStateType = ProjectStateType.OnGoing; - return defaultCriteria; - } -} - -export class ProjectDataSource extends DataSource { - - totalCount = 0; - isLoadingResults = false; - - constructor( - private _service: ProjectService, - private _paginator: MatPaginator, - private _sort: MatSort, - private _languageService: TranslateService, - private _snackBar: MatSnackBar, - private _criteria: ProjectCriteriaComponent - ) { - super(); - - //this._paginator.page.pipe(takeUntil(this._destroyed)).subscribe((pageEvent: PageEvent) => { - // this.store.dispatch(new LoadPhotosRequestAction(pageEvent.pageIndex, pageEvent.pageSize)) - //}) - } - - connect(): Observable { - const displayDataChanges = [ - this._paginator.page - //this._sort.matSortChange - ]; - - // If the user changes the sort order, reset back to the first page. - //this._sort.matSortChange.pipe(takeUntil(this._destroyed)).subscribe(() => { - // this._paginator.pageIndex = 0; - //}) - - return Observable.merge(...displayDataChanges) - .startWith(null) - .switchMap(() => { - setTimeout(() => { - this.isLoadingResults = true; - }); - const startIndex = this._paginator.pageIndex * this._paginator.pageSize; - let fields: Array = new Array(); - if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; } - const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); - request.criteria = this._criteria.criteria; - return this._service.getPaged(request); - }) - /*.catch((error: any) => { - this._snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService }, - duration: 3000, - extraClasses: ['snackbar-warning'] - }); - this._criteria.onCallbackError(error.error); - return Observable.of(null); - })*/ - .map(result => { - result.data = JsonSerializer.fromJSONArray(result.data, ProjectListingModel); - return result; - }) - .map(result => { - setTimeout(() => { - this.isLoadingResults = false; - }); - return result; - }) - .map(result => { - if (!result) { return []; } - if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; } - return result.data.map(item => { - item.dmps.map(dmp => { - dmp.url = 'dmps/edit/' + dmp.url; - dmp.all = 'dmps/project/' + item.id; - return dmp; - }); - return item; - }); - }); - - } - - disconnect() { - // No-op - } -} diff --git a/dmp-frontend/src/app/projects/project.routes.ts b/dmp-frontend/src/app/projects/project.routes.ts deleted file mode 100644 index ad3527607..000000000 --- a/dmp-frontend/src/app/projects/project.routes.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { ProjectEditorComponent } from './editor/project-editor.component'; -import { ProjectListingComponent } from './listing/project-listing.component'; -import { RouterModule, Routes } from '@angular/router'; - -export const ProjectRoutes: Routes = [ - { - path: '', - component: ProjectListingComponent, - data: { - breadcrumb: true - }, - }, - { - path: 'edit/:id', - component: ProjectEditorComponent, - data: { - breadcrumb: true - }, - /* resolve: { - project: ProjectResolver - } */ - }, - { - path: 'new', - component: ProjectEditorComponent, - data: { - breadcrumb: true - }, - }, -]; - diff --git a/dmp-frontend/src/app/projects/projects.module.ts b/dmp-frontend/src/app/projects/projects.module.ts deleted file mode 100644 index 61b1b7821..000000000 --- a/dmp-frontend/src/app/projects/projects.module.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { BaseHttpService } from '../utilities/cite-http-service-module/base-http.service'; -import { TranslateHttpLoader } from '@ngx-translate/http-loader'; -import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; -import { ProjectEditorComponent } from './editor/project-editor.component'; -import { ProjectListingComponent } from './listing/project-listing.component'; -import { ProjectRoutes } from './project.routes'; -import { HttpClient, HttpClientModule } from '@angular/common/http'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { CommonModule } from '@angular/common'; - - -import { SharedModule } from '../shared/shared.module'; -import { NgModule, LOCALE_ID } from '@angular/core'; -import { ProjectService } from '../services/project/project.service'; -import { ProjectFileUploaderService } from '../services/files/project-file-uploader.service'; -import { RouterModule } from '@angular/router'; -import { BaseHttpModule } from '../utilities/cite-http-service-module/cite-http.module'; -import { MaterialModule } from '../shared/material/material.module'; -import { CultureService } from '../utilities/culture/culture-service'; -import { MAT_DATE_LOCALE } from '@angular/material'; - -@NgModule({ - imports: [ - CommonModule, - FormsModule, - HttpClientModule, - SharedModule, - MaterialModule, - RouterModule.forChild(ProjectRoutes), - ReactiveFormsModule, - TranslateModule.forRoot({ - loader: { - provide: TranslateLoader, - useFactory: HttpLoaderFactory, - deps: [HttpClient] - } - }), - BaseHttpModule.forRoot() - ], - - declarations: [ - ProjectListingComponent, - ProjectEditorComponent - ], - - exports: [ - ProjectListingComponent, - ProjectEditorComponent, - RouterModule - ], - providers: [ - ProjectService, - ProjectFileUploaderService, - /* ProjectResolver */ - - ] -}) - -export class ProjectsModule { - constructor(private translate: TranslateService) { - translate.setDefaultLang('en'); - translate.use('en'); - } -} - -export function HttpLoaderFactory(httpClient: HttpClient) { - return new TranslateHttpLoader(httpClient, 'assets/lang/', '.json'); -} diff --git a/dmp-frontend/src/app/services/auth/auth.service.ts b/dmp-frontend/src/app/services/auth/auth.service.ts deleted file mode 100644 index 9512312ce..000000000 --- a/dmp-frontend/src/app/services/auth/auth.service.ts +++ /dev/null @@ -1,150 +0,0 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { MatSnackBar } from '@angular/material'; -import { Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { takeUntil } from 'rxjs/operators'; -import { Observable } from 'rxjs/Rx'; -import { environment } from '../../../environments/environment'; -import { BaseService } from '../../core/common/base/base.service'; -import { Credential } from '../../models/login/Credential'; -import { LoginInfo } from '../../models/login/LoginInfo'; -import { Principal } from '../../models/login/Principal'; -import { SnackBarNotificationComponent } from '../../shared/components/notificaiton/snack-bar-notification.component'; -import { JsonSerializer } from '../../utilities/JsonSerializer'; - -@Injectable() -export class AuthService extends BaseService { - private actionUrl: string; - private headers: HttpHeaders; - - constructor( - private http: HttpClient, - public snackBar: MatSnackBar, - public language: TranslateService, - public router: Router - ) { - super(); - this.actionUrl = environment.Server + 'auth/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - private clear(): void { - localStorage.removeItem('principal'); - } - - public current(principal?: Principal): Principal { - if (principal) { - localStorage.setItem('principal', JSON.stringify(principal)); - return principal; - } - const principalJson = localStorage.getItem('principal'); - if (!principalJson) { return null; } - const principalObj = JSON.parse(principalJson) as Principal; - return principalObj; - } - - //public login(credential: Credential): Observable { - // const url = this.actionUrl + 'login'; - - // return this.http.post(url, credential, { headers: this.headers }) - // .map((res: Response) => { - // let principal = this.current(new JsonSerializer().fromJSONObject(res, Principal)); - // //this.loginContextSubject.next(true); - // return principal; - // }) - // .catch((error: any) => { - // //this.loginContextSubject.next(false); - // return Observable.throw(error); - // }); - //} - - public login(loginInfo: LoginInfo): Observable { - const url = this.actionUrl + 'externallogin'; - - return this.http.post(url, loginInfo, { headers: this.headers }) - .map((res: any) => { - const principal = this.current(JsonSerializer.fromJSONObject(res.payload, Principal)); - //this.loginContextSubject.next(true); - return principal; - }) - .catch((error: any) => { - //this.loginContextSubject.next(false); - return Observable.throw(error); - }); - } - - public nativeLogin(credentials: Credential): Observable { - const url = this.actionUrl + 'nativelogin'; - - return this.http.post(url, credentials, { headers: this.headers }) - .map((res: any) => { - const principal = this.current(JsonSerializer.fromJSONObject(res.payload, Principal)); - //this.loginContextSubject.next(true); - return principal; - }) - .catch((error: any) => { - //this.loginContextSubject.next(false); - return Observable.throw(error); - }); - } - - - public logout(): void { - const url = this.actionUrl + 'logout'; - const principal = this.current(); - this.clear(); - - if (!principal) { return; } - let headers = this.headers; - headers = headers.set('AuthToken', principal.token); - this.http.post(url, null, { headers: headers }) - .pipe(takeUntil(this._destroyed)) - .subscribe( - res => this.onLogOutSuccess(res), - error => this.onLogOutError(error) - ); - } - - public me(): Observable { - const url = this.actionUrl + '/me'; - const principal = this.current(); - if (!principal) { - this.clear(); - return Observable.of(); - } - let headers = this.headers; - headers = headers.set('AuthToken', principal.token); - return this.http.post(url, null, { headers: headers }) - .map((res: any) => { - const princ = this.current(JsonSerializer.fromJSONObject(res.payload, Principal)); - return princ; - }) - .catch((error: any) => { - //console.warn('could not retrieve me info:\n', error); - this.clear(); - const princ = this.current(); - this.router.navigate(['/login']); - return Observable.of(princ); - }); - } - - public onLogOutSuccess(logoutMessage: any) { - this.snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: 'GENERAL.SNACK-BAR.SUCCESSFUL-LOGOUT', language: this.language }, - duration: 3000, - }); - this.router.navigate(['/login']); - } - - public onLogOutError(errorMessage: string) { - this.snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: 'GENERAL.SNACK-BAR.UNSUCCESSFUL-LOGOUT', language: this.language }, - duration: 3000, - }); - this.router.navigate(['/login']); - } -} diff --git a/dmp-frontend/src/app/services/breadcrumb/breadcrumb-resolver.service.ts b/dmp-frontend/src/app/services/breadcrumb/breadcrumb-resolver.service.ts deleted file mode 100644 index 6dc7dc90c..000000000 --- a/dmp-frontend/src/app/services/breadcrumb/breadcrumb-resolver.service.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { Injectable, NgZone } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { Observable } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; -import { BaseService } from '../../core/common/base/base.service'; -import { BreadcrumbItem } from '../../shared/components/breadcrumb/definition/breadcrumb-item'; -import { IBreadCrumbComponent } from '../../shared/components/breadcrumb/definition/IBreadCrumbComponent'; - -@Injectable() -export class BreadCrumbResolverService extends BaseService { - - private activeComponents = []; - private parentComponents = []; - private breadCrumbs: Observable = Observable.of([]); - constructor( - private router: Router, - private zone: NgZone - ) { super(); } - - public push(component: any) { - const existingComponentIndex = this.activeComponents.map(x => x.constructor.name).indexOf(component.constructor.name); - if (existingComponentIndex !== -1) { this.activeComponents.splice(existingComponentIndex, 1); } - this.activeComponents.push(component); - } - - public clear() { - this.activeComponents.length = 0; - this.breadCrumbs = Observable.of([]); - } - - public resolve(activatedRoute: ActivatedRoute): Observable { - this.breadCrumbs = null; - const routeComponents = this.getComponentsFromRoute(activatedRoute, []); - this.activeComponents.filter(x => routeComponents.indexOf(x.constructor.name) !== -1).forEach(x => { - if (x.hasOwnProperty('breadCrumbs')) { - const componentItems = this.resolveDependentComponents((x).breadCrumbs, []); - this.breadCrumbs = Observable.of(componentItems); - } - }); - return this.breadCrumbs; - } - - private getComponentsFromRoute(activatedRoute: ActivatedRoute, routeComponents: any[]): any[] { - activatedRoute.children.forEach(x => { - if (x.children.length > 0) { this.getComponentsFromRoute(x.children[0], routeComponents); } - if (x.component) { routeComponents.push(x.component['name']); } - }); - if (activatedRoute.component) { routeComponents.push(activatedRoute.component['name']); } - - return routeComponents; - } - - resolveDependentComponents(items: Observable, components: any[]): any[] { - items - .pipe(takeUntil(this._destroyed)) - .subscribe(breadCrumbs => { - breadCrumbs.forEach(async item => { - const parentComponent = item.parentComponentName ? this.findComponent(item.parentComponentName) : null; - if (parentComponent && parentComponent.hasOwnProperty('breadCrumbs')) { - components = this.pushToStart(components, this.resolveDependentComponents((parentComponent).breadCrumbs, components)); - } else if (item.notFoundResolver) { - components = this.pushToStart(components, item.notFoundResolver); - //components = this.pushToStart(components, [unresolvedComponentItems]) - } - }); - components = this.pushToEnd(components, breadCrumbs); - }); - return components; - } - - private findComponent(componentName: string): any { - for (let i = 0; i < this.activeComponents.length; i++) { - if (this.activeComponents[i].constructor.name === componentName) { return this.activeComponents[i]; } - } - return null; - } - - pushToStart(first: any[], second: any[]) { - return [].concat(second.filter(x => first.map(firstX => firstX.label).indexOf(x.label) === -1), first); - } - - pushToEnd(first: any[], second: any[]) { - return [].concat(first, second.filter(x => first.map(firstX => firstX.label).indexOf(x.label) === -1)); - } -} diff --git a/dmp-frontend/src/app/services/dashboard/dashboard.service.ts b/dmp-frontend/src/app/services/dashboard/dashboard.service.ts deleted file mode 100644 index da151876a..000000000 --- a/dmp-frontend/src/app/services/dashboard/dashboard.service.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import 'rxjs/add/operator/map'; -import { environment } from '../../../environments/environment'; -import { DashboardStatisticsModel } from '../../models/dashboard/DashboardStatisticsModel'; -import { SearchBarItem } from '../../models/dashboard/SearchBarItem'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; - -@Injectable() -export class DashboardService { - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private http: BaseHttpService) { - - this.actionUrl = environment.Server + 'dashboard/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - getStatistics(): Observable { - return this.http.get(this.actionUrl + 'getStatistics', { headers: this.headers }); - } - - getStatisticsSpecificuser(): Observable { - return this.http.get(this.actionUrl + 'me/getStatistics', { headers: this.headers }); - } - - searchUserItems(like: string): Observable { - return this.http.get(this.actionUrl + 'search?like=' + like, { headers: this.headers }); - } - -} diff --git a/dmp-frontend/src/app/services/data-management-plan-profile/datamanagement-profile.service.ts b/dmp-frontend/src/app/services/data-management-plan-profile/datamanagement-profile.service.ts deleted file mode 100644 index 0b4f6f32a..000000000 --- a/dmp-frontend/src/app/services/data-management-plan-profile/datamanagement-profile.service.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Injectable } from '@angular/core'; -import { HttpHeaders } from '@angular/common/http'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; -import { DataTableRequest } from '../../models/data-table/DataTableRequest'; -import { DataTableData } from '../../models/data-table/DataTableData'; -import { Observable } from 'rxjs'; -import { DataManagementPlanProfileCriteria } from '../../models/criteria/dmp-profile/DataManagementPlanProfileCriteria'; -import { DataManagementPlanProfileListingModel } from '../../models/data-management-plan-profile/DataManagementPlanProfileListingModel'; -import { DataManagementPlanProfileModel } from '../../models/data-management-plan-profile/DataManagementPlanProfileModel'; -import { RequestItem } from '../../models/criteria/RequestItem'; -import { environment } from '../../../environments/environment'; - -@Injectable() -export class DataManagementPlanProfileService { - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private http: BaseHttpService) { - - this.actionUrl = environment.Server + 'dmpprofile/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - getPaged(dataTableRequest: DataTableRequest): Observable> { - return this.http.post>(this.actionUrl + 'getPaged', dataTableRequest, { headers: this.headers }); - } - - getSingle(id: String): Observable { - return this.http.get(this.actionUrl + 'getSingle/' + id, { headers: this.headers }); - } - - createDataManagementPlan(dataManagementPlanModel: DataManagementPlanProfileModel): Observable { - return this.http.post(this.actionUrl + 'createOrUpdate', dataManagementPlanModel, { headers: this.headers }); - } - - getAll(criteria: RequestItem): Observable { - return this.http.post(this.actionUrl + 'get/', criteria, { headers: this.headers }); - } -} diff --git a/dmp-frontend/src/app/services/data-management-plan/data-management-plan.service.ts b/dmp-frontend/src/app/services/data-management-plan/data-management-plan.service.ts deleted file mode 100644 index 555062a4e..000000000 --- a/dmp-frontend/src/app/services/data-management-plan/data-management-plan.service.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import 'rxjs/add/operator/map'; -import { environment } from '../../../environments/environment'; -import { DataManagementPlanCriteria } from '../../models/criteria/data-management-plan/DataManagementPlanCriteria'; -import { DatasetProfileCriteria } from '../../models/criteria/dataset-profile/DatasetProfileCriteria'; -import { RequestItem } from '../../models/criteria/RequestItem'; -import { DataManagementPlanListingModel } from '../../models/data-managemnt-plans/DataManagementPlanListingModel'; -import { DataManagementPlanModel } from '../../models/data-managemnt-plans/DataManagementPlanModel'; -import { DataTableData } from '../../models/data-table/DataTableData'; -import { DataTableRequest } from '../../models/data-table/DataTableRequest'; -import { DatasetProfileModel } from '../../models/datasets/DatasetProfileModel'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; - -@Injectable() -export class DataManagementPlanService { - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private http: BaseHttpService, private httpClient: HttpClient) { - - this.actionUrl = environment.Server + 'dmps/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - getPaged(dataTableRequest: DataTableRequest): Observable> { - return this.http.post>(this.actionUrl + 'getPaged', dataTableRequest, { headers: this.headers }); - } - - getSingle(id: String): Observable { - return this.http.get(this.actionUrl + 'getSingle/' + id, { headers: this.headers }); - } - - unlock(id: String): Observable { - return this.http.get(this.actionUrl + id + '/unlock', { headers: this.headers }); - } - createDataManagementPlan(dataManagementPlanModel: DataManagementPlanModel): Observable { - return this.http.post(this.actionUrl + 'createOrUpdate', dataManagementPlanModel, { headers: this.headers }); - } - - inactivate(id: String): Observable { - return this.http.delete(this.actionUrl + 'inactivate/' + id, { headers: this.headers }); - } - - searchDMPProfiles(dataSetProfileRequest: RequestItem): Observable { - return this.http.post(this.actionUrl + 'datasetprofiles/get', dataSetProfileRequest, { headers: this.headers }); - } - - newVersion(dataManagementPlanModel: DataManagementPlanModel, id: String): Observable { - return this.http.post(this.actionUrl + 'new/' + id, dataManagementPlanModel, { headers: this.headers }); - } - - clone(dataManagementPlanModel: DataManagementPlanModel, id: String): Observable { - return this.http.post(this.actionUrl + 'clone/' + id, dataManagementPlanModel, { headers: this.headers }); - } - - delete(id: String): Observable { - return this.http.delete(this.actionUrl + 'delete/' + id, { headers: this.headers }); - } - - getDynamicField(requestItem: RequestItem): any { - return this.http.post(this.actionUrl + 'dynamic', requestItem, { headers: this.headers }); - } - - get(requestItem: RequestItem): Observable { - return this.http.post(this.actionUrl + 'get', requestItem, { headers: this.headers }); - } - - public downloadXML(id: string): Observable> { - return this.httpClient.get(this.actionUrl + 'getXml/' + id, { responseType: 'blob', observe: 'response' }); - } - - public downloadDocx(id: string): Observable> { - return this.httpClient.get(this.actionUrl + 'getWord/' + id, { responseType: 'blob', observe: 'response' }); - } - - public downloadPDF(id: string): Observable> { - return this.httpClient.get(this.actionUrl + 'getPDF/' + id, { responseType: 'blob', observe: 'response' }); - } -} diff --git a/dmp-frontend/src/app/services/datarepository/datarepository.service.ts b/dmp-frontend/src/app/services/datarepository/datarepository.service.ts deleted file mode 100644 index ec4ae25d6..000000000 --- a/dmp-frontend/src/app/services/datarepository/datarepository.service.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import { environment } from '../../../environments/environment'; -import { DataRepositoryModel } from '../../models/dataRepositories/DataRepositoryModel'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; - -@Injectable() -export class DataRepositoryService { - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private http: BaseHttpService) { - - this.actionUrl = environment.Server + 'datarepos/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - create(dataRepoModel: DataRepositoryModel): Observable { - return this.http.post(this.actionUrl + 'create', dataRepoModel, { headers: this.headers }); - } - -} diff --git a/dmp-frontend/src/app/services/dataset-profile.service.ts b/dmp-frontend/src/app/services/dataset-profile.service.ts deleted file mode 100644 index 6de290699..000000000 --- a/dmp-frontend/src/app/services/dataset-profile.service.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import { environment } from '../../environments/environment'; -import { AutocompleteLookupItem } from '../models/auto-complete/AutocompleteLookupItem'; -import { RequestItem } from '../models/criteria/RequestItem'; -import { DatasetProfileAdmin } from '../services/datasetProfileAdmin/datasetProfileAfmin.service'; - -@Injectable() -export class DatasetProfileService { - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private httpClient: HttpClient, private datasetProfileAdmin: DatasetProfileAdmin) { - this.actionUrl = environment.Server + 'datasetwizard/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - getDatasetProfileById(datasetProfileID) { - return this.datasetProfileAdmin.getDatasetProfileById(datasetProfileID); - } - - queryAutocomplete(lookUpItem: RequestItem): Observable { - return this.httpClient.post(environment.Server + 'search/autocomplete', lookUpItem); - } - -} diff --git a/dmp-frontend/src/app/services/dataset-wizard/dataset-wizard.service.ts b/dmp-frontend/src/app/services/dataset-wizard/dataset-wizard.service.ts deleted file mode 100644 index 0812c756e..000000000 --- a/dmp-frontend/src/app/services/dataset-wizard/dataset-wizard.service.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import 'rxjs/add/operator/map'; -import { environment } from '../../../environments/environment'; -import { DataManagementPlanCriteria } from '../../models/criteria/data-management-plan/DataManagementPlanCriteria'; -import { DatasetProfileCriteria } from '../../models/criteria/dataset-profile/DatasetProfileCriteria'; -import { RequestItem } from '../../models/criteria/RequestItem'; -import { DataManagementPlanModel } from '../../models/data-managemnt-plans/DataManagementPlanModel'; -import { DatasetProfileModel } from '../../models/datasetprofile/DatasetProfileModel'; -import { DatasetProfileDefinitionModel } from '../../models/DatasetProfileDefinitionModel'; -import { DatasetWizardModel } from '../../models/datasets/DatasetWizardModel'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; - - -@Injectable() -export class DatasetWizardService { - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private http: BaseHttpService, private httpClient: HttpClient) { - - this.actionUrl = environment.Server + 'datasetwizard/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - public userDmps(criteria: RequestItem): Observable { - return this.http.post(this.actionUrl + 'userDmps', criteria, { headers: this.headers }); - } - - public getAvailableProfiles(criteria: RequestItem): Observable { - return this.http.post(this.actionUrl + 'getAvailableProfiles/', criteria, { headers: this.headers }); - } - - public getSingle(id: String): Observable { - return this.http.get(this.actionUrl + 'getSingle/' + id, { headers: this.headers }); - } - - public delete(id: string): Observable { - return this.http.delete(this.actionUrl + 'delete/' + id, { headers: this.headers }); - } - - createDataset(datasetModel: DatasetWizardModel): Observable { - return this.http.post(this.actionUrl + 'createOrUpdate', datasetModel, { headers: this.headers }); - } - - public downloadPDF(id: string): Observable> { - return this.httpClient.get(this.actionUrl + 'getPDF/' + id, { responseType: 'blob', observe: 'response' }); - } - - public downloadXML(id: string): Observable> { - return this.httpClient.get(this.actionUrl + 'getXml/' + id, { responseType: 'blob', observe: 'response' }); - } - - public getDefinition(id: String): Observable { - return this.http.get(this.actionUrl + 'get/' + id, { headers: this.headers }); - } - - unlock(id: String): Observable { - return this.http.get(this.actionUrl + id + '/unlock', { headers: this.headers }); - } -} diff --git a/dmp-frontend/src/app/services/dataset/dataset.service.ts b/dmp-frontend/src/app/services/dataset/dataset.service.ts deleted file mode 100644 index 5a10d7ed1..000000000 --- a/dmp-frontend/src/app/services/dataset/dataset.service.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import 'rxjs/add/operator/map'; -import { environment } from '../../../environments/environment'; -import { DatasetCriteria } from '../../models/criteria/dataset/DatasetCriteria'; -import { DataTableData } from '../../models/data-table/DataTableData'; -import { DataTableRequest } from '../../models/data-table/DataTableRequest'; -import { DatasetProfileModel } from '../../models/datasetprofile/DatasetProfileModel'; -import { DatasetListingModel } from '../../models/datasets/DatasetListingModel'; -import { FacetSearchCriteriaModel } from '../../models/facet-search/FacetSearchCriteriaModel'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; - - - -@Injectable() -export class DatasetService { - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private http: BaseHttpService) { - - this.actionUrl = environment.Server + 'datasets/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - getPaged(dataTableRequest: DataTableRequest): Observable> { - return this.http.post>(this.actionUrl + 'getPaged', dataTableRequest, { headers: this.headers }); - } - - getPublicPaged(dataTableRequest: DataTableRequest): Observable> { - return this.http.post>(this.actionUrl + 'public/paged', dataTableRequest, { headers: this.headers }); - } - - makeDatasetPublic(id: String) { - return this.http.get(this.actionUrl + 'makepublic/' + id, { headers: this.headers }); - } - - getDatasetProfiles(): Observable { - return this.http.get(environment.Server + 'datasetprofiles/getAll', { headers: this.headers }); - } - -} diff --git a/dmp-frontend/src/app/services/datasetProfileAdmin/datasetProfileAfmin.service.ts b/dmp-frontend/src/app/services/datasetProfileAdmin/datasetProfileAfmin.service.ts deleted file mode 100644 index c0c17c3cd..000000000 --- a/dmp-frontend/src/app/services/datasetProfileAdmin/datasetProfileAfmin.service.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import { environment } from '../../../environments/environment'; -import { DatasetProfileCriteria } from '../../models/criteria/dataset-profile/DatasetProfileCriteria'; -import { DataTableData } from '../../models/data-table/DataTableData'; -import { DataTableRequest } from '../../models/data-table/DataTableRequest'; -import { DatasetProfileModelAdmin } from '../../models/datasetProfileAdmin/DatasetProfileModelAdmin'; -import { DatasetListingModel } from '../../models/datasets/DatasetListingModel'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; - - - -@Injectable() -export class DatasetProfileAdmin { - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private http: BaseHttpService) { - - this.actionUrl = environment.Server + 'admin/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - createForm(data) { - return this.http.post(this.actionUrl + 'addDmp', data, { headers: this.headers }); - } - - updateForm(id, data) { - return this.http.post(this.actionUrl + 'addDmp/' + id, data, { headers: this.headers }); - } - - getDatasetProfileById(datasetProfileID) { - return this.http.get(this.actionUrl + 'get/' + datasetProfileID, { headers: this.headers }); - } - - getPaged(dataTableRequest: DataTableRequest): Observable> { - return this.http.post>(this.actionUrl + 'datasetprofiles/getPaged', dataTableRequest, { headers: this.headers }); - } - - preview(data: DatasetProfileModelAdmin): Observable { - return this.http.post(this.actionUrl + 'preview', data, { headers: this.headers }); - } - - clone(id: string): Observable { - return this.http.post(environment.Server + 'datasetprofile/clone/' + id, {}, { headers: this.headers }); - } -} diff --git a/dmp-frontend/src/app/services/external-dataset/external-dataset.service.ts b/dmp-frontend/src/app/services/external-dataset/external-dataset.service.ts deleted file mode 100644 index 77f86c23f..000000000 --- a/dmp-frontend/src/app/services/external-dataset/external-dataset.service.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import { environment } from '../../../environments/environment'; -import { ExternalDatasetCriteria } from '../../models/criteria/external-dataset/ExternalDatasetCriteria'; -import { RequestItem } from '../../models/criteria/RequestItem'; -import { DataTableData } from '../../models/data-table/DataTableData'; -import { DataTableRequest } from '../../models/data-table/DataTableRequest'; -import { ExternalDatasetModel } from '../../models/external-dataset/ExternalDatasetModel'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; - - -@Injectable() -export class ExternalDatasetService { - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private http: BaseHttpService) { - - this.actionUrl = environment.Server + 'externaldatasets/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - getPaged(dataTableRequest: DataTableRequest): Observable> { - return this.http.post>(this.actionUrl + 'getPaged', dataTableRequest, { headers: this.headers }); - } - - /* get(requestItem: RequestItem): Observable { - return this.http.post(this.actionUrl + 'get', requestItem, { headers: this.headers }); - }*/ - - getWithExternal(requestItem: RequestItem): Observable { - return this.http.post(this.actionUrl + 'getWithExternal', requestItem, { headers: this.headers }); - } - - getSingle(id: string): Observable { - return this.http.get(this.actionUrl + 'getSingle/' + id, { headers: this.headers }); - } - - create(externalDatasetModel: ExternalDatasetModel): Observable { - return this.http.post(this.actionUrl + 'create', externalDatasetModel, { headers: this.headers }); - } -} diff --git a/dmp-frontend/src/app/services/external-sources/external-sources-configuration.service.ts b/dmp-frontend/src/app/services/external-sources/external-sources-configuration.service.ts deleted file mode 100644 index 884d78db1..000000000 --- a/dmp-frontend/src/app/services/external-sources/external-sources-configuration.service.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import { environment } from '../../../environments/environment'; -import { ExternalSourcesConfiguration } from '../../models/external-sources/ExternalSourcesConfiguration'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; - - -@Injectable() -export class ExternalSourcesConfigurationService { - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private http: BaseHttpService) { - - this.actionUrl = environment.Server + 'common/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - public getExternalSourcesConfiguration(): Observable { - return this.http.get(this.actionUrl + 'externalSourcesConfiguration', { headers: this.headers }); - } - -} diff --git a/dmp-frontend/src/app/services/external-sources/external-sources.service.ts b/dmp-frontend/src/app/services/external-sources/external-sources.service.ts deleted file mode 100644 index 523936c8b..000000000 --- a/dmp-frontend/src/app/services/external-sources/external-sources.service.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import 'rxjs/add/operator/map'; -import { environment } from '../../../environments/environment'; -import { DataRepositoryCriteria } from '../../models/criteria/data-repository/DataRepositoryCriteria'; -import { ExternalDatasetCriteria } from '../../models/criteria/external-dataset/ExternalDatasetCriteria'; -import { RegistryCriteria } from '../../models/criteria/registry/RegistryCriteria'; -import { RequestItem } from '../../models/criteria/RequestItem'; -import { ResearcherCriteria } from '../../models/criteria/researchers/ResearcherCriteria'; -import { ServicesCriteria } from '../../models/criteria/services/ServicesCriteria'; -import { TagsCriteria } from '../../models/criteria/tags/TagsCriteria'; -import { ExternalSourcesItemModel } from '../../models/external-sources/ExternalSourcesItemModel'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; - - -@Injectable() -export class ExternalSourcesService { - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private http: BaseHttpService) { - - this.actionUrl = environment.Server + 'external/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - public searchDatasetRegistry(requestItem: RequestItem): Observable { - return this.http.get(this.actionUrl + 'registries' + '?query=' + requestItem.criteria.like + '&type=' + requestItem.criteria.type, { headers: this.headers }); - } - - public searchDatasetRepository(requestItem: RequestItem): Observable { - return this.http.get(this.actionUrl + 'datarepos' + '?query=' + requestItem.criteria.like + '&type=' + requestItem.criteria.type, { headers: this.headers }); - } - - public searchDatasetService(requestItem: RequestItem): Observable { - return this.http.get(this.actionUrl + 'services' + '?query=' + requestItem.criteria.like + '&type=' + requestItem.criteria.type, { headers: this.headers }); - } - - public searchDatasetTags(requestItem: RequestItem): Observable { - return Observable.of([ - { id: '1', name: 'Tag 1', description: '' }, - { id: '2', name: 'Tag 2', description: '' }, - { id: '3', name: 'Tag 3', description: '' }, - { id: '4', name: 'Tag 4', description: '' }, - { id: '5', name: 'Tag 5', description: '' }, - { id: '6', name: 'Tag 6', description: '' }, - { id: '7', name: 'Tag 7', description: '' }, - { id: '8', name: 'Tag 8', description: '' }, - ]); - //return this.http.get(this.actionUrl + "tags" + "?query=" + requestItem.criteria.like + "&type=" + requestItem.criteria.type, { headers: this.headers }); - } - - public searchDatasetSExternalDatasetservice(requestItem: RequestItem): Observable { - return this.http.get(this.actionUrl + 'datasets' + '?query=' + requestItem.criteria.like + '&type=' + requestItem.criteria.type, { headers: this.headers }); - } - - public searchDMPResearchers(requestItem: RequestItem): Observable { - return this.http.post(environment.Server + '/researchers/getWithExternal', requestItem, { headers: this.headers }); - } - - public searchDMPOrganizations(like: string): Observable { - return this.http.get(this.actionUrl + 'organisations' + '?query=' + like, { headers: this.headers }); - }//organizationscriteria.criteria.like - - public searchDMPProfiles(like: string): Observable { - return this.http.get(this.actionUrl + 'datasetprofiles/get' + '?query=' + like, { headers: this.headers }); - } - -} diff --git a/dmp-frontend/src/app/services/files/project-file-uploader.service.ts b/dmp-frontend/src/app/services/files/project-file-uploader.service.ts deleted file mode 100644 index 7891bff2d..000000000 --- a/dmp-frontend/src/app/services/files/project-file-uploader.service.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import 'rxjs/add/operator/map'; -import { environment } from '../../../environments/environment'; -import { ContentFile } from '../../models/files/ContentFile'; -import { FileUploader } from '../../shared/components/file-uploader/FileUploader'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; - - -@Injectable() -export class ProjectFileUploaderService implements FileUploader { - - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private http: BaseHttpService) { - - this.actionUrl = environment.Server + 'files/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - uploadFile(formData: FormData): Observable { - return this.http.post(this.actionUrl + 'upload', formData, this.headers); - } -} diff --git a/dmp-frontend/src/app/services/help-content/CachedContentItem.ts b/dmp-frontend/src/app/services/help-content/CachedContentItem.ts deleted file mode 100644 index 91cc899b7..000000000 --- a/dmp-frontend/src/app/services/help-content/CachedContentItem.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { PageHelpContent } from '../../models/help-content/page-help-content'; - -export class CachedContentItem { - public timestamp: number; - public content: PageHelpContent; -} diff --git a/dmp-frontend/src/app/services/help-content/help-content.service.ts b/dmp-frontend/src/app/services/help-content/help-content.service.ts deleted file mode 100644 index 3b888f188..000000000 --- a/dmp-frontend/src/app/services/help-content/help-content.service.ts +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Created by stefania on 7/17/17. - */ -import { Injectable } from '@angular/core'; -import { Http, Response } from '@angular/http'; -import { Observable } from 'rxjs/Rx'; -import { environment } from '../../../environments/environment'; -import { PageHelpContent } from '../../models/help-content/page-help-content'; -import { CachedContentItem } from './CachedContentItem'; - -@Injectable() -export class HelpContentService { - private _helpServiceUrl = environment.HelpService.Url; - cache = new Map(); - - constructor(private http: Http) { - } - - getActivePageContent(route: string) { - if (!this.cache.get(route) || !this.isValidCachedItem(route)) { - return this.http.get(this._helpServiceUrl + '/page/route?q=' + route) - .map(res => { - this.cache.set(route, { timestamp: Date.now(), content: res.json() }); - return res.json(); - }) - .catch(this.handleError); - } - return Observable.create(observer => observer.next(this.cache.get(route).content)); - } - private extractData(res: Response) { - const body = res.json(); - return body.data || {}; - } - private handleError(error: Response | any) { - // In a real world app, we might use a remote logging infrastructure - // We'd also dig deeper into the error to get a better message - let errMsg = ''; - if (error instanceof Response) { - const body = error.text() || ''; - //const err = body.error || JSON.stringify(body); - errMsg = `${error.status} - ${error.statusText || ''} ${body}`; - } else { - errMsg = (error.message) ? error.message : - error.status ? `${error.status} - ${error.statusText}` : 'Server error'; - console.error(errMsg); // log to console instead - } - return Observable.throw(errMsg); - } - - isValidCachedItem(route) { - const cachedTimestamp = this.cache.get(route).timestamp; - const currentTimestamp = Date.now(); - if (currentTimestamp - cachedTimestamp > 30000) { return false; } else { return true; } - } -} diff --git a/dmp-frontend/src/app/services/invitation/invitation.service.ts b/dmp-frontend/src/app/services/invitation/invitation.service.ts deleted file mode 100644 index 074478b50..000000000 --- a/dmp-frontend/src/app/services/invitation/invitation.service.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import { environment } from '../../../environments/environment'; -import { UserInvitationCriteria } from '../../models/criteria/invitation/UserInvitationCriteria'; -import { RequestItem } from '../../models/criteria/RequestItem'; -import { Invitation } from '../../models/invitation/Invitation'; -import { User } from '../../models/invitation/User'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; - -@Injectable() -export class InvitationService { - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private http: BaseHttpService) { - - this.actionUrl = environment.Server + 'invite/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - public inviteUsers(invitation: Invitation): Observable { - return this.http.post(this.actionUrl + 'users', invitation, { headers: this.headers }); - } - - public getUsers(usersInvitationRequestItem: RequestItem): Observable { - return this.http.post(this.actionUrl + 'getUsers', usersInvitationRequestItem, { headers: this.headers }); - } - - public exchange(id: String): Observable { - return this.http.get(this.actionUrl + 'exchange/' + id, { headers: this.headers }); - } -} diff --git a/dmp-frontend/src/app/services/language/language.service.ts b/dmp-frontend/src/app/services/language/language.service.ts index 5e2e4a200..89ee186ae 100644 --- a/dmp-frontend/src/app/services/language/language.service.ts +++ b/dmp-frontend/src/app/services/language/language.service.ts @@ -2,9 +2,8 @@ import { HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { environment } from '../../../environments/environment'; +import { BaseHttpService } from '../../core/services/http/base-http.service'; import { Language } from '../../models/language/Language'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; - @Injectable() export class LanguageService { @@ -21,7 +20,6 @@ export class LanguageService { } public getLang(): Observable { - return this.http.get(this.actionUrl + 'language', { headers: this.headers }); + return this.http.get(this.actionUrl + 'language', { headers: this.headers }); } - } diff --git a/dmp-frontend/src/app/services/project/project.service.ts b/dmp-frontend/src/app/services/project/project.service.ts deleted file mode 100644 index fca7709ec..000000000 --- a/dmp-frontend/src/app/services/project/project.service.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import 'rxjs/add/operator/map'; -import { environment } from '../../../environments/environment'; -import { ProjectCriteria } from '../../models/criteria/project/ProjectCriteria'; -import { RequestItem } from '../../models/criteria/RequestItem'; -import { DataTableData } from '../../models/data-table/DataTableData'; -import { DataTableRequest } from '../../models/data-table/DataTableRequest'; -import { ProjectListingModel } from '../../models/projects/ProjectListingModel'; -import { ProjectModel } from '../../models/projects/ProjectModel'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; - - -@Injectable() -export class ProjectService { - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private http: BaseHttpService) { - - this.actionUrl = environment.Server + 'projects/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - getPaged(dataTableRequest: DataTableRequest): Observable> { - return this.http.post>(this.actionUrl + 'getPaged', dataTableRequest, { headers: this.headers }); - } - - get(requestItem: RequestItem): Observable { - return this.http.post(this.actionUrl + 'get', requestItem, { headers: this.headers }); - } - - getWithExternal(requestItem: RequestItem): Observable { - return this.http.post(this.actionUrl + 'getWithExternal', requestItem, { headers: this.headers }); - } - - getSingle(id: string): Observable { - return this.http.get(this.actionUrl + 'getSingle/' + id, { headers: this.headers }); - } - - createProject(projectModel: ProjectModel): Observable { - return this.http.post(this.actionUrl + 'createOrUpdate', projectModel, { headers: this.headers }); - } - - inactivate(id: String): Observable { - return this.http.delete(this.actionUrl + 'inactivate/' + id, { headers: this.headers }); - } - - public delete(id: string): Observable { - return this.http.delete(this.actionUrl + 'delete' + id, { headers: this.headers }); - } -} diff --git a/dmp-frontend/src/app/services/registries/registry.service.ts b/dmp-frontend/src/app/services/registries/registry.service.ts deleted file mode 100644 index e861595cb..000000000 --- a/dmp-frontend/src/app/services/registries/registry.service.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import { environment } from '../../../environments/environment'; -import { RegisterModel } from '../../models/registers/RegisterModel'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; - -@Injectable() -export class RegistryService { - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private http: BaseHttpService) { - - this.actionUrl = environment.Server + 'registries/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - create(registerModel: RegisterModel): Observable { - return this.http.post(this.actionUrl + 'create', registerModel, { headers: this.headers }); - } -} diff --git a/dmp-frontend/src/app/services/researchers/researchers.service.ts b/dmp-frontend/src/app/services/researchers/researchers.service.ts deleted file mode 100644 index ae32e24e9..000000000 --- a/dmp-frontend/src/app/services/researchers/researchers.service.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { environment } from '../../../environments/environment'; -import { ResearcherModel } from '../../models/researcher/ResearcherModel'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; - -@Injectable() -export class ResearcherService { - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private http: BaseHttpService) { - - this.actionUrl = environment.Server + 'researchers/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - public createResearcher(researcher: ResearcherModel) { - return this.http.post(this.actionUrl + 'create', researcher, { headers: this.headers }); - } - -} diff --git a/dmp-frontend/src/app/services/route-resolvers/dmp-editor-resolver.service.ts b/dmp-frontend/src/app/services/route-resolvers/dmp-editor-resolver.service.ts deleted file mode 100644 index b97f8049b..000000000 --- a/dmp-frontend/src/app/services/route-resolvers/dmp-editor-resolver.service.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* import { Injectable } from "@angular/core"; -import { ProjectService } from "../project/project.service"; -import { RouterStateSnapshot, ActivatedRouteSnapshot } from "@angular/router"; -import { inherits } from "util"; -import { McBreadcrumbsResolver } from 'ngx-breadcrumbs'; - -@Injectable() -export class DMPEditorResolver extends McBreadcrumbsResolver { - - // Optional: inject any required dependencies - constructor(private projectService: ProjectService) { - super(); - } - - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { - - const projectId = route.params.id; - const myCrumbs = this.projectService.getSingle(projectId).map((project) => ( - { - text: project.label, - path: super.getFullPath(route.parent) + 'edit/' + project.id - } - )) - - // Note: the resolve method can return any of the following types: - // - // * IBreadcrumb[] - // * Observable - // * Promise - - return myCrumbs; - } -} - */ diff --git a/dmp-frontend/src/app/services/route-resolvers/dmp-group-resolver.service.ts b/dmp-frontend/src/app/services/route-resolvers/dmp-group-resolver.service.ts deleted file mode 100644 index 06e0e82e2..000000000 --- a/dmp-frontend/src/app/services/route-resolvers/dmp-group-resolver.service.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* import { Injectable } from "@angular/core"; -import { ProjectService } from "../project/project.service"; -import { RouterStateSnapshot, ActivatedRouteSnapshot } from "@angular/router"; -import { inherits } from "util"; -import { McBreadcrumbsResolver } from 'ngx-breadcrumbs'; -import { DataManagementPlanService } from "../data-management-plan/data-management-plan.service"; - -@Injectable() -export class DMPGroupResolver extends McBreadcrumbsResolver { - - // Optional: inject any required dependencies - constructor(private dmpService: DataManagementPlanService) { - super(); - } - - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { - - const groupId = route.params.groupId; - const myCrumbs = this.dmpService.getSingle(groupId).map((dmp) => ( - { - text: dmp.label, - path: super.getFullPath(route.parent) + 'viewversions/' + dmp.id - } - )) - - // Note: the resolve method can return any of the following types: - // - // * IBreadcrumb[] - // * Observable - // * Promise - - return myCrumbs; - } -} - */ diff --git a/dmp-frontend/src/app/services/route-resolvers/project-resolver.service.ts b/dmp-frontend/src/app/services/route-resolvers/project-resolver.service.ts deleted file mode 100644 index f7c98342e..000000000 --- a/dmp-frontend/src/app/services/route-resolvers/project-resolver.service.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* import { Injectable } from "@angular/core"; -import { ProjectService } from "../project/project.service"; -import { RouterStateSnapshot, ActivatedRouteSnapshot } from "@angular/router"; -import { inherits } from "util"; -import { McBreadcrumbsResolver } from 'ngx-breadcrumbs'; - -@Injectable() -export class ProjectResolver extends McBreadcrumbsResolver { - - // Optional: inject any required dependencies - constructor(private projectService: ProjectService) { - super(); - } - - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { - - const projectId = route.params.id; - const myCrumbs = this.projectService.getSingle(projectId).map((project) => ( - { - text: project.label, - path: super.getFullPath(route.parent) + 'edit/' + project.id - } - )) - - // Note: the resolve method can return any of the following types: - // - // * IBreadcrumb[] - // * Observable - // * Promise - - return myCrumbs; - } -} - */ diff --git a/dmp-frontend/src/app/services/services/services-data.service.ts b/dmp-frontend/src/app/services/services/services-data.service.ts deleted file mode 100644 index 7640fa7f9..000000000 --- a/dmp-frontend/src/app/services/services/services-data.service.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import { environment } from '../../../environments/environment'; -import { ServiceModel } from '../../models/services/ServiceModel'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; - -@Injectable() -export class ServicesDataService { - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private http: BaseHttpService) { - - this.actionUrl = environment.Server + 'services/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - create(serviceModel: ServiceModel): Observable { - return this.http.post(this.actionUrl + 'create', serviceModel, { headers: this.headers }); - } - -} diff --git a/dmp-frontend/src/app/services/user-reference/user-reference-data.service.ts b/dmp-frontend/src/app/services/user-reference/user-reference-data.service.ts deleted file mode 100644 index 64a2ec663..000000000 --- a/dmp-frontend/src/app/services/user-reference/user-reference-data.service.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import 'rxjs/add/operator/map'; -import { environment } from '../../../environments/environment'; -import { UserCriteria } from '../../models/criteria/users/UserCriteria'; -import { DataTableData } from '../../models/data-table/DataTableData'; -import { DataTableRequest } from '../../models/data-table/DataTableRequest'; -import { UserListingModel } from '../../models/users/UserListingModel'; -import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; - -@Injectable() -export class UserReferenceService { - - private actionUrl: string; - private headers: HttpHeaders; - - constructor(private http: BaseHttpService) { - - this.actionUrl = environment.Server + '/user/'; - - this.headers = new HttpHeaders(); - this.headers = this.headers.set('Content-Type', 'application/json'); - this.headers = this.headers.set('Accept', 'application/json'); - } - - // formatItem(utilities: Utilities, item: ConfigurationModel): ConfigurationModel { - // item.validFrom = new Date(item.validFrom); - // item.validTo = new Date(item.validTo); - // return item - // } - - getPaged(dataTableRequest: DataTableRequest): Observable> { - return this.http.post>(this.actionUrl + 'getPaged', JSON.stringify(dataTableRequest), { headers: this.headers }); - } - - getUser(id: String): Observable { - return this.http.get(this.actionUrl + id, { headers: this.headers }); - } - - updateRoles(itemToUpdate: UserListingModel): Observable { - return this.http.post(this.actionUrl + 'updateRoles', JSON.stringify(itemToUpdate), { headers: this.headers }); - } - - delete(id: String): Observable { - return this.http.delete(this.actionUrl + id, { headers: this.headers }); - } - - getRecentActivity(): Observable { - return this.http.get(this.actionUrl + 'recentActivity', { headers: this.headers }); - } - - updateUserSettings(value: any): Observable { - return this.http.post(this.actionUrl + 'settings', value, { headers: this.headers }); - } -} diff --git a/dmp-frontend/src/app/shared/components/add-researchers/add-researchers.component.ts b/dmp-frontend/src/app/shared/components/add-researchers/add-researchers.component.ts deleted file mode 100644 index 14e0d2800..000000000 --- a/dmp-frontend/src/app/shared/components/add-researchers/add-researchers.component.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Component, Inject, OnInit } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; -import { ActivatedRoute, Router } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { ResearcherModel } from '../../../models/researcher/ResearcherModel'; -import { ResearcherService } from '../../../services/researchers/researchers.service'; - -@Component({ - selector: 'app-add-researchers-component', - templateUrl: 'add-researchers.component.html', - -}) -export class AddResearchersComponent extends BaseComponent implements OnInit { - - public formGroup: FormGroup; - - constructor( - private researcherService: ResearcherService, - private route: ActivatedRoute, - public router: Router, - public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any - ) { super(); } - - ngOnInit(): void { - const researcher = new ResearcherModel(); - this.formGroup = researcher.buildForm(); - } - - - send(value: any) { - this.researcherService.createResearcher(this.formGroup.value) - .pipe(takeUntil(this._destroyed)) - .subscribe( - null, null, () => this.dialogRef.close() - ); - } -} diff --git a/dmp-frontend/src/app/shared/components/auto-complete/AutoCompleteConfiguration.ts b/dmp-frontend/src/app/shared/components/auto-complete/AutoCompleteConfiguration.ts deleted file mode 100644 index 25d12102e..000000000 --- a/dmp-frontend/src/app/shared/components/auto-complete/AutoCompleteConfiguration.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { BaseCriteria } from '../../../models/criteria/BaseCriteria'; -import { RequestItem } from '../../../models/criteria/RequestItem'; -import { BehaviorSubject } from 'rxjs'; - -export class AutoCompleteConfiguration { - public callback: Function; - public refreshEvent: BehaviorSubject; - public requestItem: RequestItem; - constructor(callback: Function, requestItem: RequestItem, refreshEvent = null) { - this.callback = callback; - this.requestItem = requestItem; - this.refreshEvent = refreshEvent; - } -} diff --git a/dmp-frontend/src/app/shared/components/auto-complete/auto-complete.component.html b/dmp-frontend/src/app/shared/components/auto-complete/auto-complete.component.html deleted file mode 100644 index 7f6d09e59..000000000 --- a/dmp-frontend/src/app/shared/components/auto-complete/auto-complete.component.html +++ /dev/null @@ -1,12 +0,0 @@ - - - {{validationErrorString}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - - - - {{ this.printText(option) }} | - {{subtitleFn(option)}} - - - diff --git a/dmp-frontend/src/app/shared/components/auto-complete/auto-complete.component.scss b/dmp-frontend/src/app/shared/components/auto-complete/auto-complete.component.scss deleted file mode 100644 index cd989713b..000000000 --- a/dmp-frontend/src/app/shared/components/auto-complete/auto-complete.component.scss +++ /dev/null @@ -1,16 +0,0 @@ -.auto-complete { - width: 100%; - - .mat-form-field { - padding: 0 3px; - } - - .not-loading { - display: none; - } -} - -.two-line-mat-option { - height: 3.5em; - line-height: 1.2em; -} diff --git a/dmp-frontend/src/app/shared/components/auto-complete/auto-complete.component.ts b/dmp-frontend/src/app/shared/components/auto-complete/auto-complete.component.ts deleted file mode 100644 index da630b28c..000000000 --- a/dmp-frontend/src/app/shared/components/auto-complete/auto-complete.component.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { FormControl, FormGroupDirective, NgForm } from '@angular/forms'; -import { ErrorStateMatcher } from '@angular/material'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { AutoCompleteConfiguration } from './AutoCompleteConfiguration'; - -@Component({ - selector: 'app-auto-complete', - templateUrl: './auto-complete.component.html', - styleUrls: ['./auto-complete.component.scss'] -}) -export class AutoCompleteComponent extends BaseComponent implements OnInit, ErrorStateMatcher { - - @Input() placeholder: String; - @Input() disabled: boolean; - - @Input() typeaheadMS = 300; - @Input() formCtrl: FormControl; - @Input() required = false; - @Input() displayFunction: Function; - @Input() _subtitleFn: Function; - - @Input() assignValueFunction: Function; - @Input() transformFunction: Function; - @Input() inputData: AutoCompleteConfiguration; - @Input() validationErrorString: String; - @Input() clear = false; - - @Output() onItemChange = new EventEmitter(); - - public textFormCtrl: FormControl; - public options: any[]; - - loading = false; - hasSelectedItem = false; - isUnchanged = true; - - constructor() { - super(); - } - - ngOnInit() { - if (this.inputData.refreshEvent) { - this.inputData.refreshEvent - .pipe(takeUntil(this._destroyed)) - .subscribe(x => { - if (x) { - this.formCtrl.patchValue(null); - this.textFormCtrl.patchValue(null); - this.options = []; - } - }); - } - this.textFormCtrl = new FormControl(); - if (this.disabled) { this.textFormCtrl.disable(); } - this.formCtrl.registerOnDisabledChange(isDisabled => { - if (isDisabled) { this.textFormCtrl.disable({ onlySelf: true, emitEvent: false }); } else { this.textFormCtrl.enable({ onlySelf: true, emitEvent: false }); } - }); - if (this.formCtrl && this.formCtrl.value) { - this.textFormCtrl.patchValue(this.formCtrl.value, { emitEvent: false }); - this.hasSelectedItem = true; - } - - const valueChanges = this.textFormCtrl.valueChanges.share(); - - valueChanges.subscribe(searchTerm => { // reset value of input control every time the user starts typing - if (this.hasSelectedItem) { - this.hasSelectedItem = false; - this.onItemChange.emit(null); - if (this.formCtrl && this.formCtrl.value) { - this.formCtrl.patchValue(null, { emitEvent: false }); - } - } - this.isUnchanged = false; - }); - - valueChanges.debounceTime(this.typeaheadMS) - .do(value => { - if (this.hasSelectedItem) { this.loading = false; } - if (typeof value === 'string') { - this.loading = true; - this.inputData.requestItem.criteria['like'] = value; - this.inputData.callback(this.inputData.requestItem).map(res => { - this.options = res; - this.loading = false; - }) - .pipe(takeUntil(this._destroyed)) - .subscribe(); - } else { - this.loading = false; - } - }) - .pipe(takeUntil(this._destroyed)) - .subscribe(); - } - - printText(item: any): string { - if (this.displayFunction) { - return this.displayFunction(item); - } else { return item; } - } - - subtitleFn(item) { - return this._subtitleFn(item); - } - - getValue(item: any): string { - if (this.assignValueFunction) { - if (this.transformFunction) { return this.assignValueFunction(this.transformFunction(item)); } else { return this.assignValueFunction(item); } - } else { return item; } - } - - optionSelected(event: any) { - if (this.formCtrl) { this.formCtrl.patchValue(this.assignValueFunction ? this.assignValueFunction(event.option.value) : event.option.value, { emitEvent: false }); } - this.hasSelectedItem = true; - this.onItemChange.emit(this.assignValueFunction ? this.assignValueFunction(event.option.value) : event.option.value); - if (this.clear) { - this.options = []; - this.loading = false; - this.textFormCtrl.patchValue(null); - } - } - - isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean { - const isFormSubmitted = form && form.submitted; - const isControlInvalid = (control && control.invalid && (control.dirty || control.touched || isFormSubmitted)) || (!this.hasSelectedItem && !this.isUnchanged); - const isFormInvalid = form && form.enabled && form.invalid && (form.dirty || form.touched || isFormSubmitted); - return !!((isControlInvalid || isFormInvalid) && this.required); - } -} diff --git a/dmp-frontend/src/app/shared/components/autocompletes/multiple/multiple-auto-complete-configuration.ts b/dmp-frontend/src/app/shared/components/autocompletes/multiple/multiple-auto-complete-configuration.ts deleted file mode 100644 index 986d6e97f..000000000 --- a/dmp-frontend/src/app/shared/components/autocompletes/multiple/multiple-auto-complete-configuration.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Observable } from 'rxjs'; - -export interface MultipleAutoCompleteConfiguration { - // Delay for performing the request. Default: 200ms. - requestDelay?: number; - // Min characters for the filtering to be applied. Default: 3. - minFilteringChars?: number; - // Load and present items from start, without user query. Default: true. - loadDataOnStart?: boolean; - // Static or initial items. - initialItems?: (excludedItems: any[]) => Observable; - // Data retrieval function - filterFn?: (searchQuery: string, excludedItems: any[]) => Observable; - // Property formating for input - displayFn?: (item: any) => string; - // Property formating for dropdown - titleFn?: (item: any) => string; - // Property formating for dropdown - subtitleFn?: (item: any) => string; -} diff --git a/dmp-frontend/src/app/shared/components/autocompletes/multiple/multiple-auto-complete.component.html b/dmp-frontend/src/app/shared/components/autocompletes/multiple/multiple-auto-complete.component.html deleted file mode 100644 index 77541fb39..000000000 --- a/dmp-frontend/src/app/shared/components/autocompletes/multiple/multiple-auto-complete.component.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - {{this._displayFn(selectedItem)}} - cancel - - - - {{validationErrorString}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - {{'GENERAL.VALIDATION.INVALID-JSON' | translate}} - - - - {{_titleFn(item)}} -
- {{_subtitleFn(item)}} -
-
-
diff --git a/dmp-frontend/src/app/shared/components/autocompletes/multiple/multiple-auto-complete.component.scss b/dmp-frontend/src/app/shared/components/autocompletes/multiple/multiple-auto-complete.component.scss deleted file mode 100644 index e9502d874..000000000 --- a/dmp-frontend/src/app/shared/components/autocompletes/multiple/multiple-auto-complete.component.scss +++ /dev/null @@ -1,14 +0,0 @@ -.multiple-auto-complete { - width: 100%; - .mat-form-field { - padding: 0 3px; - } - .not-loading { - display: none; - } -} - -.two-line-mat-option { - height: 3.5em; - line-height: 1.2em; -} diff --git a/dmp-frontend/src/app/shared/components/autocompletes/multiple/multiple-auto-complete.component.ts b/dmp-frontend/src/app/shared/components/autocompletes/multiple/multiple-auto-complete.component.ts deleted file mode 100644 index 930ad5580..000000000 --- a/dmp-frontend/src/app/shared/components/autocompletes/multiple/multiple-auto-complete.component.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { Input, OnInit, Component, Output, EventEmitter, ViewChild, ElementRef, QueryList, AfterViewInit } from '@angular/core'; -import { FormControl, FormGroupDirective, NgForm, FormArray, AbstractControl, FormGroup, FormBuilder, Validators } from '@angular/forms'; -import { ErrorStateMatcher, MatChipInputEvent, MatAutocompleteSelectedEvent, MatChipList, MatAutocompleteTrigger } from '@angular/material'; -import { TranslateService } from '@ngx-translate/core'; -import { Subject, Observable } from 'rxjs'; -import { map, startWith, merge, mapTo, mergeMap, timeout } from 'rxjs/operators'; -import { MultipleAutoCompleteConfiguration } from './multiple-auto-complete-configuration'; -import { ENTER } from '@angular/cdk/keycodes'; -import { COMMA } from '@angular/cdk/keycodes'; - -@Component({ - selector: 'app-multiple-auto-complete', - templateUrl: './multiple-auto-complete.component.html', - styleUrls: ['./multiple-auto-complete.component.scss'] -}) -export class MultipleAutoCompleteComponent implements OnInit { - - @ViewChild('textInput') textInput: ElementRef; - @ViewChild(MatAutocompleteTrigger) autocomplete: MatAutocompleteTrigger; - - @Input() reactiveFormControl: FormControl; - @Input() placeholder: string; - @Input() validationErrorString: string; - @Input() configuration: MultipleAutoCompleteConfiguration; - @Input() required: boolean; - // Selected Option Event - @Output() optionSelected: EventEmitter = new EventEmitter(); - - private requestDelay = 200; //ms - private minFilteringChars = 3; - private loadDataOnStart = true; - - loading = false; - _items: Observable; - - visible = true; - selectable = true; - removable = true; - addOnBlur = false; - separatorKeysCodes = [ENTER, COMMA]; - inputFormControl: FormControl; - - constructor() { - } - - ngOnInit() { - this.inputFormControl = new FormControl({ value: this.reactiveFormControl.value, disabled: this.reactiveFormControl.disabled }); - } - - filter(query: string): Observable { - // If loadDataOnStart is enabled and query is empty we return the initial items. - if (this.isNullOrEmpty(query) && this.loadDataOnStart) { - return this.configuration.initialItems(this.reactiveFormControl.value || []) || Observable.of([]); - } else if (query && query.length >= this.minFilteringChars) { - if (this.configuration.filterFn) { - return this.configuration.filterFn(query, this.reactiveFormControl.value || []); - } else { - return this.configuration.initialItems(this.reactiveFormControl.value || []) || Observable.of([]); - } - } else { - return Observable.of([]); - } - } - - isNullOrEmpty(query: string): boolean { - return typeof query !== 'string' || query === null || query.length === 0; - } - - _displayFn(item: any): string { - if (this.configuration.displayFn && item) { return this.configuration.displayFn(item); } - return item; - } - - _titleFn(item: any): string { - if (this.configuration.titleFn && item) { return this.configuration.titleFn(item); } - return item; - } - - _subtitleFn(item: any): string { - if (this.configuration.subtitleFn && item) { return this.configuration.subtitleFn(item); } - return null; - } - - _requestDelay(): number { - return this.configuration.requestDelay || this.requestDelay; - } - - _minFilteringChars(): number { - return this.configuration.minFilteringChars || this.minFilteringChars; - } - - _loadDataOnStart(): boolean { - return this.configuration.loadDataOnStart || this.loadDataOnStart; - } - - _chipItems(): any[] { - return this.reactiveFormControl.value || []; - } - - _optionSelected(event: MatAutocompleteSelectedEvent) { - const newValue = this.reactiveFormControl.value || []; - newValue.push(event.option.value); - this.reactiveFormControl.patchValue(newValue); - this.textInput.nativeElement.value = ''; - this.inputFormControl.setValue(null); - - this.optionSelected.emit(event.option.value); - } - - _onInputFocus() { - // We set the items observable on focus to avoid the request being executed on component load. - if (!this._items) { - this._items = this.inputFormControl.valueChanges - .startWith(null) - .debounceTime(this.requestDelay) - .distinctUntilChanged() - .do(() => { this.loading = true; }) - .flatMap(query => { - // If its a valid object, a selection just made and the object is set as the value of the form control. That means we should fire an extra request to the server. - if (this._isValidObject(query)) { return Observable.of([]); } - return this.filter(query); - }) - .do(() => { this.loading = false; }); - } - } - - _isValidObject(value: any): boolean { - try { - if (!value) { return false; } - if (typeof value !== 'object') { JSON.parse(value); } - } catch (e) { - return false; - } - return true; - } - - _removeSelectedItem(item: any): void { - const autocompleteValue = this.reactiveFormControl.value; - const index = autocompleteValue.indexOf(item); - if (index >= 0) { - autocompleteValue.splice(index, 1); - this.reactiveFormControl.patchValue(autocompleteValue); - } - } - - _onInputClick(item: any) { - if (!this.autocomplete.panelOpen) { - this.autocomplete.openPanel(); - } - } - - _addItem(event: MatChipInputEvent): void { - // const input = event.input; - // const value = event.value; - // // Add our fruit - // if ((value || '').trim()) { - // this.selectedItems.push(value.trim()); - // } - // // Reset the input value - // if (input) { - // input.value = ''; - // } - // this.inputFormControl.setValue(null); - } -} diff --git a/dmp-frontend/src/app/shared/components/autocompletes/single/single-auto-complete-configuration.ts b/dmp-frontend/src/app/shared/components/autocompletes/single/single-auto-complete-configuration.ts deleted file mode 100644 index efd9f2b27..000000000 --- a/dmp-frontend/src/app/shared/components/autocompletes/single/single-auto-complete-configuration.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Observable } from 'rxjs'; - -export interface SingleAutoCompleteConfiguration { - // Delay for performing the request. Default: 200ms. - requestDelay?: number; - // Min characters for the filtering to be applied. Default: 3. - minFilteringChars?: number; - // Load and present items from start, without user query. Default: true. - loadDataOnStart?: boolean; - // Static or initial items. - items?: Observable; - // Data retrieval function - filterFn?: (searchQuery: string) => Observable; - // Property formating for input - displayFn?: (item: any) => string; - // Property formating for dropdown - titleFn?: (item: any) => string; - // Property formating for dropdown - subtitleFn?: (item: any) => string; -} diff --git a/dmp-frontend/src/app/shared/components/autocompletes/single/single-auto-complete.component.html b/dmp-frontend/src/app/shared/components/autocompletes/single/single-auto-complete.component.html deleted file mode 100644 index c84cd5d6b..000000000 --- a/dmp-frontend/src/app/shared/components/autocompletes/single/single-auto-complete.component.html +++ /dev/null @@ -1,15 +0,0 @@ - - - {{validationErrorString}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - {{'GENERAL.VALIDATION.INVALID-JSON' | translate}} - - - - - {{_titleFn(item)}} -
- {{_subtitleFn(item)}} -
-
-
diff --git a/dmp-frontend/src/app/shared/components/autocompletes/single/single-auto-complete.component.scss b/dmp-frontend/src/app/shared/components/autocompletes/single/single-auto-complete.component.scss deleted file mode 100644 index a0fa34dc6..000000000 --- a/dmp-frontend/src/app/shared/components/autocompletes/single/single-auto-complete.component.scss +++ /dev/null @@ -1,17 +0,0 @@ -.auto-complete { - width: 100%; - .mat-form-field { - padding: 0 3px; - } - .not-loading { - display: none; - } -} -.two-line-mat-option { - height: 3.5em; - line-height: 1.2em; -} - -// .mat-tooltip.warn-tooltip { -// background-color: mat-color($warn); -// } diff --git a/dmp-frontend/src/app/shared/components/autocompletes/single/single-auto-complete.component.ts b/dmp-frontend/src/app/shared/components/autocompletes/single/single-auto-complete.component.ts deleted file mode 100644 index a52d55164..000000000 --- a/dmp-frontend/src/app/shared/components/autocompletes/single/single-auto-complete.component.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { Input, OnInit, Component, Output, EventEmitter, ViewChild, ElementRef, QueryList, AfterViewInit } from '@angular/core'; -import { FormControl, FormGroupDirective, NgForm, FormArray, AbstractControl, FormGroup, FormBuilder, Validators } from '@angular/forms'; -import { ErrorStateMatcher, MatChipInputEvent, MatAutocompleteSelectedEvent, MatChipList } from '@angular/material'; -import { TranslateService } from '@ngx-translate/core'; -import { Subject, Observable } from 'rxjs'; -import { map, startWith, merge, mapTo, mergeMap, timeout } from 'rxjs/operators'; -import { SingleAutoCompleteConfiguration } from './single-auto-complete-configuration'; - -@Component({ - selector: 'app-single-auto-complete', - templateUrl: './single-auto-complete.component.html', - styleUrls: ['./single-auto-complete.component.scss'] -}) -export class SingleAutoCompleteComponent implements OnInit { - - @Input() reactiveFormControl: FormControl; - @Input() placeholder: string; - @Input() validationErrorString: string; - @Input() required: boolean; - @Input() configuration: SingleAutoCompleteConfiguration; - - // Selected Option Event - @Output() optionSelected: EventEmitter = new EventEmitter(); - - private requestDelay = 200; //ms - private minFilteringChars = 3; - private loadDataOnStart = true; - - // @Input() items: Observable; - // @Input() filterFn?: (searchQuery: string) => Observable; - // @Input() displayFn?: (item: any) => string; - // @Input() titleFn?: (item: any) => string; - // @Input() subtitleFn?: (item: any) => string; - loading = false; - _items: Observable; - - constructor() { - } - - ngOnInit() { - - } - - filter(query: string): Observable { - // If loadDataOnStart is enabled and query is empty we return the initial items. - if (this.isNullOrEmpty(query) && this.loadDataOnStart) { - return this.configuration.items || Observable.of([]); - } else if (query && query.length >= this.minFilteringChars) { - if (this.configuration.filterFn) { - return this.configuration.filterFn(query); - } else { - return this.configuration.items || Observable.of([]); - } - } else { - return Observable.of([]); - } - } - - isNullOrEmpty(query: string): boolean { - return typeof query !== 'string' || query === null || query.length === 0; - } - - _displayFn(item: any): string { - if (this.configuration.displayFn && item) { return this.configuration.displayFn(item); } - return item; - } - - _titleFn(item: any): string { - if (this.configuration.titleFn && item) { return this.configuration.titleFn(item); } - return item; - } - - _subtitleFn(item: any): string { - if (this.configuration.subtitleFn && item) { return this.configuration.subtitleFn(item); } - return null; - } - - _requestDelay(): number { - return this.configuration.requestDelay || this.requestDelay; - } - - _minFilteringChars(): number { - return this.configuration.minFilteringChars || this.minFilteringChars; - } - - _loadDataOnStart(): boolean { - return this.configuration.loadDataOnStart || this.loadDataOnStart; - } - - _optionSelected(event: MatAutocompleteSelectedEvent) { - this.optionSelected.emit(event.option.value); - } - - _onInputFocus() { - // We set the items observable on focus to avoid the request being executed on component load. - if (!this._items) { - this._items = this.reactiveFormControl.valueChanges - .startWith(null) - .debounceTime(this.requestDelay) - .distinctUntilChanged() - .do(() => { this.loading = true; }) - .flatMap(query => { - // If its a valid object, a selection just made and the object is set as the value of the form control. That means we should fire an extra request to the server. - if (this._isValidObject(query)) { return Observable.of([]); } - return this.filter(query); - }) - .do(() => { this.loading = false; }); - } - } - - _isValidObject(value: any): boolean { - try { - if (!value) { return false; } - if (typeof value !== 'object') { JSON.parse(value); } - } catch (e) { - return false; - } - return true; - } -} diff --git a/dmp-frontend/src/app/shared/components/available-profiles/available-profiles.component.ts b/dmp-frontend/src/app/shared/components/available-profiles/available-profiles.component.ts deleted file mode 100644 index dc4323133..000000000 --- a/dmp-frontend/src/app/shared/components/available-profiles/available-profiles.component.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Component, Inject, OnInit } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; -import { ActivatedRoute, Router } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { DatasetProfileModel } from '../../../models/datasetprofile/DatasetProfileModel'; -import { DatasetService } from '../../../services/dataset/dataset.service'; -import { JsonSerializer } from '../../../utilities/JsonSerializer'; - -@Component({ - selector: 'app-available-profiles-component', - templateUrl: 'available-profiles.component.html', -}) -export class AvailableProfilesComponent extends BaseComponent implements OnInit { - - public formGroup: FormGroup; - public profiles: DatasetProfileModel[] = []; - public selectedProfiles: DatasetProfileModel[] = []; - public selectedOptions: any; - constructor( - private datasetService: DatasetService, - private route: ActivatedRoute, - public router: Router, - public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any - ) { super(); } - - ngOnInit(): void { - this.formGroup = this.data['profiles']; - this.datasetService.getDatasetProfiles() - .pipe(takeUntil(this._destroyed)) - .subscribe(data => { - this.profiles = JsonSerializer.fromJSONArray(data, DatasetProfileModel); - }); - } - - addProfiles(profiles) { - profiles.selectedOptions.selected.forEach(element => { - const selectedElement = new DatasetProfileModel(); - selectedElement.id = element.value.id; - selectedElement.label = element.value.label; - this.selectedProfiles.push(selectedElement); - }); - this.formGroup.setValue(this.selectedProfiles); - this.dialogRef.close(); - } - - isOptionSelected(profile: any) { - return this.formGroup.value.map(x => x.id).indexOf(profile.id) !== -1; - } -} diff --git a/dmp-frontend/src/app/shared/components/breadcrumb/breadcrumb.component.html b/dmp-frontend/src/app/shared/components/breadcrumb/breadcrumb.component.html deleted file mode 100644 index f87968072..000000000 --- a/dmp-frontend/src/app/shared/components/breadcrumb/breadcrumb.component.html +++ /dev/null @@ -1,12 +0,0 @@ -
    -
    -
    -
  1. - - {{ breadcrumb.label }} - -
  2. - chevron_right -
    -
    -
diff --git a/dmp-frontend/src/app/shared/components/breadcrumb/breadcrumb.component.scss b/dmp-frontend/src/app/shared/components/breadcrumb/breadcrumb.component.scss deleted file mode 100644 index 665f22abb..000000000 --- a/dmp-frontend/src/app/shared/components/breadcrumb/breadcrumb.component.scss +++ /dev/null @@ -1,8 +0,0 @@ -ol.no-style { - li { - list-style-type: none; - } - margin-bottom: 0px; - margin-top: 20px; - padding-left: 0px -} diff --git a/dmp-frontend/src/app/shared/components/breadcrumb/breadcrumb.component.ts b/dmp-frontend/src/app/shared/components/breadcrumb/breadcrumb.component.ts deleted file mode 100644 index 91988f62a..000000000 --- a/dmp-frontend/src/app/shared/components/breadcrumb/breadcrumb.component.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Component, OnInit, ViewEncapsulation } from '@angular/core'; -import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; -import { BreadCrumbResolverService } from '../../../services/breadcrumb/breadcrumb-resolver.service'; -import { BreadcrumbItem } from './definition/breadcrumb-item'; -import { Observable } from 'rxjs'; - -@Component({ - selector: 'app-breadcrumb', - templateUrl: './breadcrumb.component.html', - styleUrls: ['./breadcrumb.component.scss'], - encapsulation: ViewEncapsulation.None -}) -export class BreadcrumbComponent implements OnInit { - breadcrumbs$ = this.router.events - .filter(event => event instanceof NavigationEnd) - .distinctUntilChanged() - .flatMap(event => this.buildBreadCrumb(this.activatedRoute.root)); - - - constructor( - public activatedRoute: ActivatedRoute, - private router: Router, - private breadCrumbService: BreadCrumbResolverService - ) { - - } - - ngOnInit() { - - } - - buildBreadCrumb(route: ActivatedRoute): Observable { - if (this.breadCrumbService.resolve(route)) { return this.breadCrumbService.resolve(route).map(x => { x.unshift({ label: 'Dashboard', url: '/welcome' }); return x; }); } - return Observable.of([]); - } - - navigate(url, params) { - this.router.navigate([url, params]); - } -} diff --git a/dmp-frontend/src/app/shared/components/breadcrumb/definition/breadcrumb-item.ts b/dmp-frontend/src/app/shared/components/breadcrumb/definition/breadcrumb-item.ts deleted file mode 100644 index e87bcdd82..000000000 --- a/dmp-frontend/src/app/shared/components/breadcrumb/definition/breadcrumb-item.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Observable } from 'rxjs'; - -export class BreadcrumbItem { - parentComponentName?: string; - label: string; - url: string; - params?: any = {}; - notFoundResolver?: any[]; -} diff --git a/dmp-frontend/src/app/shared/components/criteria/base/base-criteria.component.ts b/dmp-frontend/src/app/shared/components/criteria/base/base-criteria.component.ts deleted file mode 100644 index f64519bc6..000000000 --- a/dmp-frontend/src/app/shared/components/criteria/base/base-criteria.component.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; -import { BaseComponent } from '../../../../core/common/base/base.component'; -import { BaseCriteriaErrorModel } from '../../../../models/criteria/BaseCriteriaErrorModel'; - -@Component({ - selector: 'app-base-criteria-component', - template: '', - providers: [ - - ] -}) - -export class BaseCriteriaComponent extends BaseComponent implements OnInit { - - public refreshCallback: Function = null; - public formGroup: FormGroup = null; - - constructor( - public baseErrorModel?: BaseCriteriaErrorModel, - ) { - super(); - } - - ngOnInit() { - if (this.baseErrorModel == null) { this.baseErrorModel = new BaseCriteriaErrorModel(); } - } - - controlModified(): void { - this.clearErrorModel(); - if (!this.isFormValid()) { return; } - if (this.refreshCallback != null) { this.refreshCallback(); } - } - - public isFormValid(): boolean { - this.touchAllFormFields(this.formGroup); - this.validateAllFormFields(this.formGroup); - return this.formGroup.valid; - } - - public getFormData(): any { - return this.formGroup.value; - } - - public getFormControl(controlName: string): AbstractControl { - return this.formGroup.get(controlName); - } - - public disableFormFields(formControl: AbstractControl) { - formControl.disable(); - } - - public validateAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.updateValueAndValidity({ emitEvent: false }); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.validateAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.validateAllFormFields(item); - }); - } - } - - public touchAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.markAsTouched(); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.touchAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.touchAllFormFields(item); - }); - } - } - - setRefreshCallback(callback: Function): void { - this.refreshCallback = callback; - } - - onCallbackError(error: any) { - this.setErrorModel(error.error); - this.validateAllFormFields(this.formGroup); - } - - public setErrorModel(errorModel: BaseCriteriaErrorModel) { - Object.keys(errorModel).forEach(item => { - (this.baseErrorModel)[item] = (errorModel)[item]; - }); - } - - public clearErrorModel() { - Object.keys(this.baseErrorModel).forEach(item => { - (this.baseErrorModel)[item] = ''; - }); - } - -} diff --git a/dmp-frontend/src/app/shared/components/criteria/data-management-plan/dmp-criteria.component.html b/dmp-frontend/src/app/shared/components/criteria/data-management-plan/dmp-criteria.component.html deleted file mode 100644 index cdc0b7a6b..000000000 --- a/dmp-frontend/src/app/shared/components/criteria/data-management-plan/dmp-criteria.component.html +++ /dev/null @@ -1,23 +0,0 @@ -
- - - -

{{'CRITERIA.FILTERS'| translate}}

-
-
-
-
- - - {{baseErrorModel['Criteria.like']}} - -
-
- - -
-
-
-
diff --git a/dmp-frontend/src/app/shared/components/criteria/data-management-plan/dmp-criteria.component.ts b/dmp-frontend/src/app/shared/components/criteria/data-management-plan/dmp-criteria.component.ts deleted file mode 100644 index 83fde5356..000000000 --- a/dmp-frontend/src/app/shared/components/criteria/data-management-plan/dmp-criteria.component.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { FormBuilder, FormControl } from '@angular/forms'; -import { TranslateService } from '@ngx-translate/core'; -import { takeUntil } from 'rxjs/operators'; -import { DataManagementPlanCriteria } from '../../../../models/criteria/data-management-plan/DataManagementPlanCriteria'; -import { DataManagementPlanCriteriaErrorModel } from '../../../../models/criteria/data-management-plan/DataManagementPlanCriteriaErrorModel'; -import { ProjectCriteria } from '../../../../models/criteria/project/ProjectCriteria'; -import { RequestItem } from '../../../../models/criteria/RequestItem'; -import { ProjectModel } from '../../../../models/projects/ProjectModel'; -import { ProjectService } from '../../../../services/project/project.service'; -import { MultipleAutoCompleteConfiguration } from '../../autocompletes/multiple/multiple-auto-complete-configuration'; -import { BaseCriteriaComponent } from '../base/base-criteria.component'; - -@Component({ - selector: 'app-dmp-criteria-component', - templateUrl: './dmp-criteria.component.html', - styleUrls: ['./dmp-criteria.component.scss'], -}) - -export class DataManagementPlanCriteriaComponent extends BaseCriteriaComponent implements OnInit { - - @Input() - showProject: boolean; - filteringProjectsAsync = false; - filteredProjects: ProjectModel[]; - projectAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; - public formGroup = new FormBuilder().group({ - like: new FormControl(), - projects: new FormControl() - }); - - constructor( - public language: TranslateService, - public projectService: ProjectService, - public formBuilder: FormBuilder - ) { - super(new DataManagementPlanCriteriaErrorModel()); - } - - ngOnInit() { - super.ngOnInit(); - - this.projectAutoCompleteConfiguration = { - filterFn: this.filterProject.bind(this), - initialItems: (excludedItems: any[]) => this.filterProject('').map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1)), - displayFn: (item) => item['label'], - titleFn: (item) => item['label'], - //mapFn: (item) => new JsonSerializer().fromJSONArray(item, ProjectReference).map(item => item.toDropdownList()), - loadDataOnStart: true - }; - - this.formGroup.get('projects').valueChanges - .pipe(takeUntil(this._destroyed)) - .subscribe(x => this.controlModified()); - this.formGroup.get('like').valueChanges - .pipe(takeUntil(this._destroyed)) - .subscribe(x => this.controlModified()); - //if (this.criteria == null) { this.criteria = new DataManagementPlanCriteria(); } - } - - setCriteria(criteria: DataManagementPlanCriteria): void { - this.formGroup.get('like').patchValue(criteria.like); - this.formGroup.get('projects').patchValue(criteria.projects); - } - - onCallbackError(error: any) { - this.setErrorModel(error.error); - } - - controlModified(): void { - this.clearErrorModel(); - if (this.refreshCallback != null && - (this.formGroup.get('like').value == null || this.formGroup.get('like').value.length === 0 || this.formGroup.get('like').value.length > 2) - ) { - this.refreshCallback(); - } - } - - filterProject(query: string) { - const projectRequestItem: RequestItem = new RequestItem(); - projectRequestItem.criteria = new ProjectCriteria(); - projectRequestItem.criteria.like = query; - return this.projectService.get(projectRequestItem); - } -} diff --git a/dmp-frontend/src/app/shared/components/criteria/datamanagementplanprofile/dmp-profile-criteria.component.html b/dmp-frontend/src/app/shared/components/criteria/datamanagementplanprofile/dmp-profile-criteria.component.html deleted file mode 100644 index d1f2e79a7..000000000 --- a/dmp-frontend/src/app/shared/components/criteria/datamanagementplanprofile/dmp-profile-criteria.component.html +++ /dev/null @@ -1,13 +0,0 @@ -
- -
-
- - - {{baseErrorModel['Criteria.like']}} - -
-
-
-
diff --git a/dmp-frontend/src/app/shared/components/criteria/datamanagementplanprofile/dmp-profile-criteria.component.ts b/dmp-frontend/src/app/shared/components/criteria/datamanagementplanprofile/dmp-profile-criteria.component.ts deleted file mode 100644 index 195ed8fe3..000000000 --- a/dmp-frontend/src/app/shared/components/criteria/datamanagementplanprofile/dmp-profile-criteria.component.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { TranslateService } from '@ngx-translate/core'; -import { Component, OnInit, Input } from '@angular/core'; -import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms'; -import { BaseCriteriaComponent } from '../base/base-criteria.component'; -import { ValidationContext, Validation } from '../../../../utilities/validators/ValidationContext'; -import { BackendErrorValidator } from '../../../../utilities/validators/BackendErrorValidator'; -import { DataManagementPlanCriteria } from '../../../../models/criteria/data-management-plan/DataManagementPlanCriteria'; -import { DataManagementPlanCriteriaErrorModel } from '../../../../models/criteria/data-management-plan/DataManagementPlanCriteriaErrorModel'; -import { ProjectModel } from '../../../../models/projects/ProjectModel'; -import { ProjectCriteria } from '../../../../models/criteria/project/ProjectCriteria'; -import { RequestItem } from '../../../../models/criteria/RequestItem'; -import { create } from 'domain'; -import { DataManagementPlanProfileCriteria } from '../../../../models/criteria/dmp-profile/DataManagementPlanProfileCriteria'; -import { DataManagementPlanProfileCriteriaErrorModel } from '../../../../models/criteria/dmp-profile/DataManagementPlanProfileCriteriaErrorModel'; - -@Component({ - selector: 'app-dmp-profile-criteria-component', - templateUrl: './dmp-profile-criteria.component.html', - styleUrls: ['./dmp-profile-criteria.component.scss'], -}) - -export class DataManagementPlanProfileCriteriaComponent extends BaseCriteriaComponent implements OnInit { - - @Input() - showProject: boolean; - public criteria: DataManagementPlanProfileCriteria = new DataManagementPlanProfileCriteria(); - filteringProjectsAsync = false; - filteredProjects: ProjectModel[]; - - constructor( - public language: TranslateService, - public formBuilder: FormBuilder - ) { - super(new DataManagementPlanProfileCriteriaErrorModel()); - } - - ngOnInit() { - super.ngOnInit(); - if (this.criteria == null) { this.criteria = new DataManagementPlanCriteria(); } - } - - setCriteria(criteria: DataManagementPlanProfileCriteria): void { - this.criteria = criteria; - } - - onCallbackError(error: any) { - this.setErrorModel(error.error); - } - - controlModified(): void { - this.clearErrorModel(); - if (this.refreshCallback != null && - (this.criteria.like == null || this.criteria.like.length === 0 || this.criteria.like.length > 2) - ) { - this.refreshCallback(); - } - } -} diff --git a/dmp-frontend/src/app/shared/components/criteria/dataset-profile/dataset-profile.component.ts b/dmp-frontend/src/app/shared/components/criteria/dataset-profile/dataset-profile.component.ts deleted file mode 100644 index 7f16e7c15..000000000 --- a/dmp-frontend/src/app/shared/components/criteria/dataset-profile/dataset-profile.component.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { TranslateService } from '@ngx-translate/core'; -import { Component, OnInit, Input } from '@angular/core'; -import { BaseCriteriaComponent } from '../base/base-criteria.component'; -import { DatasetProfileCriteria } from '../../../../models/criteria/dataset-profile/DatasetProfileCriteria'; -import { FormBuilder } from '@angular/forms'; - -@Component({ - selector: 'app-dataset-profile-criteria-component', - templateUrl: './dataset-profile.component.html', - styleUrls: ['./dataset-profile.component.scss'], -}) - -export class DatasetProfileCriteriaComponent extends BaseCriteriaComponent implements OnInit { - - public criteria: DatasetProfileCriteria = new DatasetProfileCriteria(); - - constructor( - public language: TranslateService, - public formBuilder: FormBuilder - ) { - super(new DatasetProfileCriteria()); - } - - ngOnInit() { - super.ngOnInit(); - if (this.criteria == null) { this.criteria = new DatasetProfileCriteria(); } - } - - setCriteria(criteria: DatasetProfileCriteria): void { - this.criteria = criteria; - } - - onCallbackError(error: any) { - this.setErrorModel(error.error); - } - - controlModified(): void { - this.clearErrorModel(); - if (this.refreshCallback != null && - (this.criteria.like == null || this.criteria.like.length === 0 || this.criteria.like.length > 2) - ) { - this.refreshCallback(); - } - } -} diff --git a/dmp-frontend/src/app/shared/components/criteria/datasets/datasets-criteria.component.html b/dmp-frontend/src/app/shared/components/criteria/datasets/datasets-criteria.component.html deleted file mode 100644 index 40a651b9a..000000000 --- a/dmp-frontend/src/app/shared/components/criteria/datasets/datasets-criteria.component.html +++ /dev/null @@ -1,45 +0,0 @@ -
- - - -

{{'CRITERIA.FILTERS'| translate}}

-
-
-
-
- - - {{baseErrorModel['Criteria.like']}} - -
-
- - - - {{status.viewValue}} - - - {{baseErrorModel['Criteria.status']}} - -
-
- - -
{{chip.name.substring(0, 1).toUpperCase()}}
- {{chip.name}} -
- -
- {{option.name}} -
-
- -
-
-
-
-
diff --git a/dmp-frontend/src/app/shared/components/criteria/datasets/datasets-criteria.component.ts b/dmp-frontend/src/app/shared/components/criteria/datasets/datasets-criteria.component.ts deleted file mode 100644 index b3bb34251..000000000 --- a/dmp-frontend/src/app/shared/components/criteria/datasets/datasets-criteria.component.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { FormBuilder } from '@angular/forms'; -import { TranslateService } from '@ngx-translate/core'; -import { takeUntil } from 'rxjs/operators'; -import { DatasetCriteria } from '../../../../models/criteria/dataset/DatasetCriteria'; -import { DatasetCriteriaErrorModel } from '../../../../models/criteria/dataset/DatasetCriteriaErrorModel'; -import { RequestItem } from '../../../../models/criteria/RequestItem'; -import { TagsCriteria } from '../../../../models/criteria/tags/TagsCriteria'; -import { ExternalSourcesItemModel } from '../../../../models/external-sources/ExternalSourcesItemModel'; -import { ExternalSourcesService } from '../../../../services/external-sources/external-sources.service'; -import { BaseCriteriaComponent } from '../base/base-criteria.component'; - -@Component({ - selector: 'app-datasets-criteria-component', - templateUrl: './datasets-criteria.component.html', - styleUrls: ['./datasets-criteria.component.scss'], - providers: [ - ExternalSourcesService - ] -}) - -export class DatasetCriteriaComponent extends BaseCriteriaComponent implements OnInit { - - public criteria: any; - public filteringTagsAsync = false; - public filteredTags: ExternalSourcesItemModel[]; - - statuses = [ - { value: '0', viewValue: 'Draft' }, - { value: '1', viewValue: 'Finalised' } - ]; - - constructor( - public language: TranslateService, - public formBuilder: FormBuilder, - public externalSourcesService: ExternalSourcesService - ) { - super(new DatasetCriteriaErrorModel()); - } - - ngOnInit() { - super.ngOnInit(); - if (this.criteria == null) { this.criteria = {}; } - } - - setCriteria(criteria: DatasetCriteria): void { - this.criteria = criteria; - } - - onCallbackError(error: any) { - this.setErrorModel(error.error); - } - - controlModified(): void { - this.clearErrorModel(); - if (this.refreshCallback != null && - (this.criteria.like == null || this.criteria.like.length === 0 || this.criteria.like.length > 2) - ) { - this.refreshCallback(); - } - } - - filterTags(value: string): void { - - this.filteredTags = undefined; - if (value) { - this.filteringTagsAsync = true; - - const requestItem: RequestItem = new RequestItem(); - const criteria: TagsCriteria = new TagsCriteria(); - criteria.like = value; - requestItem.criteria = criteria; - this.externalSourcesService.searchDatasetTags(requestItem) - .pipe(takeUntil(this._destroyed)) - .subscribe(items => { - this.filteredTags = items; - this.filteringTagsAsync = false; - }); - } - } -} diff --git a/dmp-frontend/src/app/shared/components/criteria/projects/projects-criteria.component.html b/dmp-frontend/src/app/shared/components/criteria/projects/projects-criteria.component.html deleted file mode 100644 index 81ee7d21b..000000000 --- a/dmp-frontend/src/app/shared/components/criteria/projects/projects-criteria.component.html +++ /dev/null @@ -1,37 +0,0 @@ -
- - - - {{baseErrorModel['criteria.like']}} - - - - - - - {{baseErrorModel['criteria.periodStart']}} - - - - {{baseErrorModel['criteria.periodEnd']}} - - - - - - - - {{ 'CRITERIA.PROJECTS.TYPES.ON-GOING' | translate}} - - - {{ 'CRITERIA.PROJECTS.TYPES.FINISHED' | translate}} - - - -
diff --git a/dmp-frontend/src/app/shared/components/criteria/projects/projects-criteria.component.ts b/dmp-frontend/src/app/shared/components/criteria/projects/projects-criteria.component.ts deleted file mode 100644 index df5a08b52..000000000 --- a/dmp-frontend/src/app/shared/components/criteria/projects/projects-criteria.component.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { TranslateService } from '@ngx-translate/core'; -import { Component, OnInit } from '@angular/core'; -import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms'; -import { BaseCriteriaComponent } from '../base/base-criteria.component'; -import { ValidationContext, Validation } from '../../../../utilities/validators/ValidationContext'; -import { BackendErrorValidator } from '../../../../utilities/validators/BackendErrorValidator'; -import { ProjectCriteria } from '../../../../models/criteria/project/ProjectCriteria'; -import { ProjectCriteriaErrorModel } from '../../../../models/criteria/project/ProjectCriteriaErrorModel'; -import { LanguageResolverService } from '../../../../services/language-resolver/language-resolver.service'; -import { ProjectStateType } from '../../../../models/projects/ProjectStateType'; - -@Component({ - selector: 'app-projects-criteria-component', - templateUrl: './projects-criteria.component.html', - styleUrls: ['./projects-criteria.component.scss'], - providers: [ - ] -}) - -export class ProjectCriteriaComponent extends BaseCriteriaComponent implements OnInit { - - // public form: ProjectType; - public ProjectStateType = ProjectStateType; - public criteria: ProjectCriteria = new ProjectCriteria(); - - constructor( - public language: TranslateService, - public formBuilder: FormBuilder, - public languageResolver: LanguageResolverService - ) { - super(new ProjectCriteriaErrorModel()); - } - - ngOnInit() { - super.ngOnInit(); - if (this.criteria == null) { this.criteria = new ProjectCriteria(); } - } - - setCriteria(criteria: ProjectCriteria): void { - this.criteria = criteria; - } - - onCallbackError(error: any) { - this.setErrorModel(error.error); - } - - controlModified(): void { - this.clearErrorModel(); - if (this.refreshCallback != null && - (this.criteria.like == null || this.criteria.like.length === 0 || this.criteria.like.length > 2) - ) { - this.refreshCallback(); - } - } -} diff --git a/dmp-frontend/src/app/shared/components/criteria/users/users-criteria.component.html b/dmp-frontend/src/app/shared/components/criteria/users/users-criteria.component.html deleted file mode 100644 index 7e8ab3fbc..000000000 --- a/dmp-frontend/src/app/shared/components/criteria/users/users-criteria.component.html +++ /dev/null @@ -1,19 +0,0 @@ -
- -
-
- - - -
-
- - - {{getPrincipalAppRoleWithLanguage(role)}} - - -
-
-
-
diff --git a/dmp-frontend/src/app/shared/components/criteria/users/users-criteria.component.scss b/dmp-frontend/src/app/shared/components/criteria/users/users-criteria.component.scss deleted file mode 100644 index 02b2ce834..000000000 --- a/dmp-frontend/src/app/shared/components/criteria/users/users-criteria.component.scss +++ /dev/null @@ -1,10 +0,0 @@ -.user-roles-criteria { - mat-form-field { - padding-bottom: 5px; - width: 100%; - } - - mat-card { - padding-bottom: 0px; - } -} diff --git a/dmp-frontend/src/app/shared/components/criteria/users/users-criteria.component.ts b/dmp-frontend/src/app/shared/components/criteria/users/users-criteria.component.ts deleted file mode 100644 index 2cc88834a..000000000 --- a/dmp-frontend/src/app/shared/components/criteria/users/users-criteria.component.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { FormBuilder, FormGroup } from '@angular/forms'; -import { TranslateService } from '@ngx-translate/core'; -import { takeUntil } from 'rxjs/operators'; -import { UserCriteria } from '../../../../models/criteria/users/UserCriteria'; -import { UserCriteriaErrorModel } from '../../../../models/criteria/users/UserCriteriaErrorModel'; -import { Principal } from '../../../../models/login/Principal'; -import { Utilities } from '../../../../utilities/utilities'; -import { Validation, ValidationContext } from '../../../../utilities/validators/ValidationContext'; -import { BaseCriteriaComponent } from '../base/base-criteria.component'; - -@Component({ - selector: 'app-users-criteria-component', - templateUrl: './users-criteria.component.html', - styleUrls: ['./users-criteria.component.scss'], - providers: [Utilities] -}) - -export class UsersCriteriaComponent extends BaseCriteriaComponent implements OnInit { - - public role: Principal.AppRole; - public criteria: UserCriteria = new UserCriteria(); - - constructor( - public language: TranslateService, - public formBuilder: FormBuilder, - public utilities: Utilities - ) { - super(new UserCriteriaErrorModel()); - } - - ngOnInit() { - super.ngOnInit(); - if (this.criteria == null) { this.criteria = new UserCriteria(); } - if (this.formGroup == null) { this.formGroup = this.buildForm(); } - } - - setCriteria(criteria: UserCriteria): void { - this.criteria = criteria; - this.formGroup = this.buildForm(); - } - - public fromJSONObject(item: any): UserCriteria { - this.criteria = new UserCriteria(); - this.criteria.label = item.Label; - this.criteria.appRoles = item.appRoles; - return this.criteria; - } - - buildForm(): FormGroup { - const context: ValidationContext = this.createValidationContext(); - - return this.formBuilder.group({ - like: [this.criteria.label, context.getValidation('label').validators], - appRoles: [this.criteria.appRoles, context.getValidation('appRoles').validators], - }); - } - - createValidationContext(): ValidationContext { - const validationContext: ValidationContext = new ValidationContext(); - const validationArray: Validation[] = new Array(); - - validationArray.push({ key: 'label' }); - validationArray.push({ key: 'appRoles' }); - - validationContext.validation = validationArray; - return validationContext; - } - - getPrincipalAppRoleValues(): Number[] { - let keys: string[] = Object.keys(Principal.AppRole); - keys = keys.slice(0, keys.length / 2); - const values: Number[] = keys.map(Number); - return values; - } - - getPrincipalAppRoleWithLanguage(role: Principal.AppRole): string { - let result = ''; - this.language.get(this.utilities.convertFromPrincipalAppRole(role)) - .pipe(takeUntil(this._destroyed)) - .subscribe((value: string) => { - result = value; - }); - return result; - } - -} diff --git a/dmp-frontend/src/app/shared/components/external-items/external-item-listing/external-item-listing.component.html b/dmp-frontend/src/app/shared/components/external-items/external-item-listing/external-item-listing.component.html deleted file mode 100644 index 42d1e71f2..000000000 --- a/dmp-frontend/src/app/shared/components/external-items/external-item-listing/external-item-listing.component.html +++ /dev/null @@ -1,15 +0,0 @@ -
- - - - {{ option.label }} - - - - - -
-
- - -
diff --git a/dmp-frontend/src/app/shared/components/external-items/external-item-listing/external-item-listing.component.ts b/dmp-frontend/src/app/shared/components/external-items/external-item-listing/external-item-listing.component.ts deleted file mode 100644 index 684724a9b..000000000 --- a/dmp-frontend/src/app/shared/components/external-items/external-item-listing/external-item-listing.component.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { Component, OnInit, Input, ContentChild, TemplateRef, ViewChild, Output, EventEmitter } from '@angular/core'; -import { FormGroup, FormControl, FormArray, AbstractControl } from '@angular/forms'; -import { ExternalSourcesUrlModel } from '../../../../models/external-sources/ExternalSourcesUrlModel'; -import { AutoCompleteConfiguration } from '../../auto-complete/AutoCompleteConfiguration'; - -@Component({ - selector: 'app-external-item-listing', - templateUrl: './external-item-listing.component.html', - styleUrls: ['./external-item-listing.component.scss'] -}) -export class ExternalItemListingComponent implements OnInit { - @Input() - public placeholder: string; - - @Input() - public formGroup: AbstractControl; - - @Input() - public autoCompleteConfiguration: AutoCompleteConfiguration; - - @Input() - public displayFunction: Function; - - @Input() - public subtitleFunction: Function; - - @Input() - public disabled = true; - - @Input() - public viewOnly = false; - - @Input() - public titleKey: string; - - @Input() - parentTemplate; - - @Input() - public options: Array; - - @Output() - public onItemChange = new EventEmitter(); - - public choice: string; - public formControl = new FormControl(); - enabled = true; - - ngOnInit() { - if (this.disabled) { this.formControl.disable(); } - } - - onItemChangeFunc(event) { - if (event) { this.onItemChange.emit(event); } - } - - selectionChange(event) { - if (this.formControl.disabled) { this.formControl.enable(); } - this.autoCompleteConfiguration.requestItem.criteria['type'] = event.value; - this.autoCompleteConfiguration.refreshEvent.next(true); - } - - deleteItem(name: number) { - (this.formGroup).removeAt(name); - } -} - diff --git a/dmp-frontend/src/app/shared/components/external-items/external-item/external-item.component.html b/dmp-frontend/src/app/shared/components/external-items/external-item/external-item.component.html deleted file mode 100644 index 13cf4f779..000000000 --- a/dmp-frontend/src/app/shared/components/external-items/external-item/external-item.component.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/dmp-frontend/src/app/shared/components/external-items/external-item/external-item.component.ts b/dmp-frontend/src/app/shared/components/external-items/external-item/external-item.component.ts deleted file mode 100644 index c69ba080a..000000000 --- a/dmp-frontend/src/app/shared/components/external-items/external-item/external-item.component.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; -import { Placeholder } from '@angular/compiler/src/i18n/i18n_ast'; -import { FormGroup, FormControl } from '@angular/forms'; -import { AutoCompleteConfiguration } from '../../auto-complete/AutoCompleteConfiguration'; - -@Component({ - selector: 'app-external-item', - templateUrl: './external-item.component.html', - styleUrls: ['./external-item.component.scss'] -}) -export class ExternalItemComponent implements OnInit { - - @Input() - public placeholder: string; - - @Input() - public formGroup: FormGroup; - - @Input() - public autoCompleteConfiguration: AutoCompleteConfiguration; - - @Input() - public displayFunction: Function; - - @Input() - public subtitleFunction: Function; - - @Input() - public disabled = false; - - @Input() - public titleKey: string; - - @Output() - public onItemChange = new EventEmitter(); - - @Input() - public formCtrl: FormControl; - - ngOnInit() { - } - - onItemChangeFunc(event) { - this.onItemChange.emit(event); - } -} diff --git a/dmp-frontend/src/app/shared/components/facets/facet-search-component/facet-search-section.component.ts b/dmp-frontend/src/app/shared/components/facets/facet-search-component/facet-search-section.component.ts deleted file mode 100644 index 8e3aa96e5..000000000 --- a/dmp-frontend/src/app/shared/components/facets/facet-search-component/facet-search-section.component.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { SelectionModel } from '@angular/cdk/collections'; -import { Component, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core'; -import { FormControl } from '@angular/forms'; -import { MatListOption, MatSelectionList } from '@angular/material'; -import { Observable } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../../core/common/base/base.component'; - -@Component({ - selector: 'app-facet-section-component', - templateUrl: './facet-search-section.component.html', - styleUrls: ['./facet-search-section.component.scss'], - encapsulation: ViewEncapsulation.None, -}) -export class FacetSearchSectionComponent extends BaseComponent implements OnInit { - - @Input() - searchEnabled = false; - - @Input() - requestDelay = 200; - - @Input() - multipleSelect = true; - - @Input() - filterOptions: (value) => Observable; - - @Input() - options: Observable = Observable.of([]); - - @Input() - displayTitleFunc: (value) => string; - - @Input() - displayValueFunc: (value) => string; - - @Output() - selectedChanged = new EventEmitter(); - - @Output() - optionRemoved = new EventEmitter(); - - optionSearchControl = new FormControl(''); - - private selectedOptions: any[] = []; - - @ViewChild('optionsList') selectionList: MatSelectionList; - - - ngOnInit(): void { - if (!this.multipleSelect) { this.selectionList.selectedOptions = new SelectionModel(this.multipleSelect); } - this.optionSearchControl.valueChanges.debounceTime(this.requestDelay) - .distinctUntilChanged() - .pipe(takeUntil(this._destroyed)) - .subscribe(x => { if (this.filterOptions) { this.options = this.filterOptions(x); } }); - } - - public selectionChanged(event: any) { - const eventValue = event.option.value; - if (event.option.selected) { this.selectedOptions.push(eventValue); } - if (!event.option.selected) { - const index = this.selectedOptions.map(x => this.displayValue(x)).indexOf(this.displayValue(eventValue)); - this.selectedOptions.splice(index, 1); - } - this.selectedChanged.emit(event); - } - - public removeOption(project) { - const list = this.selectionList.selectedOptions.selected.map(x => x.value); - const indexOfProject = list.indexOf(project); - if (this.selectionList.selectedOptions.selected[indexOfProject]) { - this.selectionList.selectedOptions.selected[indexOfProject].selected = false; - this.selectionList.selectedOptions.selected.splice(indexOfProject, 1); - } - this.selectedOptions.splice(this.selectedOptions.map(x => this.displayValue(x)).indexOf(this.displayValue(project)), 1); - this.optionRemoved.emit(project); - } - - public isOptionSelected(value) { - return this.selectedOptions.map(x => this.displayValue(x)).indexOf(this.displayValue(value)) !== -1; - } - - displayLabel(value) { - return this.displayTitleFunc ? this.displayTitleFunc(value) : value; - } - - displayValue(value) { - return this.displayValueFunc ? this.displayValueFunc(value) : value; - } - -} diff --git a/dmp-frontend/src/app/shared/components/facets/facet-search.component.html b/dmp-frontend/src/app/shared/components/facets/facet-search.component.html deleted file mode 100644 index 89b457891..000000000 --- a/dmp-frontend/src/app/shared/components/facets/facet-search.component.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - {{ 'FACET-SEARCH.FILTER' | translate }} - - -
- - - -
-
- - -
{{chip.name.substring(0, 1).toUpperCase()}}
- {{chip.name}} -
- -
- {{option.name}} -
-
- -
-
-
- - - - {{ 'FACET-SEARCH.PROJECT-STATUS.TITLE' | translate }} - - - - - - - - - - {{ 'FACET-SEARCH.PROJECT.TITLE' | translate }} - - - - - - - - - - {{ 'FACET-SEARCH.PROFILES.TITLE' | translate }} - - - - - - - - - {{ 'FACET-SEARCH.DMP-ORGANISATIONS.TITLE' | translate }} - - - - - - -
diff --git a/dmp-frontend/src/app/shared/components/facets/facet-search.component.ts b/dmp-frontend/src/app/shared/components/facets/facet-search.component.ts deleted file mode 100644 index bd3bd7b38..000000000 --- a/dmp-frontend/src/app/shared/components/facets/facet-search.component.ts +++ /dev/null @@ -1,180 +0,0 @@ -import { AfterViewInit, Component, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core'; -import { MatAccordion } from '@angular/material'; -import { ActivatedRoute } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { ProjectCriteria } from '../../../models/criteria/project/ProjectCriteria'; -import { RequestItem } from '../../../models/criteria/RequestItem'; -import { TagsCriteria } from '../../../models/criteria/tags/TagsCriteria'; -import { DatasetProfileModel } from '../../../models/datasetprofile/DatasetProfileModel'; -import { ExternalSourcesItemModel } from '../../../models/external-sources/ExternalSourcesItemModel'; -import { FacetSearchCriteriaModel } from '../../../models/facet-search/FacetSearchCriteriaModel'; -import { ProjectModel } from '../../../models/projects/ProjectModel'; -import { ProjectStateType } from '../../../models/projects/ProjectStateType'; -import { DatasetService } from '../../../services/dataset/dataset.service'; -import { ExternalSourcesService } from '../../../services/external-sources/external-sources.service'; -import { ProjectService } from '../../../services/project/project.service'; - -@Component({ - selector: 'app-facet', - templateUrl: './facet-search.component.html', - styleUrls: ['./facet-search.component.scss'], - encapsulation: ViewEncapsulation.None, - providers: [ProjectService] -}) -export class FacetSearchComponent extends BaseComponent implements OnInit, AfterViewInit { - - @Input() facetCriteria = new FacetSearchCriteriaModel(); - @Output() facetCriteriaChange = new EventEmitter(); - public filteringTagsAsync = false; - public filteredTags: ExternalSourcesItemModel[]; - ProjectStateType = ProjectStateType; - projects: Observable; - profiles: Observable; - dmpOrganisations: Observable; - projectOptions: Observable; - projectStateOptions: Observable; - @ViewChild('facetAccordion') accordion: MatAccordion; - - displayProjectStateValue = (option) => option['value']; - displayProjectStateLabel = (option) => option['label']; - - displayProjectValue = (option) => option['id']; - displayProjectLabel = (option) => option['label']; - - displayProfileValue = (option) => option['id']; - displayProfileLabel = (option) => option['label']; - - displayDmpOrganisationsValue = (option) => option['id']; - displayDmpOrganisationsLabel = (option) => option['name']; - - constructor( - public activatedRoute: ActivatedRoute, - public projectService: ProjectService, - public languageService: TranslateService, - public datasetProfileService: DatasetService, - public externalSourcesService: ExternalSourcesService - ) { super(); } - - ngOnInit() { - setTimeout(x => { - this.projectStateOptions = Observable.of( - [ - { label: this.languageService.instant('FACET-SEARCH.PROJECT-STATUS.OPTIONS.INACTIVE'), value: ProjectStateType.Finished }, - { label: this.languageService.instant('FACET-SEARCH.PROJECT-STATUS.OPTIONS.ACTIVE'), value: ProjectStateType.OnGoing }, - ]); - }); - this.profiles = this.datasetProfileService.getDatasetProfiles(); - this.dmpOrganisations = this.externalSourcesService.searchDMPOrganizations(''); - } - - ngAfterViewInit(): void { - this.accordion.openAll(); - } - - public projectStatusChanged(event) { - this.facetCriteria.projectStatus = event.option.value.value; - if (!event.option.selected) { - this.facetCriteria.projectStatus = null; - this.projects = Observable.of([]); - this.facetCriteria.projects = []; - } - if (event.option.selected) { - const projectCriteria = new ProjectCriteria(); - projectCriteria.projectStateType = this.facetCriteria.projectStatus; - projectCriteria['length'] = 10; - const dataTableRequest: RequestItem = { criteria: projectCriteria }; - this.projects = this.projectService.get(dataTableRequest); - this.facetCriteria.projects = []; - } - this.facetCriteriaChange.emit(this.facetCriteria); - } - - public projectChanged(event: any) { - const eventValue = event.option.value.id; - if (event.option.selected) { this.facetCriteria.projects.push(eventValue); } - if (!event.option.selected) { - const index = this.facetCriteria.projects.indexOf(eventValue); - this.facetCriteria.projects.splice(index, 1); - } - this.facetCriteriaChange.emit(this.facetCriteria); - } - - removeProject(project) { - this.facetCriteria.projects.splice(this.facetCriteria.projects.indexOf(project), 1); - this.facetCriteriaChange.emit(this.facetCriteria); - } - - public profileChanged(event: any) { - const eventValue = event.option.value.id; - if (event.option.selected) { - this.facetCriteria.datasetProfile.push(eventValue); - } - if (!event.option.selected) { - const index = this.facetCriteria.datasetProfile.indexOf(eventValue); - this.facetCriteria.datasetProfile.splice(index, 1); - } - this.facetCriteriaChange.emit(this.facetCriteria); - } - - removeProfile(profile) { - this.facetCriteria.datasetProfile.splice(this.facetCriteria.datasetProfile.indexOf(profile), 1); - this.facetCriteriaChange.emit(this.facetCriteria); - } - - public dmpOrganisationChanged(event: any) { - const eventValue = event.option.value.id; - if (event.option.selected) { this.facetCriteria.dmpOrganisations.push(eventValue); } - if (!event.option.selected) { - const index = this.facetCriteria.dmpOrganisations.indexOf(eventValue); - this.facetCriteria.dmpOrganisations.splice(index, 1); - } - this.facetCriteriaChange.emit(this.facetCriteria); - } - - public projectSearch(value: string): Observable { - const projectCriteria = new ProjectCriteria(); - projectCriteria.projectStateType = this.facetCriteria.projectStatus; - projectCriteria['length'] = 10; - projectCriteria.like = value; - const dataTableRequest: RequestItem = { criteria: projectCriteria }; - return this.projectService.get(dataTableRequest); - } - - public dmpOrganisationSearch(value: string): Observable { - return this.externalSourcesService.searchDMPOrganizations(value); - } - - removeOrganisation(organisation) { - this.facetCriteria.dmpOrganisations.splice(this.facetCriteria.dmpOrganisations.indexOf(organisation), 1); - this.facetCriteriaChange.emit(this.facetCriteria); - } - - public profileSearch(value: string) { - return this.datasetProfileService.getDatasetProfiles(); - } - - public controlModified() { - this.facetCriteriaChange.emit(this.facetCriteria); - } - - filterTags(value: string): void { - this.filteredTags = undefined; - if (value) { - this.filteringTagsAsync = true; - const requestItem: RequestItem = new RequestItem(); - const criteria: TagsCriteria = new TagsCriteria(); - criteria.like = value; - requestItem.criteria = criteria; - this.externalSourcesService.searchDatasetTags(requestItem) - .pipe(takeUntil(this._destroyed)) - .subscribe(items => { - this.filteredTags = items; - this.filteringTagsAsync = false; - }); - - } - } -} diff --git a/dmp-frontend/src/app/shared/components/figurecard/figurecard.component.ts b/dmp-frontend/src/app/shared/components/figurecard/figurecard.component.ts deleted file mode 100644 index 47b334c66..000000000 --- a/dmp-frontend/src/app/shared/components/figurecard/figurecard.component.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Component, OnInit, Input } from '@angular/core'; -import { Router } from '@angular/router'; -import { AuthService } from '../../../services/auth/auth.service'; - -@Component({ - selector: 'app-figurecard', - templateUrl: './figurecard.component.html', - styleUrls: ['./figurecard.component.scss'] -}) -export class FigurecardComponent implements OnInit { - @Input() headerIcon: string; - @Input() category: string; - @Input() title: string; - @Input() footerIcon: string; - @Input() footContent: string; - @Input() linearColor: string; - @Input() boxShadow: string; - @Input() routelLink: string; - @Input() hasFootContent = false; - @Input() buttonTitle: string; - @Input() buttonRedirectLink: string; - - constructor(private router: Router, private authService: AuthService) { } - - ngOnInit() { - } - - navigateToUrl() { - if (!this.isAuthenticated()) { return; } - this.router.navigate([this.routelLink]); - } - - createNew() { - this.router.navigate([this.buttonRedirectLink]); - } - - isAuthenticated() { - return this.authService.current() != null; - } - -} diff --git a/dmp-frontend/src/app/shared/components/file-uploader/FileUploader.ts b/dmp-frontend/src/app/shared/components/file-uploader/FileUploader.ts deleted file mode 100644 index e87e040ad..000000000 --- a/dmp-frontend/src/app/shared/components/file-uploader/FileUploader.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Observable } from 'rxjs'; -import { ContentFile } from '../../../models/files/ContentFile'; - -export interface FileUploader { - uploadFile(formData: FormData): Observable; -} diff --git a/dmp-frontend/src/app/shared/components/file-uploader/file-uploader.component.html b/dmp-frontend/src/app/shared/components/file-uploader/file-uploader.component.html deleted file mode 100644 index 7aa8c8ab3..000000000 --- a/dmp-frontend/src/app/shared/components/file-uploader/file-uploader.component.html +++ /dev/null @@ -1,11 +0,0 @@ - - file_upload - {{ files['name'] }} - - attach_file - - {{label | translate}} - - - diff --git a/dmp-frontend/src/app/shared/components/file-uploader/file-uploader.component.ts b/dmp-frontend/src/app/shared/components/file-uploader/file-uploader.component.ts deleted file mode 100644 index 548ffc0b1..000000000 --- a/dmp-frontend/src/app/shared/components/file-uploader/file-uploader.component.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { FormControl } from '@angular/forms'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { FileUploader } from '../../../shared/components/file-uploader/FileUploader'; - -@Component({ - selector: 'app-fileuploader-component', - templateUrl: './file-uploader.component.html' -}) -export class FileUploaderComponent extends BaseComponent implements OnInit { - - files: File | FileList; - disabled = false; - - fileSelectMultipleMsg = 'No file(s) selected yet.'; - - @Input() - public label = 'FILE-UPLOADER.DEFAULT'; - - @Input() - public fileUploader: FileUploader; - - @Input() - form: FormControl; - - ngOnInit(): void { - } - - selectEvent(files: FileList | File): void { - this.label = 'FILE-UPLOADER.UPLOAD'; - if (files instanceof FileList) { - const names: string[] = []; - for (let i = 0; i < files.length; i++) { - names.push(files[i].name); - } - this.fileSelectMultipleMsg = names.join(','); - } else { - this.fileSelectMultipleMsg = files.name; - } - } - - uploadEvent(files: FileList | File): void { - const formdata: FormData = new FormData(); - - if (files instanceof FileList) { - for (let i = 0; i < files.length; i++) { - formdata.append('file', files[i]); - } - } else { - formdata.append('file', files); - } - this.fileUploader.uploadFile(formdata) - .pipe(takeUntil(this._destroyed)) - .subscribe(fileitem => this.form.patchValue(fileitem)); - } - - cancelEvent(): void { - } -} diff --git a/dmp-frontend/src/app/shared/components/invitation-accepted/invitation-accepted.component.html b/dmp-frontend/src/app/shared/components/invitation-accepted/invitation-accepted.component.html deleted file mode 100644 index e69de29bb..000000000 diff --git a/dmp-frontend/src/app/shared/components/invitation-accepted/invitation-accepted.component.ts b/dmp-frontend/src/app/shared/components/invitation-accepted/invitation-accepted.component.ts deleted file mode 100644 index d6d439842..000000000 --- a/dmp-frontend/src/app/shared/components/invitation-accepted/invitation-accepted.component.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { InvitationService } from '../../../services/invitation/invitation.service'; - -@Component({ - selector: 'app-invitation-accepted-component', - templateUrl: 'invitation-accepted.component.html', - -}) -export class InvitationAcceptedComponent extends BaseComponent implements OnInit { - constructor( - private invitationService: InvitationService, - private route: ActivatedRoute, - public router: Router - ) { super(); } - - ngOnInit(): void { - this.route.params - .pipe(takeUntil(this._destroyed)) - .subscribe(params => { - const id = params['id']; - this.invitationService.exchange(id) - .pipe(takeUntil(this._destroyed)) - .subscribe(result => { - this.router.navigate(['dmps/edit/' + result]); - }); - }); - } -} diff --git a/dmp-frontend/src/app/shared/components/invitation/invitation.component.html b/dmp-frontend/src/app/shared/components/invitation/invitation.component.html deleted file mode 100644 index 10e752ae2..000000000 --- a/dmp-frontend/src/app/shared/components/invitation/invitation.component.html +++ /dev/null @@ -1,24 +0,0 @@ -
-

{{'INVITATION-EDITOR.TITLE' | translate}} {{data.dmpName}}

-
- - -
{{chip.name.substring(0, 1).toUpperCase()}}
- {{chip.name}} -
- -
- {{option.name}} -
-
- -
-
-
-
- -
-
-
diff --git a/dmp-frontend/src/app/shared/components/invitation/invitation.component.scss b/dmp-frontend/src/app/shared/components/invitation/invitation.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/dmp-frontend/src/app/shared/components/invitation/invitation.component.ts b/dmp-frontend/src/app/shared/components/invitation/invitation.component.ts deleted file mode 100644 index ea22c38d0..000000000 --- a/dmp-frontend/src/app/shared/components/invitation/invitation.component.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { Component, Inject, OnInit } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; -import { ActivatedRoute, Router } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { UserInvitationCriteria } from '../../../models/criteria/invitation/UserInvitationCriteria'; -import { RequestItem } from '../../../models/criteria/RequestItem'; -import { Invitation } from '../../../models/invitation/Invitation'; -import { User } from '../../../models/invitation/User'; -import { InvitationService } from '../../../services/invitation/invitation.service'; -import { JsonSerializer } from '../../../utilities/JsonSerializer'; - -@Component({ - selector: 'app-invitation-component', - templateUrl: 'invitation.component.html', - -}) -export class InvitationComponent extends BaseComponent implements OnInit { - - public formGroup: FormGroup; - - public filteredUsersAsync = false; - - public filteredUsers: User[]; - - constructor( - public invitationService: InvitationService, - public route: ActivatedRoute, - public router: Router, - public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any - ) { super(); } - - ngOnInit(): void { - const invitation = new Invitation(); - invitation.dataManagementPlan = this.data.dmpId; - this.formGroup = invitation.buildForm(); - } - - - send(value: any) { - this.invitationService.inviteUsers(this.formGroup.value) - .pipe(takeUntil(this._destroyed)) - .subscribe( - null, null, () => this.dialogRef.close() - ); - } - - filterUsers(value: string): void { - this.filteredUsers = undefined; - if (value) { - this.filteredUsersAsync = true; - const request = new RequestItem(); - request.criteria = { like: value }; - this.invitationService.getUsers(request) - .pipe(takeUntil(this._destroyed)) - .subscribe(items => { - this.filteredUsers = JsonSerializer.fromJSONArray(items, User); - if (!this.filteredUsers || this.filteredUsers.length === 0) { - const user = new User(); - user.email = value; - user.name = value; - this.filteredUsers.push(user); - } - this.filteredUsersAsync = false; - }); - } - } -} diff --git a/dmp-frontend/src/app/shared/components/navigation/navigation.component.html b/dmp-frontend/src/app/shared/components/navigation/navigation.component.html deleted file mode 100644 index bb20957d1..000000000 --- a/dmp-frontend/src/app/shared/components/navigation/navigation.component.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - -
- - - - - {{option.label}} -
- {{transformType(option.type)}} -
-
-
-
-
-
- -
- -
- -
-
- -
-
- - - - -
diff --git a/dmp-frontend/src/app/shared/components/navigation/navigation.component.scss b/dmp-frontend/src/app/shared/components/navigation/navigation.component.scss deleted file mode 100644 index 816925725..000000000 --- a/dmp-frontend/src/app/shared/components/navigation/navigation.component.scss +++ /dev/null @@ -1,54 +0,0 @@ -.navbar-icon { - padding: 0 14px; -} - -.navbar-spacer { - flex: 1 1 auto; -} - -.navbar-button { - text-transform: uppercase; -} -.navbar-button:hover { - color: white; - text-decoration: none; -} - -.navbar-button:focus { - color: white; - text-decoration: none; -} -.user-label { - padding: 0 0 0 5px; - font-size: 14px; -} - -.app-title { - color: inherit; - text-decoration: none; - padding-right: 15px; -} - -.login-label { - font-size: 14px; -} - -.app-logo { - height: 60px; - img{ - height: inherit; - } -} - -.user-profile{ - width: 10%; -} - -.full-width { - width: 100%; -} - -.transformation-value-mat-option { - height: 3.5em; - line-height: 1.2em; -} diff --git a/dmp-frontend/src/app/shared/components/navigation/navigation.component.ts b/dmp-frontend/src/app/shared/components/navigation/navigation.component.ts deleted file mode 100644 index 938adfa04..000000000 --- a/dmp-frontend/src/app/shared/components/navigation/navigation.component.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { sample } from 'rxjs/operators'; -import { Component, EventEmitter, Input, Output, ElementRef, OnInit } from '@angular/core'; -import { Principal } from '../../../models/login/Principal'; -import { AuthService } from '../../../services/auth/auth.service'; -import { LanguageResolverService } from '../../../services/language-resolver/language-resolver.service'; -import { MatSidenav, MatDialog } from '@angular/material'; -import { UserDialogComponent } from '../user-dialog/user-dialog.component'; -import { SingleAutoCompleteConfiguration } from '../autocompletes/single/single-auto-complete-configuration'; -import { ProjectCriteria } from '../../../models/criteria/project/ProjectCriteria'; -import { RequestItem } from '../../../models/criteria/RequestItem'; -import { ProjectService } from '../../../services/project/project.service'; -import { FormControl } from '@angular/forms'; -import { DashboardService } from '../../../services/dashboard/dashboard.service'; -import { Observable } from 'rxjs'; -import { SearchBarItem, SearchBarItemType } from '../../../models/dashboard/SearchBarItem'; -import { SearchBarType } from '../search-bar/types/search-bar-type'; -import { Router } from '@angular/router'; - -@Component({ - selector: 'app-navigation', - templateUrl: 'navigation.component.html', - styleUrls: ['./navigation.component.scss'], - providers: [ProjectService] -}) - -export class NavigationComponent implements OnInit { - invert = false; - public search = false; - projectAutoCompleteConfiguration: SingleAutoCompleteConfiguration; - public searchControl = new FormControl(); - filteredOptions: Observable; - @Input() - sideNav: MatSidenav; - - @Output() - sidenavOpenChanges = new EventEmitter(); - - events: string[] = []; - opened: boolean; - constructor( - private authentication: AuthService, - private languageResolver: LanguageResolverService, - public dialog: MatDialog, - private projectService: ProjectService, - private dashBoardService: DashboardService, - private router: Router, - - ) { - - } - - // tslint:disable-next-line:use-life-cycle-interface - ngOnInit() { - this.projectAutoCompleteConfiguration = { - filterFn: this.searchProject.bind(this), - items: this.searchProject(''), - displayFn: (item) => item['label'], - titleFn: (item) => item['label'], - //mapFn: (item) => new JsonSerializer().fromJSONArray(item, ProjectReference).map(item => item.toDropdownList()), - loadDataOnStart: true - }; - - this.filteredOptions = this.searchControl.valueChanges.debounceTime(500).distinctUntilChanged().flatMap(x => { - return this.dashBoardService.searchUserItems(x); - }); - } - - searchProject(query: string) { - const projectRequestItem: RequestItem = new RequestItem(); - projectRequestItem.criteria = new ProjectCriteria(); - projectRequestItem.criteria.like = query; - return this.projectService.getWithExternal(projectRequestItem); - } - - public logout(): void { - this.authentication.logout(); - } - - public isAuthenticated(): boolean { - return !(!this.authentication.current()); - } - - public isAdmin(): boolean { - if (!this.authentication.current()) { return false; } - const principalRoles = this.authentication.current().appRoles; - for (let i = 0; i < principalRoles.length; i++) { - if (principalRoles[i] === Principal.AppRole.Admin) { - return true; - } - } - return false; - } - - public principalHasAvatar(): boolean { - return this.authentication.current().avatarUrl != null; - } - - public getPrincipalAvatar(): string { - return this.authentication.current().avatarUrl; - } - - onSideNavClick() { - this.sideNav.toggle(); - } - - openProfile() { - const dialogRef = this.dialog.open(UserDialogComponent, { - hasBackdrop: true, - closeOnNavigation: true, - disableClose: false, - position: { top: '64px', left: '85%' } - }); - } - - onOptionSelected(event: any) { - this.search = false; - this.searchControl.patchValue(null); - const selectedSearchBarItem = event.option.value; - if (selectedSearchBarItem.type === SearchBarType.DATASET) { this.router.navigate(['datasets/edit/' + selectedSearchBarItem.id]); } - if (selectedSearchBarItem.type === SearchBarType.PROJECT) { this.router.navigate(['projects/edit/' + selectedSearchBarItem.id]); } - if (selectedSearchBarItem.type === SearchBarType.DATAMANAGEMENTPLAN) { this.router.navigate(['dmps/edit/' + selectedSearchBarItem.id]); } - } - - transformType(type) { - switch (type) { - case SearchBarItemType.DATASET: return 'Dataset'; - case SearchBarItemType.DMP: return 'DMP'; - case SearchBarItemType.PROJECT: return 'Project'; - } - } -} diff --git a/dmp-frontend/src/app/shared/components/notificaiton/snack-bar-notification.component.ts b/dmp-frontend/src/app/shared/components/notificaiton/snack-bar-notification.component.ts deleted file mode 100644 index 19aded5bc..000000000 --- a/dmp-frontend/src/app/shared/components/notificaiton/snack-bar-notification.component.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Component, Inject } from '@angular/core'; -import { MAT_SNACK_BAR_DATA } from '@angular/material'; -import { TranslateService } from '@ngx-translate/core'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -@Component({ - selector: 'app-snack-bar-notification', - templateUrl: 'snack-bar-notification.component.html' -}) - -export class SnackBarNotificationComponent extends BaseComponent { - message: string; - constructor(@Inject(MAT_SNACK_BAR_DATA) public data: any) { - super(); - this.parseMessage(data.message, data.language); - } - - parseMessage(message: any, language: TranslateService): void { - if (language) { - language.get(message) - .pipe(takeUntil(this._destroyed)) - .subscribe((value: string) => { - this.message = value; - }); - } else { this.message = message; } - } -} diff --git a/dmp-frontend/src/app/shared/components/search-bar/search-bar.component.html b/dmp-frontend/src/app/shared/components/search-bar/search-bar.component.html deleted file mode 100644 index e69de29bb..000000000 diff --git a/dmp-frontend/src/app/shared/components/search-bar/search-bar.component.scss b/dmp-frontend/src/app/shared/components/search-bar/search-bar.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/dmp-frontend/src/app/shared/components/search-bar/search-bar.component.ts b/dmp-frontend/src/app/shared/components/search-bar/search-bar.component.ts deleted file mode 100644 index 349394bf5..000000000 --- a/dmp-frontend/src/app/shared/components/search-bar/search-bar.component.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { sample } from 'rxjs/operators'; -import { Component, EventEmitter, Input, Output, ElementRef } from '@angular/core'; -import { Principal } from '../../../models/login/Principal'; -import { AuthService } from '../../../services/auth/auth.service'; -import { LanguageResolverService } from '../../../services/language-resolver/language-resolver.service'; -import { MatSidenav, MatDialog } from '@angular/material'; -import { UserDialogComponent } from '../user-dialog/user-dialog.component'; - -@Component({ - selector: 'app-search', - templateUrl: 'search-bar.component.html', - styleUrls: ['./search-bar.component.scss'], -}) - -export class SearchBarComponent { - -} diff --git a/dmp-frontend/src/app/shared/components/search-bar/types/search-bar-type.ts b/dmp-frontend/src/app/shared/components/search-bar/types/search-bar-type.ts deleted file mode 100644 index 0bf6b0d47..000000000 --- a/dmp-frontend/src/app/shared/components/search-bar/types/search-bar-type.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum SearchBarType { - DATASET = 0, - DATAMANAGEMENTPLAN = 1, - PROJECT = 2 -} diff --git a/dmp-frontend/src/app/shared/components/url-listing/UrlListingItem.ts b/dmp-frontend/src/app/shared/components/url-listing/UrlListingItem.ts deleted file mode 100644 index 08f10bdb1..000000000 --- a/dmp-frontend/src/app/shared/components/url-listing/UrlListingItem.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Serializable } from '../../../models/Serializable'; - -export class UrlListingItem implements Serializable { - - public label: string; - public url: string; - public all: string; - - fromJSONObject(item: any): UrlListingItem { - this.label = item.label; - this.url = item.url; - return this; - } -} diff --git a/dmp-frontend/src/app/shared/components/url-listing/url-listing.component.ts b/dmp-frontend/src/app/shared/components/url-listing/url-listing.component.ts deleted file mode 100644 index 1d55779c6..000000000 --- a/dmp-frontend/src/app/shared/components/url-listing/url-listing.component.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Component, Input } from "@angular/core"; -import { UrlListingItem } from "../../../shared/components/url-listing/UrlListingItem"; -import { Router } from "@angular/router"; -import { UrlUtilities } from "../../../utilities/UrlUtilities"; - -@Component({ - selector: 'app-url-listing', - templateUrl: './url-listing.component.html' -}) -export class UrlListingComponent { - - @Input() - items: UrlListingItem[]; - - @Input() - parameters: any - - @Input() - urlLimit: number = 3; - - constructor(private router: Router, private urlUtilities: UrlUtilities) { } - - ngOnInit() { - - } - - navigate(link: string) { - this.router.navigate([link], { queryParams: this.parameters }); - } -} diff --git a/dmp-frontend/src/app/shared/components/user-dialog/user-dialog.component.scss b/dmp-frontend/src/app/shared/components/user-dialog/user-dialog.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/dmp-frontend/src/app/shared/components/user-dialog/user-dialog.component.ts b/dmp-frontend/src/app/shared/components/user-dialog/user-dialog.component.ts deleted file mode 100644 index e0096b2c4..000000000 --- a/dmp-frontend/src/app/shared/components/user-dialog/user-dialog.component.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { JsonSerializer } from '../../../utilities/JsonSerializer'; -import { RequestItem } from '../../../models/criteria/RequestItem'; -import { Component, OnInit, Inject } from '@angular/core'; -import { FormGroup } from '@angular/forms'; -import { Params, ActivatedRoute, Router } from '@angular/router'; -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; -import { ResearcherModel } from '../../../models/researcher/ResearcherModel'; -import { ResearcherService } from '../../../services/researchers/researchers.service'; -import { AuthService } from '../../../services/auth/auth.service'; -import { Principal } from '../../../models/login/Principal'; - -@Component({ - selector: 'app-user-dialog-component', - templateUrl: 'user-dialog.component.html', - -}) -export class UserDialogComponent implements OnInit { - - public formGroup: FormGroup; - - constructor( - private route: ActivatedRoute, - private authentication: AuthService, - public router: Router, - public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any - ) { } - - ngOnInit(): void { - } - - public logout(): void { - this.dialogRef.close(); - this.authentication.logout(); - } - - public getPrincipalName(): string { - const principal: Principal = this.authentication.current(); - if (principal) { return principal.name; } - return ''; - } - - public principalHasAvatar(): boolean { - return this.authentication.current() && this.authentication.current().avatarUrl != null; - } - - public getPrincipalAvatar(): string { - return this.authentication.current() && this.authentication.current().avatarUrl; - } - - public navigateToProfile() { - this.dialogRef.close(); - this.router.navigate(['/users/' + this.authentication.current().id]); - } -} diff --git a/dmp-frontend/src/app/shared/componentsAdmin/autocomplete/autocomplete-component.html b/dmp-frontend/src/app/shared/componentsAdmin/autocomplete/autocomplete-component.html deleted file mode 100644 index c27e1329a..000000000 --- a/dmp-frontend/src/app/shared/componentsAdmin/autocomplete/autocomplete-component.html +++ /dev/null @@ -1,34 +0,0 @@ -
Autocomplete Description
-
-
-
- - - -
-
-
-
- - - -
-
- - - -
-
-
-
- - - -
-
- - - -
-
-
diff --git a/dmp-frontend/src/app/shared/componentsAdmin/autocomplete/autocomplete-component.ts b/dmp-frontend/src/app/shared/componentsAdmin/autocomplete/autocomplete-component.ts deleted file mode 100644 index 0ebd0f609..000000000 --- a/dmp-frontend/src/app/shared/componentsAdmin/autocomplete/autocomplete-component.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { AutocompleteData } from '../../../models/DataField/AutocompleteData'; -import { FormGroup } from '@angular/forms'; -import { Component, Input, OnInit } from '@angular/core'; -import { FormArray } from '@angular/forms'; -import { Field } from '../../../models/datasetProfileAdmin/Field'; -import { JsonSerializer } from '../../../utilities/JsonSerializer'; - -@Component({ - selector: 'app-autocomplete-component', - styleUrls: ['./autocomplete-component.scss'], - templateUrl: './autocomplete-component.html' -}) -export class AutocompleteComponent implements OnInit { - @Input() dataModel: Field; - @Input() form: FormGroup; - private data: AutocompleteData = new AutocompleteData(); - - ngOnInit() { - this.data.type = 'autocomplete'; - if (!this.form.get('data') || !this.form.get('data').get('autoCompleteOptions')) { - const autocomplete: AutocompleteData = new AutocompleteData(); - this.dataModel.data = JsonSerializer.fromJSONObject(this.data, AutocompleteData); - this.form.removeControl('data'); - this.form.addControl('data', autocomplete.buildForm()); - } else { - this.form.addControl('data', this.data.buildForm()); - } - } -} diff --git a/dmp-frontend/src/app/shared/componentsAdmin/booleanDecision/booleanDecision-component.html b/dmp-frontend/src/app/shared/componentsAdmin/booleanDecision/booleanDecision-component.html deleted file mode 100644 index 63bd2225c..000000000 --- a/dmp-frontend/src/app/shared/componentsAdmin/booleanDecision/booleanDecision-component.html +++ /dev/null @@ -1,10 +0,0 @@ -
Boolean Decision Description
-
-
-
- - - -
-
-
diff --git a/dmp-frontend/src/app/shared/componentsAdmin/booleanDecision/booleanDecision-component.ts b/dmp-frontend/src/app/shared/componentsAdmin/booleanDecision/booleanDecision-component.ts deleted file mode 100644 index f1f2afb98..000000000 --- a/dmp-frontend/src/app/shared/componentsAdmin/booleanDecision/booleanDecision-component.ts +++ /dev/null @@ -1,21 +0,0 @@ - -import { BooleanDecisionData } from '../../../models/DataField/BooleanDecisionData'; -import { FormGroup } from '@angular/forms'; -import { Component, Input, OnInit } from '@angular/core'; -import { FormArray } from '@angular/forms'; -import { Field } from '../../../models/datasetProfileAdmin/Field'; - -@Component({ - selector: 'app-boolean-decision-component', - styleUrls: ['./booleanDecision-component.scss'], - templateUrl: './booleanDecision-component.html' -}) -export class BooleanDecisionComponent implements OnInit { - @Input() dataModel: Field; - @Input() form: FormGroup; - private data: BooleanDecisionData = new BooleanDecisionData(); - - ngOnInit() { - this.form.addControl('data', this.data.buildForm()); - } -} diff --git a/dmp-frontend/src/app/shared/componentsAdmin/checkbox/checkbox-component.html b/dmp-frontend/src/app/shared/componentsAdmin/checkbox/checkbox-component.html deleted file mode 100644 index 9819a0be1..000000000 --- a/dmp-frontend/src/app/shared/componentsAdmin/checkbox/checkbox-component.html +++ /dev/null @@ -1,11 +0,0 @@ -
Checkbox Description
-
-
-
- - - -
-
- -
diff --git a/dmp-frontend/src/app/shared/componentsAdmin/checkbox/checkbox-component.ts b/dmp-frontend/src/app/shared/componentsAdmin/checkbox/checkbox-component.ts deleted file mode 100644 index 141550e5d..000000000 --- a/dmp-frontend/src/app/shared/componentsAdmin/checkbox/checkbox-component.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { CheckBoxData } from '../../../models/DataField/CheckBoxData'; -import { BooleanDecisionData } from '../../../models/DataField/BooleanDecisionData'; -import { FormGroup } from '@angular/forms'; -import { Component, Input, OnInit } from '@angular/core'; -import { FormArray } from '@angular/forms'; -import { Field } from '../../../models/datasetProfileAdmin/Field'; - -@Component({ - selector: 'app-checkbox-component', - styleUrls: ['./checkbox-component.scss'], - templateUrl: './checkbox-component.html' -}) -export class CheckBoxComponent implements OnInit { - @Input() dataModel: Field; - @Input() form: FormGroup; - private data: CheckBoxData = new CheckBoxData(); - - ngOnInit() { - this.form.addControl('data', this.data.buildForm()); - } -} diff --git a/dmp-frontend/src/app/shared/componentsAdmin/combobox/combobox-component.html b/dmp-frontend/src/app/shared/componentsAdmin/combobox/combobox-component.html deleted file mode 100644 index 0cafdeda3..000000000 --- a/dmp-frontend/src/app/shared/componentsAdmin/combobox/combobox-component.html +++ /dev/null @@ -1,17 +0,0 @@ -
-
- - - {{option.value}} - - -
-
-
-
- -
-
- -
-
diff --git a/dmp-frontend/src/app/shared/componentsAdmin/combobox/combobox-component.ts b/dmp-frontend/src/app/shared/componentsAdmin/combobox/combobox-component.ts deleted file mode 100644 index d1c6b5446..000000000 --- a/dmp-frontend/src/app/shared/componentsAdmin/combobox/combobox-component.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { FormGroup } from '@angular/forms'; -import { Component, Input, OnInit } from '@angular/core'; -import { Field } from '../../../models/datasetProfileAdmin/Field'; - -@Component({ - selector: 'app-combobox-component', - styleUrls: ['./combobox-component.scss'], - templateUrl: './combobox-component.html' -}) -export class ComboboxComponent implements OnInit { - @Input() dataModel: Field; - @Input() form: FormGroup; - type: string; - options = [{ id: 'autocomplete', value: 'autocomplete' }, { id: 'wordlist', value: 'wordlist' }]; - - ngOnInit() { - if (this.dataModel.data && this.form.get('data')) { - if (this.form.get('data').get('type')) { this.type = this.form.get('data').get('type').value; } - } - - } - - onchangeCombo() { - if (this.form.get('data')) { this.form.removeControl('data'); } - } -} diff --git a/dmp-frontend/src/app/shared/componentsAdmin/freetext/freetext-component.html b/dmp-frontend/src/app/shared/componentsAdmin/freetext/freetext-component.html deleted file mode 100644 index be1c67e6c..000000000 --- a/dmp-frontend/src/app/shared/componentsAdmin/freetext/freetext-component.html +++ /dev/null @@ -1,10 +0,0 @@ -
FreeText Description
-
-
-
- - - -
-
-
diff --git a/dmp-frontend/src/app/shared/componentsAdmin/freetext/freetext-component.ts b/dmp-frontend/src/app/shared/componentsAdmin/freetext/freetext-component.ts deleted file mode 100644 index 7fb64a252..000000000 --- a/dmp-frontend/src/app/shared/componentsAdmin/freetext/freetext-component.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { FreeTextData } from '../../../models/DataField/FreeTextData'; -import { CheckBoxData } from '../../../models/DataField/CheckBoxData'; -import { BooleanDecisionData } from '../../../models/DataField/BooleanDecisionData'; -import { FormGroup } from '@angular/forms'; -import { Component, Input, OnInit } from '@angular/core'; -import { FormArray } from '@angular/forms'; -import { Field } from '../../../models/datasetProfileAdmin/Field'; - -@Component({ - selector: 'app-freetext-component', - styleUrls: ['./freetext-component.scss'], - templateUrl: './freetext-component.html' -}) -export class FreeTextComponent implements OnInit { - @Input() dataModel: Field; - @Input() form: FormGroup; - private data: FreeTextData = new FreeTextData(); - - ngOnInit() { - this.form.addControl('data', this.data.buildForm()); - } -} diff --git a/dmp-frontend/src/app/shared/componentsAdmin/radiobox/radiobox-component.html b/dmp-frontend/src/app/shared/componentsAdmin/radiobox/radiobox-component.html deleted file mode 100644 index c69e24deb..000000000 --- a/dmp-frontend/src/app/shared/componentsAdmin/radiobox/radiobox-component.html +++ /dev/null @@ -1,34 +0,0 @@ -
Radio Box Description
-
-
-
- - - -
-
-
-
-
-
-
- - - -
-
- - - -
-
-
-
-
-
- -
- -
diff --git a/dmp-frontend/src/app/shared/componentsAdmin/radiobox/radiobox-component.ts b/dmp-frontend/src/app/shared/componentsAdmin/radiobox/radiobox-component.ts deleted file mode 100644 index 0407d7154..000000000 --- a/dmp-frontend/src/app/shared/componentsAdmin/radiobox/radiobox-component.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { FormGroup, FormBuilder } from '@angular/forms'; -import { Component, Input, OnInit } from '@angular/core'; -import { RadioBoxData } from '../../../models/DataField/RadioBoxData'; -import { FormArray } from '@angular/forms'; -import { ListingItem } from '../../../models/common/ListingItem'; -import { JsonSerializer } from '../../../utilities/JsonSerializer'; -import { Field } from '../../../models/datasetProfileAdmin/Field'; - -@Component({ - selector: 'app-radiobox-component', - styleUrls: ['./radiobox-component.scss'], - templateUrl: './radiobox-component.html' -}) -export class RadioBoxComponent implements OnInit { - @Input() dataModel: Field; - @Input() form: FormGroup; - private data: RadioBoxData = new RadioBoxData(); - private options = new Array(); - - ngOnInit() { - //if (this.form.get("data")) this.form.removeControl("data"); - if (!this.form.get('data')) { - this.form.addControl('data', this.data.buildForm()); - } - if (!this.dataModel.data || !this.dataModel.data['options']) { this.addNewRow(); } - } - - addNewRow() { - const radioListOptions: ListingItem = new ListingItem(); - if (!this.form.get('data').get('options')) { (this.form.get('data')).addControl('options', new FormBuilder().array([])); } - (this.form.get('data').get('options')).push(radioListOptions.buildForm()); - this.data.options = []; - this.data.options.push(radioListOptions); - this.dataModel.data = JsonSerializer.fromJSONObject(this.data, RadioBoxData); - } -} diff --git a/dmp-frontend/src/app/shared/componentsAdmin/textarea/textarea-component.html b/dmp-frontend/src/app/shared/componentsAdmin/textarea/textarea-component.html deleted file mode 100644 index 632dcea4e..000000000 --- a/dmp-frontend/src/app/shared/componentsAdmin/textarea/textarea-component.html +++ /dev/null @@ -1,11 +0,0 @@ -
TextArea Description
- -
-
-
- - - -
-
-
diff --git a/dmp-frontend/src/app/shared/componentsAdmin/textarea/textarea-component.ts b/dmp-frontend/src/app/shared/componentsAdmin/textarea/textarea-component.ts deleted file mode 100644 index d99c720d5..000000000 --- a/dmp-frontend/src/app/shared/componentsAdmin/textarea/textarea-component.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { TextArea } from '../../../models/DataField/TextArea'; -import { FreeTextData } from '../../../models/DataField/FreeTextData'; -import { CheckBoxData } from '../../../models/DataField/CheckBoxData'; -import { BooleanDecisionData } from '../../../models/DataField/BooleanDecisionData'; -import { FormGroup } from '@angular/forms'; -import { Component, Input, OnInit } from '@angular/core'; -import { FormArray } from '@angular/forms'; -import { Field } from '../../../models/datasetProfileAdmin/Field'; - -@Component({ - selector: 'app-textarea-component', - styleUrls: ['./textarea-component.scss'], - templateUrl: './textarea-component.html' -}) -export class TextAreaComponent implements OnInit { - @Input() dataModel: Field; - @Input() form: FormGroup; - private data: TextArea = new TextArea(); - - ngOnInit() { - this.form.addControl('data', this.data.buildForm()); - } -} diff --git a/dmp-frontend/src/app/shared/componentsAdmin/wordlist/wordlist-component.html b/dmp-frontend/src/app/shared/componentsAdmin/wordlist/wordlist-component.html deleted file mode 100644 index 2cb397936..000000000 --- a/dmp-frontend/src/app/shared/componentsAdmin/wordlist/wordlist-component.html +++ /dev/null @@ -1,35 +0,0 @@ -
Word List Description
- -
-
-
-
- - - -
-
-
-
-
-
- - - -
-
- - - -
-
-
-
-
-
- -
- -
diff --git a/dmp-frontend/src/app/shared/componentsAdmin/wordlist/wordlist-component.scss b/dmp-frontend/src/app/shared/componentsAdmin/wordlist/wordlist-component.scss deleted file mode 100644 index 3db0dee74..000000000 --- a/dmp-frontend/src/app/shared/componentsAdmin/wordlist/wordlist-component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.full-width { - width: 100%; -} diff --git a/dmp-frontend/src/app/shared/componentsAdmin/wordlist/wordlist-component.ts b/dmp-frontend/src/app/shared/componentsAdmin/wordlist/wordlist-component.ts deleted file mode 100644 index 06ad1aaff..000000000 --- a/dmp-frontend/src/app/shared/componentsAdmin/wordlist/wordlist-component.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { FormGroup } from '@angular/forms'; -import { Component, Input, OnInit } from '@angular/core'; -import { WordListData } from '../../../models/DataField/WordListData'; -import { FormArray } from '@angular/forms'; -import { ListingItem } from '../../../models/common/ListingItem'; -import { JsonSerializer } from '../../../utilities/JsonSerializer'; -import { Field } from '../../../models/datasetProfileAdmin/Field'; - -@Component({ - selector: 'app-wordlist-component', - styleUrls: ['./wordlist-component.scss'], - templateUrl: './wordlist-component.html' -}) -export class WordlistComponent implements OnInit { - @Input() dataModel: Field; - @Input() form: FormGroup; - private data: WordListData = new WordListData(); - private options = new Array(); - - ngOnInit() { - this.data.type = 'wordlist'; - // if (this.form.get("data")) this.form.removeControl("data"); - this.form.addControl('data', this.data.buildForm()); - if (!this.dataModel.data) { - this.addNewRow(); - } - } - - addNewRow() { - const wordListOptions: ListingItem = new ListingItem(); - (this.form.get('data').get('options')).push(wordListOptions.buildForm()); - this.data.options = []; - this.data.options.push(wordListOptions); - this.dataModel.data = JsonSerializer.fromJSONObject(this.data, WordListData); - } -} diff --git a/dmp-frontend/src/app/shared/guards/auth.guard.ts b/dmp-frontend/src/app/shared/guards/auth.guard.ts deleted file mode 100644 index 653128626..000000000 --- a/dmp-frontend/src/app/shared/guards/auth.guard.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; -import { AuthService } from '../../services/auth/auth.service'; - -@Injectable() -export class AuthGuard implements CanActivate { - - constructor(private auth: AuthService, private router: Router) { - } - canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { - const url: string = state.url; - if (!this.auth.current()) { - this.router.navigate(['/unauthorized'], { queryParams: { returnUrl: url } }); - return false; - } - return true; - } -} diff --git a/dmp-frontend/src/app/shared/help-content/help-content.component.ts b/dmp-frontend/src/app/shared/help-content/help-content.component.ts deleted file mode 100644 index 3cc977dcc..000000000 --- a/dmp-frontend/src/app/shared/help-content/help-content.component.ts +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Created by stefania on 7/17/17. - */ -import { Component, Input, OnInit } from '@angular/core'; -import { ActivatedRoute, NavigationStart, Router } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { PageHelpContent } from '../../models/help-content/page-help-content'; -import { HelpContentService } from '../../services/help-content/help-content.service'; -@Component({ - selector: 'app-help-content', - template: ` - - -
-
-
- `, -}) -export class HelpContentComponent extends BaseComponent implements OnInit { - @Input() position: string; - contents: any[]; - errorMessage: string = null; - constructor(private _helpContentService: HelpContentService, private route: ActivatedRoute, private router: Router) { - super(); - } - - ngOnInit() { - this.errorMessage = null; - this.router.events - .pipe(takeUntil(this._destroyed)) - .subscribe(event => { - if (event instanceof NavigationStart) { - this._helpContentService.getActivePageContent(event['url']) - .pipe(takeUntil(this._destroyed)) - .subscribe( - pageContent => this.shiftThroughContent(pageContent), - error => this.handleError(error)); - } - }); - } - shiftThroughContent(pageContent: PageHelpContent) { - this.contents = pageContent.content[this.position]; - } - isPresent() { - return (this.contents && this.contents.length > 0); - } - handleError(error) { - this.contents = []; - this.errorMessage = 'System error retrieving page content (Server responded: ' + error + ')'; - } -} - -@Component({ - selector: 'app-aside-help-content', - template: ` - - -
-
-
- `, -}) -export class AsideHelpContentComponent extends HelpContentComponent { -} diff --git a/dmp-frontend/src/app/shared/material/material.module.ts b/dmp-frontend/src/app/shared/material/material.module.ts deleted file mode 100644 index 57f8e3ab7..000000000 --- a/dmp-frontend/src/app/shared/material/material.module.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { NgModule, LOCALE_ID } from '@angular/core'; -import { - MatToolbarModule, - MatIconModule, - MatSidenavModule, - MatButtonModule, - MatTableModule, - MatPaginatorModule, - MatSortModule, - MatDialogModule, - MatDatepickerModule, - MatNativeDateModule, - MatInputModule, - MatFormFieldModule, - MatSnackBarModule, - MatAutocompleteModule, - MatExpansionModule, - MatSelectModule, - MatOptionModule, - MatCardModule, - MatProgressBarModule, - MatProgressSpinnerModule, - DateAdapter, - MatTooltipModule, - MatCheckboxModule, - MatTabsModule, - MatStepperModule, - MatRadioModule, - MatMenuModule, - MatListModule, - MatChipsModule, - MatBadgeModule, - MAT_DATE_LOCALE, - MAT_DATE_FORMATS -} from '@angular/material'; -import { CdkTableModule } from '@angular/cdk/table'; -import { SnackBarNotificationComponent } from '../components/notificaiton/snack-bar-notification.component'; -import { CovalentLayoutModule, CovalentChipsModule, CovalentDialogsModule, CovalentFileModule } from '@covalent/core'; -import { CultureService } from '../../utilities/culture/culture-service'; -import { MomentDateAdapter } from '@angular/material-moment-adapter'; - -@NgModule({ - imports: [ - ], - - exports: [ - MatToolbarModule, - MatIconModule, - MatSidenavModule, - MatButtonModule, - MatTableModule, - MatPaginatorModule, - CdkTableModule, - MatSortModule, - MatDialogModule, - MatDatepickerModule, - MatNativeDateModule, - MatInputModule, - MatFormFieldModule, - MatSnackBarModule, - MatAutocompleteModule, - MatExpansionModule, - MatSelectModule, - MatOptionModule, - MatCardModule, - MatProgressBarModule, - MatProgressSpinnerModule, - MatTooltipModule, - MatCheckboxModule, - MatTabsModule, - CovalentLayoutModule, - CovalentChipsModule, - CovalentDialogsModule, - CovalentFileModule, - MatStepperModule, - MatRadioModule, - MatMenuModule, - MatListModule, - MatChipsModule, - MatBadgeModule, - - ], - - providers: [ - - ], - - entryComponents: [ - SnackBarNotificationComponent - ] -}) - -export class MaterialModule { - // constructor(dateAdapter: DateAdapter) { - // dateAdapter.setLocale('el-GR'); - // } -} diff --git a/dmp-frontend/src/app/shared/shared.module.ts b/dmp-frontend/src/app/shared/shared.module.ts deleted file mode 100644 index c9415d7d6..000000000 --- a/dmp-frontend/src/app/shared/shared.module.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { BaseCriteriaComponent } from './components/criteria/base/base-criteria.component'; -import { FigurecardComponent } from './components/figurecard/figurecard.component'; -import { CommonModule } from '@angular/common'; -import { FlexLayoutModule } from '@angular/flex-layout'; - -import { NgModule, LOCALE_ID } from '@angular/core'; -import { RouterModule } from '@angular/router'; -import { NavigationComponent } from './components/navigation/navigation.component'; -import { SnackBarNotificationComponent } from './components/notificaiton/snack-bar-notification.component'; -import { MaterialModule } from './material/material.module'; -import { TranslateModule } from '@ngx-translate/core'; -import { ProjectCriteriaComponent } from './components/criteria/projects/projects-criteria.component'; -import { DatasetCriteriaComponent } from './components/criteria/datasets/datasets-criteria.component'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { DataManagementPlanCriteriaComponent } from './components/criteria/data-management-plan/dmp-criteria.component'; -import { FileUploaderComponent } from '../shared/components/file-uploader/file-uploader.component'; -import { UrlListingComponent } from '../shared/components/url-listing/url-listing.component'; -import { NgForLimitPipe } from './pipes/ngforlimit/ngforlimit.pipe'; -import { DataManagementPlanProfileCriteriaComponent } from './components/criteria/datamanagementplanprofile/dmp-profile-criteria.component'; -import { AutoCompleteComponent } from './components/auto-complete/auto-complete.component'; -import { ExternalItemListingComponent } from './components/external-items/external-item-listing/external-item-listing.component'; -import { ExternalItemComponent } from './components/external-items/external-item/external-item.component'; -import { BreadcrumbComponent } from './components/breadcrumb/breadcrumb.component'; -import { SingleAutoCompleteComponent } from './components/autocompletes/single/single-auto-complete.component'; -import { MultipleAutoCompleteComponent } from './components/autocompletes/multiple/multiple-auto-complete.component'; -import { UserDialogComponent } from './components/user-dialog/user-dialog.component'; -import { SearchBarComponent } from './components/search-bar/search-bar.component'; -import { TimezoneInfoDisplayPipe } from '../utilities/culture/pipes/TimezoneInfoDisplayPipe'; -import { CultureService } from '../utilities/culture/culture-service'; -import { MAT_DATE_LOCALE } from '@angular/material'; -import { FacetSearchComponent } from './components/facets/facet-search.component'; -import { FacetSearchSectionComponent } from './components/facets/facet-search-component/facet-search-section.component'; -import { DatasetProfileCriteriaComponent } from './components/criteria/dataset-profile/dataset-profile.component'; - -@NgModule({ - imports: [ - CommonModule, - RouterModule, - MaterialModule, - FlexLayoutModule, - TranslateModule, - FormsModule, - ReactiveFormsModule - ], - - declarations: [ - NavigationComponent, - SnackBarNotificationComponent, - ProjectCriteriaComponent, - DatasetCriteriaComponent, - DataManagementPlanCriteriaComponent, - DataManagementPlanProfileCriteriaComponent, - DatasetProfileCriteriaComponent, - FigurecardComponent, - BaseCriteriaComponent, - FileUploaderComponent, - UrlListingComponent, - NgForLimitPipe, - AutoCompleteComponent, - ExternalItemListingComponent, - ExternalItemComponent, - BreadcrumbComponent, - SingleAutoCompleteComponent, - MultipleAutoCompleteComponent, - UserDialogComponent, - SearchBarComponent, - FacetSearchComponent, - FacetSearchSectionComponent - ], - - exports: [ - MaterialModule, - FlexLayoutModule, - NavigationComponent, - SnackBarNotificationComponent, - ProjectCriteriaComponent, - DatasetCriteriaComponent, - DataManagementPlanProfileCriteriaComponent, - DataManagementPlanCriteriaComponent, - DatasetProfileCriteriaComponent, - FigurecardComponent, - BaseCriteriaComponent, - FileUploaderComponent, - UrlListingComponent, - NgForLimitPipe, - AutoCompleteComponent, - ExternalItemListingComponent, - ExternalItemComponent, - BreadcrumbComponent, - SingleAutoCompleteComponent, - MultipleAutoCompleteComponent, - UserDialogComponent, - FacetSearchComponent, - FacetSearchSectionComponent - ], - entryComponents: [ - UserDialogComponent - ], - -}) - -export class SharedModule { } diff --git a/dmp-frontend/src/app/ui/about/about.component.html b/dmp-frontend/src/app/ui/about/about.component.html new file mode 100644 index 000000000..2c0cdd53d --- /dev/null +++ b/dmp-frontend/src/app/ui/about/about.component.html @@ -0,0 +1,32 @@ +
+
+
+

{{ 'ABOUT.TITLE' | translate}}

+
+
+
+
+

{{ 'ABOUT.MAIN-CONTENT'| translate}}

+
+
+
+
+

{{ 'ABOUT.CONTRIBUTORS'| translate}}

+
+
+
+
+ +
+
+ +
+ +
+ +
+
+ +
+
+
diff --git a/dmp-frontend/src/app/about/components/about.component.scss b/dmp-frontend/src/app/ui/about/about.component.scss similarity index 100% rename from dmp-frontend/src/app/about/components/about.component.scss rename to dmp-frontend/src/app/ui/about/about.component.scss diff --git a/dmp-frontend/src/app/ui/about/about.component.ts b/dmp-frontend/src/app/ui/about/about.component.ts new file mode 100644 index 000000000..e659f69de --- /dev/null +++ b/dmp-frontend/src/app/ui/about/about.component.ts @@ -0,0 +1,18 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-about-componet', + templateUrl: './about.component.html', + styleUrls: ['./about.component.scss'] +}) +export class AboutComponent implements OnInit { + + constructor() { + + } + + ngOnInit() { + } + +} + diff --git a/dmp-frontend/src/app/ui/about/about.module.ts b/dmp-frontend/src/app/ui/about/about.module.ts new file mode 100644 index 000000000..6d7b25b2e --- /dev/null +++ b/dmp-frontend/src/app/ui/about/about.module.ts @@ -0,0 +1,14 @@ +import { NgModule } from '@angular/core'; +import { CommonUiModule } from '../../common/ui/common-ui.module'; +import { AboutComponent } from './about.component'; + +@NgModule({ + imports: [ + CommonUiModule, + AboutComponent + ], + declarations: [ + AboutComponent + ] +}) +export class AboutModule { } diff --git a/dmp-frontend/src/app/ui/about/about.routing.ts b/dmp-frontend/src/app/ui/about/about.routing.ts new file mode 100644 index 000000000..88b82f08d --- /dev/null +++ b/dmp-frontend/src/app/ui/about/about.routing.ts @@ -0,0 +1,16 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { AboutComponent } from './about.component'; + +const routes: Routes = [ + { + path: '', + component: AboutComponent, + }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class AboutRoutingModule { } diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/default-value-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/default-value-editor-model.ts new file mode 100644 index 000000000..99cd6c754 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/default-value-editor-model.ts @@ -0,0 +1,23 @@ +import { FormGroup } from '@angular/forms'; +import { DefaultValue } from '../../../../core/model/admin/dataset-profile/dataset-profile'; +import { BaseFormModel } from '../../../../core/model/base-form-model'; + +export class DefaultValueEditorModel extends BaseFormModel { + public type: string; + public value: string; + + fromModel(item: DefaultValue): DefaultValueEditorModel { + this.type = item.type; + this.value = item.value; + return this; + } + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + type: [this.type], + value: [this.value] + + }); + return formGroup; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/auto-complete-field-data-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/auto-complete-field-data-editor-model.ts new file mode 100644 index 000000000..9bf2a659f --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/auto-complete-field-data-editor-model.ts @@ -0,0 +1,32 @@ +import { FormGroup } from '@angular/forms'; +import { AutoCompleteFieldData } from '../../../../../core/model/dataset-profile-definition/field-data/field-data'; +import { FieldDataEditorModel } from './field-data-editor-model'; +import { FieldDataOptionEditorModel } from './field-data-option-editor-model'; + +export class AutoCompleteFieldDataEditorModel extends FieldDataEditorModel { + + public type: string; + public url: string; + public optionsRoot: string; + public autoCompleteOptions: FieldDataOptionEditorModel = new FieldDataOptionEditorModel(); + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + label: [this.label], + type: [this.type], + url: [this.url], + optionsRoot: [this.optionsRoot] + }); + formGroup.addControl('autoCompleteOptions', this.autoCompleteOptions.buildForm()); + return formGroup; + } + + fromModel(item: AutoCompleteFieldData): AutoCompleteFieldDataEditorModel { + this.type = item.type; + this.url = item.url; + this.label = item.label; + this.optionsRoot = item.optionsRoot; + this.autoCompleteOptions = new FieldDataOptionEditorModel().fromModel(item.autoCompleteOptions); + return this; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/boolean-decision-field-data-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/boolean-decision-field-data-editor-model.ts new file mode 100644 index 000000000..caf0b314f --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/boolean-decision-field-data-editor-model.ts @@ -0,0 +1,18 @@ +import { FormGroup } from '@angular/forms'; +import { BooleanDecisionFieldData } from '../../../../../core/model/dataset-profile-definition/field-data/field-data'; +import { FieldDataEditorModel } from './field-data-editor-model'; + +export class BooleanDecisionFieldDataEditorModel extends FieldDataEditorModel { + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + label: this.label + }); + return formGroup; + } + + fromModel(item: BooleanDecisionFieldData): BooleanDecisionFieldDataEditorModel { + this.label = item.label; + return this; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/check-box-field-data-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/check-box-field-data-editor-model.ts new file mode 100644 index 000000000..b31818399 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/check-box-field-data-editor-model.ts @@ -0,0 +1,18 @@ +import { FormGroup } from '@angular/forms'; +import { CheckBoxFieldData } from '../../../../../core/model/dataset-profile-definition/field-data/field-data'; +import { FieldDataEditorModel } from './field-data-editor-model'; + +export class CheckBoxFieldDataEditorModel extends FieldDataEditorModel { + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + label: this.label + }); + return formGroup; + } + + fromModel(item: CheckBoxFieldData): CheckBoxFieldDataEditorModel { + this.label = item.label; + return this; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/field-data-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/field-data-editor-model.ts new file mode 100644 index 000000000..71b2c620c --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/field-data-editor-model.ts @@ -0,0 +1,16 @@ +import { FormGroup } from '@angular/forms'; +import { BaseFormModel } from '../../../../../core/model/base-form-model'; + +export abstract class FieldDataEditorModel extends BaseFormModel { + + public label: string; + + buildForm(): FormGroup { + throw new Error('Build Form Is not not correctly overriden'); + } + + fromJSONObject(item: any): T { + throw new Error('From Json Object is not correctly overriden'); + } + +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/field-data-option-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/field-data-option-editor-model.ts new file mode 100644 index 000000000..3a97ccfa9 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/field-data-option-editor-model.ts @@ -0,0 +1,21 @@ +import { FormBuilder, FormGroup } from '@angular/forms'; +import { FieldDataOption } from '../../../../../core/model/dataset-profile-definition/field-data/field-data'; +import { FieldDataEditorModel } from './field-data-editor-model'; + +export class FieldDataOptionEditorModel extends FieldDataEditorModel { + public label: string; + public value: string; + + buildForm(): FormGroup { + return new FormBuilder().group({ + label: [this.label], + value: [this.value] + }); + } + + fromModel(item: FieldDataOption): FieldDataOptionEditorModel { + this.label = item.label; + this.value = item.value; + return this; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/free-text-field-data-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/free-text-field-data-editor-model.ts new file mode 100644 index 000000000..884db0f1b --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/free-text-field-data-editor-model.ts @@ -0,0 +1,18 @@ +import { FormGroup } from '@angular/forms'; +import { FreeTextFieldData } from '../../../../../core/model/dataset-profile-definition/field-data/field-data'; +import { FieldDataEditorModel } from './field-data-editor-model'; + +export class FreeTextFieldDataEditorModel extends FieldDataEditorModel { + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + label: this.label + }); + return formGroup; + } + + fromModel(item: FreeTextFieldData): FreeTextFieldDataEditorModel { + this.label = item.label; + return this; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/radio-box-field-data-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/radio-box-field-data-editor-model.ts new file mode 100644 index 000000000..a9dfde1f5 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/radio-box-field-data-editor-model.ts @@ -0,0 +1,30 @@ +import { FormGroup } from '@angular/forms'; +import { RadioBoxFieldData } from '../../../../../core/model/dataset-profile-definition/field-data/field-data'; +import { FieldDataEditorModel } from './field-data-editor-model'; +import { FieldDataOptionEditorModel } from './field-data-option-editor-model'; + +export class RadioBoxFieldDataEditorModel extends FieldDataEditorModel { + + public options: Array = []; + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + label: [this.label] + }); + const optionsFormArray = new Array(); + if (this.options) { + this.options.forEach(item => { + const form: FormGroup = item.buildForm(); + optionsFormArray.push(form); + }); + } + formGroup.addControl('options', this.formBuilder.array(optionsFormArray)); + return formGroup; + } + + fromModel(item: RadioBoxFieldData): RadioBoxFieldDataEditorModel { + if (item.options) { this.options = item.options.map(x => new FieldDataOptionEditorModel().fromModel(x)); } + this.label = item.label; + return this; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/text-area-field-data-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/text-area-field-data-editor-model.ts new file mode 100644 index 000000000..2a746176c --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/text-area-field-data-editor-model.ts @@ -0,0 +1,18 @@ +import { FormGroup } from '@angular/forms'; +import { TextAreaFieldData } from '../../../../../core/model/dataset-profile-definition/field-data/field-data'; +import { FieldDataEditorModel } from './field-data-editor-model'; + +export class TextAreaFieldDataEditorModel extends FieldDataEditorModel { + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + label: this.label + }); + return formGroup; + } + + fromModel(item: TextAreaFieldData): TextAreaFieldDataEditorModel { + this.label = item.label; + return this; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/word-list-field-data-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/word-list-field-data-editor-model.ts new file mode 100644 index 000000000..174dc758e --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/word-list-field-data-editor-model.ts @@ -0,0 +1,34 @@ +import { FormGroup } from '@angular/forms'; +import { DatasetProfileComboBoxType } from '../../../../../core/common/enum/dataset-profile-combo-box-type'; +import { WordListFieldData } from '../../../../../core/model/dataset-profile-definition/field-data/field-data'; +import { FieldDataEditorModel } from './field-data-editor-model'; +import { FieldDataOptionEditorModel } from './field-data-option-editor-model'; + +export class WordListFieldDataEditorModel extends FieldDataEditorModel { + public type: DatasetProfileComboBoxType; + public options: Array; + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + type: [this.type], + label: [this.label] + }); + const optionsFormArray = new Array(); + if (this.options) { + this.options.forEach(item => { + const form: FormGroup = item.buildForm(); + optionsFormArray.push(form); + }); + } + formGroup.addControl('options', this.formBuilder.array(optionsFormArray)); + + return formGroup; + } + + fromModel(item: WordListFieldData): WordListFieldDataEditorModel { + this.type = item.type; + if (item.options) { this.options = item.options.map(x => new FieldDataOptionEditorModel().fromModel(x)); } + this.label = item.label; + return this; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-editor-model.ts new file mode 100644 index 000000000..3ba94c5da --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-editor-model.ts @@ -0,0 +1,76 @@ +import { FormArray, FormControl, FormGroup } from '@angular/forms'; +import { ValidationType } from '../../../../core/common/enum/validation-type'; +import { Field } from '../../../../core/model/admin/dataset-profile/dataset-profile'; +import { BaseFormModel } from '../../../../core/model/base-form-model'; +import { DefaultValueEditorModel } from './default-value-editor-model'; +import { AutoCompleteFieldDataEditorModel } from './field-data/auto-complete-field-data-editor-model'; +import { BooleanDecisionFieldDataEditorModel } from './field-data/boolean-decision-field-data-editor-model'; +import { CheckBoxFieldDataEditorModel } from './field-data/check-box-field-data-editor-model'; +import { FieldDataEditorModel } from './field-data/field-data-editor-model'; +import { FreeTextFieldDataEditorModel } from './field-data/free-text-field-data-editor-model'; +import { RadioBoxFieldDataEditorModel } from './field-data/radio-box-field-data-editor-model'; +import { TextAreaFieldDataEditorModel } from './field-data/text-area-field-data-editor-model'; +import { WordListFieldDataEditorModel } from './field-data/word-list-field-data-editor-model'; +import { ViewStyleEditorModel } from './view-style-editor-model'; +import { VisibilityEditorModel } from './visibility-editor-model'; + +export class FieldEditorModel extends BaseFormModel { + + public id: string; + // public title: string; + public defaultValue: DefaultValueEditorModel = new DefaultValueEditorModel(); + public viewStyle: ViewStyleEditorModel = new ViewStyleEditorModel(); + public page: number; + public ordinal: number; + public visible: VisibilityEditorModel = new VisibilityEditorModel(); + public data: FieldDataEditorModel; + public validations: ValidationType[]; + + fromModel(item: Field): FieldEditorModel { + this.id = item.id; + if (item.defaultValue) { this.defaultValue = new DefaultValueEditorModel().fromModel(item.defaultValue); } + this.page = item.page; + this.ordinal = item.ordinal; + this.validations = item.validations; + this.viewStyle = new ViewStyleEditorModel().fromModel(item.viewStyle); + this.visible = new VisibilityEditorModel().fromModel(item.visible); + + if (item.data) { + if (this.viewStyle.renderStyle === 'combobox') { + if (item.data.type === 'autocomplete') { this.data = new AutoCompleteFieldDataEditorModel().fromModel(item.data); } + if (item.data.type === 'wordlist') { this.data = new WordListFieldDataEditorModel().fromModel(item.data); } + } else { + if (this.viewStyle.renderStyle === 'radiobox') { this.data = new RadioBoxFieldDataEditorModel().fromModel(item.data); } + if (this.viewStyle.renderStyle === 'checkBox') { this.data = new CheckBoxFieldDataEditorModel().fromModel(item.data); } + if (this.viewStyle.renderStyle === 'textarea') { this.data = new TextAreaFieldDataEditorModel().fromModel(item.data); } + if (this.viewStyle.renderStyle === 'freetext') { this.data = new FreeTextFieldDataEditorModel().fromModel(item.data); } + if (this.viewStyle.renderStyle === 'booleanDecision') { this.data = new BooleanDecisionFieldDataEditorModel().fromModel(item.data); } + } + } + return this; + } + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + id: [this.id], + // title: [this.title], + page: [this.page], + ordinal: [this.ordinal] + }); + let valid = ValidationType.None; + if (this.validations && this.validations[0] === 1) { valid = ValidationType.Required; } + const arr = new FormArray([ + new FormControl(valid) + ]); + + // formGroup.addControl("multiplicity", this.multiplicity.buildForm()); + formGroup.addControl('validations', new FormControl(this.validations)); + formGroup.addControl('defaultValue', this.defaultValue.buildForm()); + formGroup.addControl('viewStyle', this.viewStyle.buildForm()); + formGroup.addControl('visible', this.visible.buildForm()); + //formGroup.addControl("data",this.data? this.data.buildForm():this.formBuilder.group({})); + if (this.data) { formGroup.addControl('data', this.data.buildForm()); } + + return formGroup; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-set-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-set-editor-model.ts new file mode 100644 index 000000000..9e3d31a44 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-set-editor-model.ts @@ -0,0 +1,52 @@ + +import { FormGroup } from '@angular/forms'; +import { FieldSet } from '../../../../core/model/admin/dataset-profile/dataset-profile'; +import { BaseFormModel } from '../../../../core/model/base-form-model'; +import { FieldEditorModel } from './field-editor-model'; +import { MultiplicityEditorModel } from './multiplicity-editor-model'; + +export class FieldSetEditorModel extends BaseFormModel { + + public fields: Array = new Array(); + public id: string; + public ordinal: number; + public multiplicity: MultiplicityEditorModel = new MultiplicityEditorModel(); + public title: string; + public description: string; + public extendedDescription: string; + public hasCommentField: boolean; + + fromModel(item: FieldSet): FieldSetEditorModel { + + if (item.fields) { this.fields = item.fields.map(x => new FieldEditorModel().fromModel(x)); } + if (item.multiplicity) this.multiplicity = new MultiplicityEditorModel().fromModel(item.multiplicity); + this.id = item.id; + this.ordinal = item.ordinal; + this.title = item.title; + this.description = item.description; + this.extendedDescription = item.extendedDescription; + this.hasCommentField = item.hasCommentField; + return this; + } + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + id: [this.id], + ordinal: [this.ordinal], + title: [this.title], + description: [this.description], + extendedDescription: [this.extendedDescription], + hasCommentField: [this.hasCommentField] + }); + + const fieldsFormArray = new Array(); + this.fields.forEach(item => { + const form: FormGroup = item.buildForm(); + fieldsFormArray.push(form); + }); + formGroup.addControl('fields', this.formBuilder.array(fieldsFormArray)); + formGroup.addControl('multiplicity', this.multiplicity.buildForm()); + + return formGroup; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/multiplicity-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/multiplicity-editor-model.ts new file mode 100644 index 000000000..fbbd0207d --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/multiplicity-editor-model.ts @@ -0,0 +1,22 @@ +import { FormGroup } from '@angular/forms'; +import { Multiplicity } from '../../../../core/model/admin/dataset-profile/dataset-profile'; +import { BaseFormModel } from '../../../../core/model/base-form-model'; + +export class MultiplicityEditorModel extends BaseFormModel { + public min: number; + public max: number; + + fromModel(item: Multiplicity): MultiplicityEditorModel { + this.min = item.min; + this.max = item.max; + return this; + } + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + min: [this.min], + max: [this.max] + }); + return formGroup; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/page-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/page-editor-model.ts new file mode 100644 index 000000000..bf821ae0f --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/page-editor-model.ts @@ -0,0 +1,31 @@ +import { FormGroup } from '@angular/forms'; +import { Page } from '../../../../core/model/admin/dataset-profile/dataset-profile'; +import { BaseFormModel } from '../../../../core/model/base-form-model'; + +export class PageEditorModel extends BaseFormModel { + public title: string; + public id: string; + public ordinal: number; + + constructor(ordinal?: number) { + super(); + if (isNaN(ordinal)) { this.ordinal = 0; } else { this.ordinal = ordinal; } + this.id = 'page_' + this.ordinal; + } + + fromModel(item: Page): PageEditorModel { + this.title = item.title; + this.id = item.id; + this.ordinal = item.ordinal; + return this; + } + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + title: [this.title], + id: [this.id], + ordinal: [this.ordinal] + }); + return formGroup; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/rule-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/rule-editor-model.ts new file mode 100644 index 000000000..b4d1ad698 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/rule-editor-model.ts @@ -0,0 +1,32 @@ +import { FormGroup } from "@angular/forms"; +import { Rule } from "../../../../core/model/admin/dataset-profile/dataset-profile"; +import { BaseFormModel } from "../../../../core/model/base-form-model"; + +export class RuleEditorModel extends BaseFormModel { + public target: string; + public value: string; + public ruleType: string; + public ruleStyle: string; + public valueType: string; + + fromModel(item: Rule): RuleEditorModel { + this.target = item.target; + this.value = item.value; + this.ruleType = item.ruleType; + this.ruleStyle = item.ruleStyle; + this.valueType = item.valueType; + return this; + } + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + // sourceField: [this.sourceField], + target: [this.target], + ruleStyle: [this.ruleStyle], + value: [this.value], + ruleType: [this.ruleType], + valueType: [this.valueType] + }); + return formGroup; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/section-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/section-editor-model.ts new file mode 100644 index 000000000..2f2cb6569 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/section-editor-model.ts @@ -0,0 +1,58 @@ +import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; +import { Section } from '../../../../core/model/admin/dataset-profile/dataset-profile'; +import { BaseFormModel } from '../../../../core/model/base-form-model'; +import { FieldSetEditorModel } from './field-set-editor-model'; + +export class SectionEditorModel extends BaseFormModel { + public sections: Array = new Array(); + public defaultVisibility: boolean; + public page: string; + public id: string; + public title: string; + public description: string; + public ordinal: number; + public fieldSets: Array = new Array(); + + fromModel(item: Section): SectionEditorModel { + if (item.sections) { this.sections = item.sections.map(x => new SectionEditorModel().fromModel(x)); } + this.page = item.page; + this.defaultVisibility = item.defaultVisibility; + this.id = item.id; + this.title = item.title; + this.description = item.description; + this.ordinal = item.ordinal; + if (item.fieldSets) { this.fieldSets = item.fieldSets.map(x => new FieldSetEditorModel().fromModel(x)); } + return this; + } + + buildForm(): FormGroup { + const formGroup: FormGroup = new FormBuilder().group({}); + const sectionsFormArray = new Array(); + if (this.sections) { + this.sections.forEach(item => { + const form: FormGroup = item.buildForm(); + sectionsFormArray.push(form); + }); + } + const compositeFieldsFormArray = new Array(); + if (this.fieldSets) { + this.fieldSets.forEach(item => { + const form: FormGroup = item.buildForm(); + compositeFieldsFormArray.push(form); + }); + } + + formGroup.addControl('sections', this.formBuilder.array(sectionsFormArray)); + formGroup.addControl('fieldSets', this.formBuilder.array(compositeFieldsFormArray)); + formGroup.addControl('defaultVisibility', new FormControl(this.defaultVisibility)); + formGroup.addControl('page', new FormControl(this.page, [Validators.required])); + formGroup.addControl('id', new FormControl(this.id)); + formGroup.addControl('title', new FormControl(this.title)); + formGroup.addControl('description', new FormControl(this.description)); + formGroup.addControl('ordinal', new FormControl(this.ordinal)); + + if (!formGroup.controls['defaultVisibility'].value) { formGroup.controls['defaultVisibility'].setValue(true); } + + return formGroup; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/view-style-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/view-style-editor-model.ts new file mode 100644 index 000000000..89eb6087e --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/view-style-editor-model.ts @@ -0,0 +1,23 @@ +import { FormGroup } from "@angular/forms"; +import { ViewStyle } from "../../../../core/model/admin/dataset-profile/dataset-profile"; +import { BaseFormModel } from "../../../../core/model/base-form-model"; + +export class ViewStyleEditorModel extends BaseFormModel { + public cssClass: string; + public renderStyle: string; + + fromModel(item: ViewStyle): ViewStyleEditorModel { + this.cssClass = item.cssClass; + this.renderStyle = item.renderStyle; + return this; + } + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + cssClass: [this.cssClass], + renderStyle: [this.renderStyle] + + }); + return formGroup; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/visibility-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/visibility-editor-model.ts new file mode 100644 index 000000000..9068bf021 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/visibility-editor-model.ts @@ -0,0 +1,36 @@ +import { FormGroup } from '@angular/forms'; +import { Visibility } from '../../../../core/model/admin/dataset-profile/dataset-profile'; +import { BaseFormModel } from '../../../../core/model/base-form-model'; +import { RuleEditorModel } from './rule-editor-model'; + +export class VisibilityEditorModel extends BaseFormModel { + + public rules: Array = new Array(); + public style: string; + + fromModel(item: Visibility): VisibilityEditorModel { + if (item.rules) { this.rules = item.rules.map(x => new RuleEditorModel().fromModel(x)); } + this.style = item.style; + + return this; + } + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + style: [this.style] + }); + + const rulesFormArray = new Array(); + if (this.rules) { + this.rules.forEach(rule => { + const form: FormGroup = rule.buildForm(); + rulesFormArray.push(form); + }); + } + + formGroup.addControl('rules', this.formBuilder.array(rulesFormArray)); + + return formGroup; + } + +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts new file mode 100644 index 000000000..3d8968f85 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts @@ -0,0 +1,52 @@ +import { NgModule } from '@angular/core'; +import { CommonFormsModule } from '../../../common/forms/common-forms.module'; +import { CommonUiModule } from '../../../common/ui/common-ui.module'; +import { FormattingModule } from '../../../core/formatting.module'; +import { DatasetProfileRoutingModule } from './dataset-profile.routing'; +import { DatasetProfileEditorCompositeFieldComponent } from './editor/components/composite-field/dataset-profile-editor-composite-field.component'; +import { DatasetProfileEditorAutoCompleteFieldComponent } from './editor/components/field-type/auto-complete/dataset-profile-editor-auto-complete-field.component'; +import { DatasetProfileEditorBooleanDecisionFieldComponent } from './editor/components/field-type/boolean-decision/dataset-profile-editor-boolean-decision-field.component'; +import { DatasetProfileEditorCheckboxFieldComponent } from './editor/components/field-type/checkbox/dataset-profile-editor-checkbox-field.component'; +import { DatasetProfileEditorComboBoxFieldComponent } from './editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component'; +import { DatasetProfileEditorFreeTextFieldComponent } from './editor/components/field-type/free-text/dataset-profile-editor-free-text-field.component'; +import { DatasetProfileEditorRadioBoxFieldComponent } from './editor/components/field-type/radio-box/dataset-profile-editor-radio-box-field.component'; +import { DatasetProfileEditorTextAreaFieldComponent } from './editor/components/field-type/textarea/dataset-profile-editor-text-area-field.component'; +import { DatasetProfileEditorWordListFieldComponent } from './editor/components/field-type/word-list/dataset-profile-editor-word-list-field.component'; +import { DatasetProfileEditorFieldComponent } from './editor/components/field/dataset-profile-editor-field.component'; +import { DatasetProfileEditorPageComponent } from './editor/components/page/dataset-profile-editor-page.component'; +import { DatasetProfileEditorRuleComponent } from './editor/components/rule/dataset-profile-editor-rule.component'; +import { DatasetProfileEditorSectionComponent } from './editor/components/section/dataset-profile-editor-section.component'; +import { DatasetProfileEditorComponent } from './editor/dataset-profile-editor.component'; +import { DatasetProfileCriteriaComponent } from './listing/criteria/dataset-profile.component'; +import { DatasetProfileListingComponent } from './listing/dataset-profile-listing.component'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule, + FormattingModule, + DatasetProfileRoutingModule + ], + declarations: [ + DatasetProfileListingComponent, + DatasetProfileCriteriaComponent, + DatasetProfileEditorComponent, + DatasetProfileEditorSectionComponent, + DatasetProfileEditorCompositeFieldComponent, + DatasetProfileEditorFieldComponent, + DatasetProfileEditorPageComponent, + DatasetProfileEditorRuleComponent, + DatasetProfileEditorAutoCompleteFieldComponent, + DatasetProfileEditorBooleanDecisionFieldComponent, + DatasetProfileEditorCheckboxFieldComponent, + DatasetProfileEditorComboBoxFieldComponent, + DatasetProfileEditorFreeTextFieldComponent, + DatasetProfileEditorRadioBoxFieldComponent, + DatasetProfileEditorTextAreaFieldComponent, + DatasetProfileEditorWordListFieldComponent + ], + entryComponents: [ + ] +}) +export class DatasetProfileModule { } + diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.routing.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.routing.ts new file mode 100644 index 000000000..3fe6a4520 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.routing.ts @@ -0,0 +1,29 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { DatasetProfileEditorComponent } from './editor/dataset-profile-editor.component'; +import { DatasetProfileListingComponent } from './listing/dataset-profile-listing.component'; + +const routes: Routes = [ + { + path: 'new', + component: DatasetProfileEditorComponent + }, + { + path: ':id', + component: DatasetProfileEditorComponent + }, + { + path: 'clone/:cloneid', + component: DatasetProfileEditorComponent + }, + { + path: '', + component: DatasetProfileListingComponent, + }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class DatasetProfileRoutingModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.html new file mode 100644 index 000000000..9ddcd688c --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.html @@ -0,0 +1,55 @@ +
+

{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.TITLE' | translate}}

+

{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.SIMPLE-FIELD-TITLE' | translate}}

+ {{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.COMPOSITE-CHECKBOX' | translate}} + {{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.MULTIPLICITY-CHECKBOX' | translate}} + {{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.COMMENT-CHECKBOX' | translate}} +
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
+

{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.SUB-FIELDS-TITLE' | translate}}

+
+ + + {{i + 1}}. {{getFieldTile(field, i)}} +
+ +
+
+
+ +
+
+
+
+
diff --git a/dmp-frontend/src/app/dataset-profile-form/compositefield-form/compositefield-form.component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.scss similarity index 100% rename from dmp-frontend/src/app/dataset-profile-form/compositefield-form/compositefield-form.component.scss rename to dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.scss diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.ts new file mode 100644 index 000000000..d74872513 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.ts @@ -0,0 +1,59 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormArray, FormControl, FormGroup } from '@angular/forms'; +import { FieldEditorModel } from '../../../admin/field-editor-model'; + +@Component({ + selector: 'app-dataset-profile-editor-composite-field-component', + templateUrl: './dataset-profile-editor-composite-field.component.html', + styleUrls: ['./dataset-profile-editor-composite-field.component.scss'] +}) +export class DatasetProfileEditorCompositeFieldComponent implements OnInit { + + @Input() form: FormGroup; + @Input() indexPath: string; + + isComposite = false; + isMultiplicityEnabled = false; + + constructor() { } + + ngOnInit() { + //this.addNewField(); + if (this.form.get('multiplicity')) { + if (this.form.get('multiplicity').value.min > 1 || this.form.get('multiplicity').value.max > 1) { + this.isMultiplicityEnabled = true; + } + } + this.isComposite = (this.form.get('fields') as FormArray).length > 1; + } + + onIsCompositeChange(isComposite: boolean) { + if (!isComposite && (this.form.get('fields')).length > 1) { + for (let i = 0; i < (this.form.get('fields')).length - 1; i++) { + (this.form.get('fields')).removeAt(1); + } + (this.form.get('fields') as FormArray).controls.splice(1); + } + } + + onIsMultiplicityEnabledChange(isMultiplicityEnabled: boolean) { + if (!isMultiplicityEnabled) { + (this.form.get('multiplicity').get('min')).setValue(0); + (this.form.get('multiplicity').get('max')).setValue(0); + } + } + + addNewField() { + const field: FieldEditorModel = new FieldEditorModel(); + (this.form.get('fields')).push(field.buildForm()); + } + + DeleteField(index) { + (this.form.get('fields')).removeAt(index); + } + + getFieldTile(formGroup: FormGroup, index: number) { + if (formGroup.get('title') && formGroup.get('title').value && formGroup.get('title').value.length > 0) { return formGroup.get('title').value; } + return "Field " + (index + 1); + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/auto-complete/dataset-profile-editor-auto-complete-field.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/auto-complete/dataset-profile-editor-auto-complete-field.component.html new file mode 100644 index 000000000..bf6e6b8d0 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/auto-complete/dataset-profile-editor-auto-complete-field.component.html @@ -0,0 +1,20 @@ +
+ +
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-AUTOCOMPLETE-TITLE' | translate}}
+ + + + + + + + + + + + + + + + +
diff --git a/dmp-frontend/src/app/dataset-profile-form/page-form/page-component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/auto-complete/dataset-profile-editor-auto-complete-field.component.scss similarity index 100% rename from dmp-frontend/src/app/dataset-profile-form/page-form/page-component.scss rename to dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/auto-complete/dataset-profile-editor-auto-complete-field.component.scss diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/auto-complete/dataset-profile-editor-auto-complete-field.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/auto-complete/dataset-profile-editor-auto-complete-field.component.ts new file mode 100644 index 000000000..579b22214 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/auto-complete/dataset-profile-editor-auto-complete-field.component.ts @@ -0,0 +1,20 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { DatasetProfileComboBoxType } from '../../../../../../../core/common/enum/dataset-profile-combo-box-type'; +import { AutoCompleteFieldDataEditorModel } from '../../../../admin/field-data/auto-complete-field-data-editor-model'; + +@Component({ + selector: 'app-dataset-profile-editor-auto-complete-field-component', + styleUrls: ['./dataset-profile-editor-auto-complete-field.component.scss'], + templateUrl: './dataset-profile-editor-auto-complete-field.component.html' +}) +export class DatasetProfileEditorAutoCompleteFieldComponent implements OnInit { + + @Input() form: FormGroup; + private data: AutoCompleteFieldDataEditorModel = new AutoCompleteFieldDataEditorModel(); + + ngOnInit() { + this.data.type = DatasetProfileComboBoxType.Autocomplete; + if (!this.form.get('data')) { this.form.addControl('data', this.data.buildForm()); } + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/boolean-decision/dataset-profile-editor-boolean-decision-field.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/boolean-decision/dataset-profile-editor-boolean-decision-field.component.html new file mode 100644 index 000000000..66105b839 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/boolean-decision/dataset-profile-editor-boolean-decision-field.component.html @@ -0,0 +1,8 @@ +
+ +
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-BOOLEAN-DECISION-TITLE' | translate}}
+ + + + +
diff --git a/dmp-frontend/src/app/dataset-profile-form/rule-component/rule.component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/boolean-decision/dataset-profile-editor-boolean-decision-field.component.scss similarity index 100% rename from dmp-frontend/src/app/dataset-profile-form/rule-component/rule.component.scss rename to dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/boolean-decision/dataset-profile-editor-boolean-decision-field.component.scss diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/boolean-decision/dataset-profile-editor-boolean-decision-field.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/boolean-decision/dataset-profile-editor-boolean-decision-field.component.ts new file mode 100644 index 000000000..826f46f69 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/boolean-decision/dataset-profile-editor-boolean-decision-field.component.ts @@ -0,0 +1,19 @@ + +import { Component, Input, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { BooleanDecisionFieldDataEditorModel } from '../../../../admin/field-data/boolean-decision-field-data-editor-model'; + +@Component({ + selector: 'app-dataset-profile-editor-boolean-decision-field-component', + styleUrls: ['./dataset-profile-editor-boolean-decision-field.component.scss'], + templateUrl: './dataset-profile-editor-boolean-decision-field.component.html' +}) +export class DatasetProfileEditorBooleanDecisionFieldComponent implements OnInit { + + @Input() form: FormGroup; + private data: BooleanDecisionFieldDataEditorModel = new BooleanDecisionFieldDataEditorModel(); + + ngOnInit() { + if (!this.form.get('data')) { this.form.addControl('data', this.data.buildForm()); } + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/checkbox/dataset-profile-editor-checkbox-field.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/checkbox/dataset-profile-editor-checkbox-field.component.html new file mode 100644 index 000000000..cb2d82d7f --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/checkbox/dataset-profile-editor-checkbox-field.component.html @@ -0,0 +1,8 @@ +
+ +
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CHECKBOX-TITLE' | translate}}
+ + + + +
diff --git a/dmp-frontend/src/app/shared/componentsAdmin/autocomplete/autocomplete-component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/checkbox/dataset-profile-editor-checkbox-field.component.scss similarity index 100% rename from dmp-frontend/src/app/shared/componentsAdmin/autocomplete/autocomplete-component.scss rename to dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/checkbox/dataset-profile-editor-checkbox-field.component.scss diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/checkbox/dataset-profile-editor-checkbox-field.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/checkbox/dataset-profile-editor-checkbox-field.component.ts new file mode 100644 index 000000000..2cc7d6c30 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/checkbox/dataset-profile-editor-checkbox-field.component.ts @@ -0,0 +1,18 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { CheckBoxFieldDataEditorModel } from '../../../../admin/field-data/check-box-field-data-editor-model'; + +@Component({ + selector: 'app-dataset-profile-editor-checkbox-field-component', + styleUrls: ['./dataset-profile-editor-checkbox-field.component.scss'], + templateUrl: './dataset-profile-editor-checkbox-field.component.html' +}) +export class DatasetProfileEditorCheckboxFieldComponent implements OnInit { + + @Input() form: FormGroup; + private data: CheckBoxFieldDataEditorModel = new CheckBoxFieldDataEditorModel(); + + ngOnInit() { + if (!this.form.get('data')) { this.form.addControl('data', this.data.buildForm()); } + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component.html new file mode 100644 index 000000000..014c776f1 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component.html @@ -0,0 +1,10 @@ +
+ + + {{enumUtils.toDatasetProfileComboBoxTypeString(options.Autocomplete)}} + {{enumUtils.toDatasetProfileComboBoxTypeString(options.WordList)}} + + + + +
diff --git a/dmp-frontend/src/app/shared/componentsAdmin/booleanDecision/booleanDecision-component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component.scss similarity index 100% rename from dmp-frontend/src/app/shared/componentsAdmin/booleanDecision/booleanDecision-component.scss rename to dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component.scss diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component.ts new file mode 100644 index 000000000..8e6feb7b5 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component.ts @@ -0,0 +1,29 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { DatasetProfileComboBoxType } from '../../../../../../../core/common/enum/dataset-profile-combo-box-type'; +import { EnumUtils } from '../../../../../../../core/services/utilities/enum-utils.service'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../../../../core/common/base/base.component'; + +@Component({ + selector: 'app-dataset-profile-editor-combo-box-field-component', + styleUrls: ['./dataset-profile-editor-combo-box-field.component.scss'], + templateUrl: './dataset-profile-editor-combo-box-field.component.html' +}) +export class DatasetProfileEditorComboBoxFieldComponent extends BaseComponent implements OnInit { + + @Input() form: FormGroup; + options = DatasetProfileComboBoxType; + + constructor( + public enumUtils: EnumUtils + ) { super(); } + + ngOnInit() { + this.form.get('data').get('type').valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => { + if (this.form.get('data')) { this.form.removeControl('data'); } + }) + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/free-text/dataset-profile-editor-free-text-field.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/free-text/dataset-profile-editor-free-text-field.component.html new file mode 100644 index 000000000..4e285a97f --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/free-text/dataset-profile-editor-free-text-field.component.html @@ -0,0 +1,8 @@ +
+ +
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-FREE-TEXT-TITLE' | translate}}
+ + + + +
diff --git a/dmp-frontend/src/app/shared/componentsAdmin/checkbox/checkbox-component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/free-text/dataset-profile-editor-free-text-field.component.scss similarity index 100% rename from dmp-frontend/src/app/shared/componentsAdmin/checkbox/checkbox-component.scss rename to dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/free-text/dataset-profile-editor-free-text-field.component.scss diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/free-text/dataset-profile-editor-free-text-field.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/free-text/dataset-profile-editor-free-text-field.component.ts new file mode 100644 index 000000000..1d6e752c4 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/free-text/dataset-profile-editor-free-text-field.component.ts @@ -0,0 +1,18 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { FreeTextFieldDataEditorModel } from '../../../../admin/field-data/free-text-field-data-editor-model'; + +@Component({ + selector: 'app-dataset-profile-editor-free-text-field-component', + styleUrls: ['./dataset-profile-editor-free-text-field.component.scss'], + templateUrl: './dataset-profile-editor-free-text-field.component.html' +}) +export class DatasetProfileEditorFreeTextFieldComponent implements OnInit { + + @Input() form: FormGroup; + private data: FreeTextFieldDataEditorModel = new FreeTextFieldDataEditorModel(); + + ngOnInit() { + if (!this.form.get('data')) { this.form.addControl('data', this.data.buildForm()); } + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/radio-box/dataset-profile-editor-radio-box-field.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/radio-box/dataset-profile-editor-radio-box-field.component.html new file mode 100644 index 000000000..7a1d7035d --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/radio-box/dataset-profile-editor-radio-box-field.component.html @@ -0,0 +1,22 @@ +
+ +
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-RADIO-BOX-TITLE' | translate}}
+ + + + + +
+
+ + + + + + +
+
+
+ add +
+
diff --git a/dmp-frontend/src/app/shared/componentsAdmin/combobox/combobox-component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/radio-box/dataset-profile-editor-radio-box-field.component.scss similarity index 100% rename from dmp-frontend/src/app/shared/componentsAdmin/combobox/combobox-component.scss rename to dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/radio-box/dataset-profile-editor-radio-box-field.component.scss diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/radio-box/dataset-profile-editor-radio-box-field.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/radio-box/dataset-profile-editor-radio-box-field.component.ts new file mode 100644 index 000000000..66a9c8461 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/radio-box/dataset-profile-editor-radio-box-field.component.ts @@ -0,0 +1,25 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormArray, FormBuilder, FormGroup } from '@angular/forms'; +import { FieldDataOptionEditorModel } from '../../../../admin/field-data/field-data-option-editor-model'; +import { RadioBoxFieldDataEditorModel } from '../../../../admin/field-data/radio-box-field-data-editor-model'; + +@Component({ + selector: 'app-dataset-profile-editor-radio-box-field-component', + styleUrls: ['./dataset-profile-editor-radio-box-field.component.scss'], + templateUrl: './dataset-profile-editor-radio-box-field.component.html' +}) +export class DatasetProfileEditorRadioBoxFieldComponent implements OnInit { + + @Input() form: FormGroup; + private data: RadioBoxFieldDataEditorModel = new RadioBoxFieldDataEditorModel(); + + ngOnInit() { + if (!this.form.get('data')) { this.form.addControl('data', this.data.buildForm()); } + } + + addNewRow() { + const radioListOptions: FieldDataOptionEditorModel = new FieldDataOptionEditorModel(); + if (!this.form.get('data').get('options')) { (this.form.get('data')).addControl('options', new FormBuilder().array([])); } + (this.form.get('data').get('options')).push(radioListOptions.buildForm()); + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/textarea/dataset-profile-editor-text-area-field.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/textarea/dataset-profile-editor-text-area-field.component.html new file mode 100644 index 000000000..1ab7e71c1 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/textarea/dataset-profile-editor-text-area-field.component.html @@ -0,0 +1,8 @@ +
+ +
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-TEXT-AREA-TITLE' | translate}}
+ + + + +
diff --git a/dmp-frontend/src/app/shared/componentsAdmin/freetext/freetext-component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/textarea/dataset-profile-editor-text-area-field.component.scss similarity index 100% rename from dmp-frontend/src/app/shared/componentsAdmin/freetext/freetext-component.scss rename to dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/textarea/dataset-profile-editor-text-area-field.component.scss diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/textarea/dataset-profile-editor-text-area-field.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/textarea/dataset-profile-editor-text-area-field.component.ts new file mode 100644 index 000000000..d59b9b977 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/textarea/dataset-profile-editor-text-area-field.component.ts @@ -0,0 +1,18 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { TextAreaFieldDataEditorModel } from '../../../../admin/field-data/text-area-field-data-editor-model'; + +@Component({ + selector: 'app-dataset-profile-editor-text-area-field-component', + styleUrls: ['./dataset-profile-editor-text-area-field.component.scss'], + templateUrl: './dataset-profile-editor-text-area-field.component.html' +}) +export class DatasetProfileEditorTextAreaFieldComponent implements OnInit { + + @Input() form: FormGroup; + private data: TextAreaFieldDataEditorModel = new TextAreaFieldDataEditorModel(); + + ngOnInit() { + if (!this.form.get('data')) { this.form.addControl('data', this.data.buildForm()); } + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/word-list/dataset-profile-editor-word-list-field.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/word-list/dataset-profile-editor-word-list-field.component.html new file mode 100644 index 000000000..bcca0780c --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/word-list/dataset-profile-editor-word-list-field.component.html @@ -0,0 +1,22 @@ +
+ +
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-WORD-LIST-TITLE' | translate}}
+ + + + + +
+
+ + + + + + +
+
+
+
diff --git a/dmp-frontend/src/app/shared/componentsAdmin/radiobox/radiobox-component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/word-list/dataset-profile-editor-word-list-field.component.scss similarity index 100% rename from dmp-frontend/src/app/shared/componentsAdmin/radiobox/radiobox-component.scss rename to dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/word-list/dataset-profile-editor-word-list-field.component.scss diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/word-list/dataset-profile-editor-word-list-field.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/word-list/dataset-profile-editor-word-list-field.component.ts new file mode 100644 index 000000000..caa18cdee --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/word-list/dataset-profile-editor-word-list-field.component.ts @@ -0,0 +1,26 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormArray, FormGroup } from '@angular/forms'; +import { DatasetProfileComboBoxType } from '../../../../../../../core/common/enum/dataset-profile-combo-box-type'; +import { FieldDataOptionEditorModel } from '../../../../admin/field-data/field-data-option-editor-model'; +import { WordListFieldDataEditorModel } from '../../../../admin/field-data/word-list-field-data-editor-model'; + +@Component({ + selector: 'app-dataset-profile-editor-word-list-field-component', + styleUrls: ['./dataset-profile-editor-word-list-field.component.scss'], + templateUrl: './dataset-profile-editor-word-list-field.component.html' +}) +export class DatasetProfileEditorWordListFieldComponent implements OnInit { + + @Input() form: FormGroup; + private data: WordListFieldDataEditorModel = new WordListFieldDataEditorModel(); + + ngOnInit() { + this.data.type = DatasetProfileComboBoxType.WordList; + if (!this.form.get('data')) { this.form.addControl('data', this.data.buildForm()); } + } + + addNewRow() { + const wordListOptions: FieldDataOptionEditorModel = new FieldDataOptionEditorModel(); + (this.form.get('data').get('options')).push(wordListOptions.buildForm()); + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.html new file mode 100644 index 000000000..25a6e59dd --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.html @@ -0,0 +1,49 @@ +
+ + + + + + + {{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.BooleanDecision)}} + {{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.CheckBox)}} + {{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.ComboBox)}} + {{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.FreeText)}} + {{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.RadioBox)}} + {{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.TextArea)}} + + + + + + + + + + + {{enumUtils.toDatasetProfileFieldValidationTypeString(option)}} + + +
+
+ {{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.MULTIPLICITY-CHECKBOX' | translate}} + + + + + + +
+
+ + + + + + +
+
+

{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.RULES-TITLE' | translate}}

+ +
+
diff --git a/dmp-frontend/src/app/dataset-profile-form/field-form/field-form.component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.scss similarity index 100% rename from dmp-frontend/src/app/dataset-profile-form/field-form/field-form.component.scss rename to dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.scss diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.ts new file mode 100644 index 000000000..32e9d820b --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.ts @@ -0,0 +1,53 @@ + +import { Component, Input, OnInit } from '@angular/core'; +import { FormArray, FormControl, FormGroup } from '@angular/forms'; +import { ValidationType } from '../../../../../../core/common/enum/validation-type'; +import { EnumUtils } from '../../../../../../core/services/utilities/enum-utils.service'; +import { RuleEditorModel } from '../../../admin/rule-editor-model'; +import { DatasetProfileFieldViewStyle } from '../../../../../../core/common/enum/dataset-profile-field-view-style'; + +@Component({ + selector: 'app-dataset-profile-editor-field-component', + templateUrl: './dataset-profile-editor-field.component.html', + styleUrls: ['./dataset-profile-editor-field.component.scss'] +}) +export class DatasetProfileEditorFieldComponent implements OnInit { + + @Input() form: FormGroup; + @Input() showMultiplicity = true; + @Input() showOrdinal = true; + @Input() indexPath: string; + validationsOptions: ValidationType[] = this.enumUtils.getEnumValues(ValidationType); + viewStyleEnum = DatasetProfileFieldViewStyle; + isFieldMultiplicityEnabled = false; + + constructor( + public enumUtils: EnumUtils + ) { + } + + ngOnInit() { + if (this.form.get('multiplicity')) { + if (this.form.get('multiplicity').value.min > 1 || this.form.get('multiplicity').value.max > 1) { + this.isFieldMultiplicityEnabled = true; + } + } + // this.addNewRule(); + } + + onIsFieldMultiplicityEnabledChange(isFieldMultiplicityEnabled: boolean) { + if (!isFieldMultiplicityEnabled) { + (this.form.get('multiplicity').get('min')).setValue(0); + (this.form.get('multiplicity').get('max')).setValue(0); + } + } + + addNewRule() { + const rule: RuleEditorModel = new RuleEditorModel(); + (this.form.get('visible').get('rules')).push(rule.buildForm()); + } + + onchangeCombo() { + if (this.form.get('data')) { this.form.removeControl('data'); } + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/page/dataset-profile-editor-page.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/page/dataset-profile-editor-page.component.html new file mode 100644 index 000000000..9f79d729e --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/page/dataset-profile-editor-page.component.html @@ -0,0 +1,11 @@ + + {{'DATASET-PROFILE-EDITOR.STEPS.PAGES.PAGE-PREFIX' | translate}} {{i + 1}} +
+ + + + +
+
diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/page/dataset-profile-editor-page.component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/page/dataset-profile-editor-page.component.scss new file mode 100644 index 000000000..135c7a3f6 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/page/dataset-profile-editor-page.component.scss @@ -0,0 +1,7 @@ +.page-card { + margin-bottom: 1em; + + .page-card-title { + text-align: center; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/page/dataset-profile-editor-page.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/page/dataset-profile-editor-page.component.ts new file mode 100644 index 000000000..52e35cb03 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/page/dataset-profile-editor-page.component.ts @@ -0,0 +1,16 @@ +import { Component, Input } from '@angular/core'; +import { FormArray } from '@angular/forms'; + +@Component({ + selector: 'app-dataset-profile-editor-page-component', + templateUrl: './dataset-profile-editor-page.component.html', + styleUrls: ['./dataset-profile-editor-page.component.scss'] +}) +export class DatasetProfileEditorPageComponent { + + @Input() form: FormArray; + + removePage(index) { + (this.form).removeAt(index); + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/rule/dataset-profile-editor-rule.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/rule/dataset-profile-editor-rule.component.html new file mode 100644 index 000000000..6373cc699 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/rule/dataset-profile-editor-rule.component.html @@ -0,0 +1,18 @@ +
+ {{i + 1}} + + + field value + + + + + + + + +
+
+
diff --git a/dmp-frontend/src/app/shared/componentsAdmin/textarea/textarea-component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/rule/dataset-profile-editor-rule.component.scss similarity index 100% rename from dmp-frontend/src/app/shared/componentsAdmin/textarea/textarea-component.scss rename to dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/rule/dataset-profile-editor-rule.component.scss diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/rule/dataset-profile-editor-rule.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/rule/dataset-profile-editor-rule.component.ts new file mode 100644 index 000000000..6f1d8710d --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/rule/dataset-profile-editor-rule.component.ts @@ -0,0 +1,21 @@ +import { Component, Input } from '@angular/core'; +import { FormArray } from '@angular/forms'; + +@Component({ + selector: 'app-dataset-profile-editor-rule-component', + templateUrl: './dataset-profile-editor-rule.component.html', + styleUrls: ['./dataset-profile-editor-rule.component.scss'] +}) + +export class DatasetProfileEditorRuleComponent { + + @Input() form: FormArray; + + targetValidation() { + //TODO + } + + deleteRule(index) { + this.form.removeAt(index); + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component.html new file mode 100644 index 000000000..96c98a93f --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component.html @@ -0,0 +1,58 @@ +
+

{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.TITLE' | translate}}

+ + + + + + + + + + {{pageGroup.get('title').value}} + + + + + + +

{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.FIELDS-TITLE' | translate}}

+
+ +
+ {{i + 1}}. {{getFieldTile(fieldControl, i)}} + + + +
+
+
+
+ +

{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.SUB-SECTIONS-TITLE' | translate}}

+
+ + +
+ {{i + 1}}. {{form.get('sections').get(''+i).get('title').value}} + +
+
+
+ +
+
+
+
+ +
\ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component.scss new file mode 100644 index 000000000..8bd8d916e --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component.scss @@ -0,0 +1,5 @@ +.dataset-profile-editor { + .field-card { + margin-bottom: 1em; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component.ts new file mode 100644 index 000000000..48453a8a9 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component.ts @@ -0,0 +1,68 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormArray, FormGroup } from '@angular/forms'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../../../core/common/base/base.component'; +import { FieldEditorModel } from '../../../admin/field-editor-model'; +import { FieldSetEditorModel } from '../../../admin/field-set-editor-model'; +import { SectionEditorModel } from '../../../admin/section-editor-model'; + +@Component({ + selector: 'app-dataset-profile-editor-section-component', + templateUrl: './dataset-profile-editor-section.component.html', + styleUrls: ['./dataset-profile-editor-section.component.scss'] +}) + +export class DatasetProfileEditorSectionComponent extends BaseComponent implements OnInit { + @Input() form: FormGroup; + @Input() dataModel: SectionEditorModel; + @Input() indexPath: string; + + constructor() { super(); } + + ngOnInit() { + this.form.root.get('pages').valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => + this.keepPageSelectionValid(x) + ); + } + + addField() { + const fieldSet: FieldSetEditorModel = new FieldSetEditorModel(); + const field: FieldEditorModel = new FieldEditorModel(); + fieldSet.fields.push(field); + if (this.dataModel.fieldSets) { + this.dataModel.fieldSets.push(fieldSet); + } + (this.form.get('fieldSets')).push(fieldSet.buildForm()); + } + + addSectioninSection() { + const section: SectionEditorModel = new SectionEditorModel(); + this.dataModel.sections.push(section); + (this.form.get('sections')).push(section.buildForm()); + } + + DeleteSectionInSection(index) { + this.dataModel.sections.splice(index); + (this.form.get('sections')).removeAt(index); + } + + deleteFieldSet(index) { + this.dataModel.fieldSets.splice(index, 1); + (this.form.get('fieldSets')).removeAt(index); + } + + keepPageSelectionValid(pagesJson: Array) { + const selectedPage = this.form.get('page').value as String; + // const pages: Array = JsonSerializer.fromJSONArray(pagesJson, Page); + if (pagesJson.find(elem => elem.id === selectedPage) === undefined) { + this.form.get('page').reset(); + } + } + + getFieldTile(formGroup: FormGroup, index: number) { + if (formGroup.get('title') && formGroup.get('title').value && formGroup.get('title').value.length > 0) { return formGroup.get('title').value; } + return "Field " + (index + 1); + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor-model.ts new file mode 100644 index 000000000..1dc3c2a4e --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor-model.ts @@ -0,0 +1,41 @@ +import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; +import { DatasetProfile } from '../../../../core/model/admin/dataset-profile/dataset-profile'; +import { BaseFormModel } from '../../../../core/model/base-form-model'; +import { PageEditorModel } from '../admin/page-editor-model'; +import { SectionEditorModel } from '../admin/section-editor-model'; + + +export class DatasetProfileEditorModel extends BaseFormModel { + + public sections: Array = new Array(); + public pages: Array = new Array(); + public label: string; + + fromModel(item: DatasetProfile): DatasetProfileEditorModel { + if (item.sections) { this.sections = item.sections.map(x => new SectionEditorModel().fromModel(x)); } + if (item.pages) { this.pages = item.pages.map(x => new PageEditorModel().fromModel(x)); } + this.label = item.label; + return this; + } + + buildForm(): FormGroup { + const formGroup: FormGroup = new FormBuilder().group({}); + + const sectionsFormArray = new Array(); + this.sections.forEach(item => { + const form: FormGroup = item.buildForm(); + sectionsFormArray.push(form); + }); + formGroup.addControl('sections', this.formBuilder.array(sectionsFormArray)); + + const pagesFormArray = new Array(); + this.pages.forEach(item => { + const form: FormGroup = item.buildForm(); + pagesFormArray.push(form); + }); + formGroup.addControl('pages', this.formBuilder.array(pagesFormArray)); + + formGroup.addControl('label', new FormControl(this.label, Validators.required)); + return formGroup; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.html new file mode 100644 index 000000000..c910e750d --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.html @@ -0,0 +1,42 @@ +
+ + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + {{'DATASET-PROFILE-EDITOR.STEPS.PAGES.TITLE' | translate}} +
+ +
+
+
+ + {{'DATASET-PROFILE-EDITOR.STEPS.FORM.TITLE' | translate}} +
+ + + + {{i + 1}}. {{form.get('sections').get(''+i).get('title').value}} + + +
+ +
+
+
+
+
+
+ +
+ +
diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.scss new file mode 100644 index 000000000..55e9eae24 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.scss @@ -0,0 +1,5 @@ +.dataset-profile-editor { + .full-width { + width: 100%; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts new file mode 100644 index 000000000..54620d2b1 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts @@ -0,0 +1,173 @@ +import { HttpErrorResponse } from '@angular/common/http'; +import { Component, OnInit, ViewChild } from '@angular/core'; +import { FormArray, FormControl, FormGroup } from '@angular/forms'; +import { MatHorizontalStepper } from '@angular/material'; +import { ActivatedRoute, ParamMap, Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { map, takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../core/common/base/base.component'; +import { DatasetProfile } from '../../../../core/model/admin/dataset-profile/dataset-profile'; +import { DatasetWizardModel } from '../../../../core/model/dataset/dataset-wizard'; +import { DatasetProfileService } from '../../../../core/services/dataset-profile/dataset-profile.service'; +import { LoggingService } from '../../../../core/services/logging/logging-service'; +import { SnackBarNotificationLevel, UiNotificationService } from '../../../../core/services/notification/ui-notification-service'; +import { PageEditorModel } from '../admin/page-editor-model'; +import { SectionEditorModel } from '../admin/section-editor-model'; +import { DatasetProfileEditorModel } from './dataset-profile-editor-model'; + +@Component({ + selector: 'app-dataset-profile-editor-component', + templateUrl: './dataset-profile-editor.component.html', + styleUrls: ['./dataset-profile-editor.component.scss'] +}) +export class DatasetProfileEditorComponent extends BaseComponent implements OnInit { + + isNew = true; + isDeleted = false; + dataModel: DatasetProfileEditorModel; + form: FormGroup; + previewerFormGroup: FormGroup; + private datasetProfileId: string; + dataWizardModel: DatasetWizardModel; + @ViewChild('stepper') stepper: MatHorizontalStepper; + + constructor( + private datasetProfileService: DatasetProfileService, + private route: ActivatedRoute, + private router: Router, + private logger: LoggingService, + private uiNotificationService: UiNotificationService, + private language: TranslateService + ) { + super(); + // this.profileID = route.snapshot.params['id']; + // this.cloneId = route.snapshot.params['cloneid']; + } + + ngOnInit() { + + this.route.paramMap.pipe(takeUntil(this._destroyed)).subscribe((paramMap: ParamMap) => { + this.datasetProfileId = paramMap.get('id'); + const cloneId = paramMap.get('cloneid'); + + if (this.datasetProfileId != null) { + this.isNew = false; + this.datasetProfileService.getDatasetProfileById(this.datasetProfileId) + .pipe(map(data => data as DatasetProfile), takeUntil(this._destroyed)) + .subscribe( + data => { + try { + this.dataModel = new DatasetProfileEditorModel().fromModel(data); + // this.isDeleted = this.masterItem.isActive === IsActive.Inactive; + this.form = this.dataModel.buildForm(); + this.prepareForm(); + } catch { + this.logger.error('Could not parse MasterItem: ' + data); + this.uiNotificationService.snackBarNotification(this.language.instant('NOTIFICATIONS.DEFAULT.ERROR'), SnackBarNotificationLevel.Error); + } + }, + error => this.onCallbackError(error) + ); + } else if (cloneId != null) { + this.datasetProfileService.clone(cloneId) + .pipe(map(data => data as DatasetProfile), takeUntil(this._destroyed)) + .subscribe( + data => { + try { + this.dataModel = new DatasetProfileEditorModel().fromModel(data); + // this.isDeleted = this.masterItem.isActive === IsActive.Inactive; + this.form = this.dataModel.buildForm(); + this.prepareForm(); + } catch { + this.logger.error('Could not parse MasterItem: ' + data); + this.uiNotificationService.snackBarNotification(this.language.instant('NOTIFICATIONS.DEFAULT.ERROR'), SnackBarNotificationLevel.Error); + } + }, + error => this.onCallbackError(error) + ); + } else { + this.dataModel = new DatasetProfileEditorModel(); + this.form = this.dataModel.buildForm(); + this.addSection(); + this.addPage(); + } + }); + } + + prepareForm() { + this.form.valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(change => { + // this.datasetProfileService.preview(this.form.value) + // .pipe(takeUntil(this._destroyed)) + // .subscribe(dataset => { + // const datasetModel = new DatasetWizardModel(); + // datasetModel.datasetProfileDefinition = JsonSerializer.fromJSONObject(dataset, DatasetProfileDefinitionModel); + // this.dataWizardModel = datasetModel; + // this.previewerFormGroup = this.dataWizardModel.buildForm().get('datasetProfileDefinition'); + // }); + }); + this.form.updateValueAndValidity(); + } + + onIsMultiplicityEnabledChange(isMultiplicityEnabled: boolean) { + if (!isMultiplicityEnabled) { + (this.form.get('multiplicity').get('min')).setValue(0); + (this.form.get('multiplicity').get('max')).setValue(0); + } + } + + addSection() { + const section: SectionEditorModel = new SectionEditorModel(); + this.dataModel.sections.push(section); + (this.form.get('sections')).push(section.buildForm()); + } + + addPage() { + const page: PageEditorModel = new PageEditorModel(this.dataModel.pages.length); + this.dataModel.pages.push(page); + (this.form.get('pages')).push(page.buildForm()); + } + + DeleteSection(index) { + this.dataModel.sections.splice(index, 1); + (this.form.get('sections')).removeAt(index); + } + + onSubmit() { + const data = this.form.value; + + if (this.datasetProfileId) { + this.datasetProfileService.updateForm(this.datasetProfileId, data) + .pipe(takeUntil(this._destroyed)) + .subscribe(() => { + this.router.navigate(['/dataset-profiles']); + }); + } else { + this.datasetProfileService.createForm(data) + .pipe(takeUntil(this._destroyed)) + .subscribe(() => { + this.router.navigate(['/dataset-profiles']); + }); + } + } + + isStepActive(step: number) { + return this.stepper && this.stepper.selectedIndex === step; + } + + onCallbackSuccess(): void { + this.uiNotificationService.snackBarNotification(this.isNew ? this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-CREATION') : this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success); + this.router.navigate(['/master-items']); + } + + onCallbackError(errorResponse: HttpErrorResponse) { + // const error: HttpError = this.httpErrorHandlingService.getError(errorResponse); + // if (error.statusCode === 400) { + // this.masterItem.validationErrorModel.fromJSONObject(errorResponse.error); + // this.formService.validateAllFormFields(this.formGroup); + // } else { + this.uiNotificationService.snackBarNotification(errorResponse.message, SnackBarNotificationLevel.Warning); + // } + } +} diff --git a/dmp-frontend/src/app/shared/components/criteria/dataset-profile/dataset-profile.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component.html similarity index 100% rename from dmp-frontend/src/app/shared/components/criteria/dataset-profile/dataset-profile.component.html rename to dmp-frontend/src/app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component.html diff --git a/dmp-frontend/src/app/shared/components/criteria/dataset-profile/dataset-profile.component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component.scss similarity index 100% rename from dmp-frontend/src/app/shared/components/criteria/dataset-profile/dataset-profile.component.scss rename to dmp-frontend/src/app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component.scss diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component.ts new file mode 100644 index 000000000..1062cfb78 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component.ts @@ -0,0 +1,41 @@ +import { Component, OnInit } from '@angular/core'; +import { ValidationErrorModel } from '../../../../../common/forms/validation/error-model/validation-error-model'; +import { DatasetProfileCriteria } from '../../../../../core/query/dataset-profile/dataset-profile-criteria'; +import { BaseCriteriaComponent } from '../../../../misc/criteria/base-criteria.component'; + +@Component({ + selector: 'app-dataset-profile-criteria-component', + templateUrl: './dataset-profile.component.html', + styleUrls: ['./dataset-profile.component.scss'], +}) +export class DatasetProfileCriteriaComponent extends BaseCriteriaComponent implements OnInit { + + public criteria: DatasetProfileCriteria = new DatasetProfileCriteria(); + + constructor( + ) { + super(new ValidationErrorModel()); + } + + ngOnInit() { + super.ngOnInit(); + if (this.criteria == null) { this.criteria = new DatasetProfileCriteria(); } + } + + setCriteria(criteria: DatasetProfileCriteria): void { + this.criteria = criteria; + } + + onCallbackError(error: any) { + this.setErrorModel(error.error); + } + + controlModified(): void { + this.clearErrorModel(); + if (this.refreshCallback != null && + (this.criteria.like == null || this.criteria.like.length === 0 || this.criteria.like.length > 2) + ) { + this.refreshCallback(); + } + } +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.html new file mode 100644 index 000000000..af99ee0cd --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.html @@ -0,0 +1,59 @@ +
+

{{titlePrefix}} {{'DATASET-PROFILE-LISTING.TITLE' | translate}}

+ + + + + + + + + + + + {{'DATASET-PROFILE-LISTING.COLUMNS.NAME' | translate}} + {{row.label}} + + + + + {{'DATASET-PROFILE-LISTING.COLUMNS.DESCRIPTION' | translate}} + {{row.description}} + + + + + {{'DATASET-PROFILE-LISTING.COLUMNS.CREATED' | + translate}} + {{row.created | date:'shortDate'}} + + + + + {{'DATASET-PROFILE-LISTING.COLUMNS.ACTIONS' | translate}} + + + + + + + + + + + + + + + + + + + +
diff --git a/dmp-frontend/src/app/dataset-profile-form/datasets-admin-listing/dataset-profile-admin-listing.component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.scss similarity index 100% rename from dmp-frontend/src/app/dataset-profile-form/datasets-admin-listing/dataset-profile-admin-listing.component.scss rename to dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.scss diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.ts new file mode 100644 index 000000000..29eeb804c --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.ts @@ -0,0 +1,148 @@ +import { DataSource } from '@angular/cdk/table'; +import { Component, OnInit, ViewChild } from '@angular/core'; +import { MatPaginator, MatSort, PageEvent } from '@angular/material'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../core/common/base/base.component'; +import { DatasetListingModel } from '../../../../core/model/dataset/dataset-listing'; +import { DmpModel } from '../../../../core/model/dmp/dmp'; +import { DatasetProfileCriteria } from '../../../../core/query/dataset-profile/dataset-profile-criteria'; +import { DatasetProfileService } from '../../../../core/services/dataset-profile/dataset-profile.service'; +import { DmpService } from '../../../../core/services/dmp/dmp.service'; +import { DataTableRequest } from '../../../../core/model/data-table/data-table-request'; +import { DatasetProfileCriteriaComponent } from './criteria/dataset-profile.component'; + +@Component({ + selector: 'app-dataset-profile-listing-component', + templateUrl: 'dataset-profile-listing.component.html', + styleUrls: ['./dataset-profile-listing.component.scss'] +}) +export class DatasetProfileListingComponent extends BaseComponent implements OnInit { + + @ViewChild(MatPaginator) _paginator: MatPaginator; + @ViewChild(MatSort) sort: MatSort; + @ViewChild(DatasetProfileCriteriaComponent) criteria: DatasetProfileCriteriaComponent; + + + dataSource: DatasetDataSource | null; + displayedColumns: String[] = ['label', 'description', 'created', 'actions']; + pageEvent: PageEvent; + titlePrefix: String; + dmpId: String; + + constructor( + private datasetService: DatasetProfileService, + private router: Router, + private route: ActivatedRoute, + private dmpService: DmpService + ) { + super(); + } + + + ngOnInit() { + this.route.params + .pipe(takeUntil(this._destroyed)) + .subscribe((params: Params) => { + this.dmpId = params['dmpId']; + if (this.dmpId != null) { this.setDmpTitle(this.dmpId); } + this.criteria.setCriteria(this.getDefaultCriteria(this.dmpId)); + this.refresh(); + this.criteria.setRefreshCallback(() => this.refresh()); + }); + } + + setDmpTitle(dmpId: String) { + this.dmpService.getSingle(dmpId).map(data => data as DmpModel) + .pipe(takeUntil(this._destroyed)) + .subscribe(data => { + this.titlePrefix = data.label; + }); + } + + refresh() { + this.dataSource = new DatasetDataSource(this.datasetService, this._paginator, this.sort, this.criteria); + } + + rowClick(rowId: String) { + this.router.navigate(['dataset-profiles/' + rowId]); + } + + getDefaultCriteria(dmpId: String): DatasetProfileCriteria { + const defaultCriteria = new DatasetProfileCriteria(); + + return defaultCriteria; + } + + clone(id: string) { + this.router.navigate(['dataset-profiles/clone/' + id]); + } + + // makeItPublic(id: String) { + // debugger; + // this.datasetService.makeDatasetPublic(id).pipe(takeUntil(this._destroyed)).subscribe(); + // } + +} + +export class DatasetDataSource extends DataSource { + + totalCount = 0; + isLoadingResults = false; + + constructor( + private _service: DatasetProfileService, + private _paginator: MatPaginator, + private _sort: MatSort, + private _criteria: DatasetProfileCriteriaComponent + ) { + super(); + + } + + connect(): Observable { + const displayDataChanges = [ + this._paginator.page + //this._sort.matSortChange + ]; + + return Observable.merge(...displayDataChanges) + .startWith(null) + .switchMap(() => { + setTimeout(() => { + this.isLoadingResults = true; + }); + const startIndex = this._paginator.pageIndex * this._paginator.pageSize; + let fields: Array = new Array(); + if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; } + const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); + request.criteria = this._criteria.criteria; + return this._service.getPaged(request); + }) + /*.catch((error: any) => { + this._snackBar.openFromComponent(SnackBarNotificationComponent, { + data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService }, + duration: 3000, + extraClasses: ['snackbar-warning'] + }); + //this._criteria.criteria.onCallbackError(error); + return Observable.of(null); + })*/ + .map(result => { + setTimeout(() => { + this.isLoadingResults = false; + }); + return result; + }) + .map(result => { + if (!result) { return []; } + if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; } + return result.data; + }); + } + + disconnect() { + // No-op + } +} diff --git a/dmp-frontend/src/app/dataset-profile-form/previewer/dataset-profile-previewer.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/preview/dataset-profile-preview.component.html similarity index 100% rename from dmp-frontend/src/app/dataset-profile-form/previewer/dataset-profile-previewer.component.html rename to dmp-frontend/src/app/ui/admin/dataset-profile/preview/dataset-profile-preview.component.html diff --git a/dmp-frontend/src/app/dataset-profile-form/previewer/dataset-profile-previewer.component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/preview/dataset-profile-preview.component.scss similarity index 100% rename from dmp-frontend/src/app/dataset-profile-form/previewer/dataset-profile-previewer.component.scss rename to dmp-frontend/src/app/ui/admin/dataset-profile/preview/dataset-profile-preview.component.scss diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/preview/dataset-profile-preview.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/preview/dataset-profile-preview.component.ts new file mode 100644 index 000000000..90736dd56 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/preview/dataset-profile-preview.component.ts @@ -0,0 +1,35 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../core/common/base/base.component'; +import { DatasetProfileService } from '../../../../core/services/dataset-profile/dataset-profile.service'; +import { DatasetWizardEditorModel } from '../../../dataset/dataset-wizard/dataset-wizard-editor.model'; + +@Component({ + selector: 'app-dataset-profile-preview-component', + templateUrl: './dataset-profile-preview.component.html', + styleUrls: ['./dataset-profile-preview.component.scss'] +}) +export class DatasetProfilePreviewerComponent extends BaseComponent implements OnInit { + formGroup: FormGroup; + datasetWizardModel: DatasetWizardEditorModel; + constructor( + private datasetProfileService: DatasetProfileService, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any + ) { super(); } + + ngOnInit(): void { + + this.datasetProfileService.preview(this.data['model']) + .pipe(takeUntil(this._destroyed)) + .subscribe(x => { + this.datasetWizardModel = new DatasetWizardEditorModel().fromModel({ + datasetProfileDefinition: x + }); + this.formGroup = this.datasetWizardModel.buildForm().get('datasetProfileDefinition'); + }); + + } +} diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.module.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.module.ts new file mode 100644 index 000000000..561c81867 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.module.ts @@ -0,0 +1,25 @@ +import { NgModule } from "@angular/core"; +import { CommonFormsModule } from "../../../common/forms/common-forms.module"; +import { CommonUiModule } from "../../../common/ui/common-ui.module"; +import { ConfirmationDialogModule } from "../../../library/confirmation-dialog/confirmation-dialog.module"; +import { UrlListingModule } from "../../../library/url-listing/url-listing.module"; +import { DmpProfileRoutingModule } from "./dmp-profile.routing"; +import { DmpProfileEditorComponent } from "./editor/dmp-profile-editor.component"; +import { DmpProfileCriteriaComponent } from "./listing/criteria/dmp-profile-criteria.component"; +import { DmpProfileListingComponent } from "./listing/dmp-profile-listing.component"; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule, + UrlListingModule, + ConfirmationDialogModule, + DmpProfileRoutingModule + ], + declarations: [ + DmpProfileEditorComponent, + DmpProfileListingComponent, + DmpProfileCriteriaComponent + ] +}) +export class DmpProfileModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.routing.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.routing.ts new file mode 100644 index 000000000..700b2e106 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.routing.ts @@ -0,0 +1,17 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { AuthGuard } from '../../../core/auth-guard.service'; +import { DmpProfileEditorComponent } from './editor/dmp-profile-editor.component'; +import { DmpProfileListingComponent } from './listing/dmp-profile-listing.component'; + +const routes: Routes = [ + { path: '', component: DmpProfileListingComponent, canActivate: [AuthGuard] }, + { path: 'new', component: DmpProfileEditorComponent, canActivate: [AuthGuard] }, + { path: ':id', component: DmpProfileEditorComponent, canActivate: [AuthGuard] }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class DmpProfileRoutingModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.html b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.html new file mode 100644 index 000000000..084a07a0f --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.html @@ -0,0 +1,68 @@ +
+
+ + + +

{{'DMP-PROFILE-EDITOR.TITLE.NEW' | translate}}

+
+ +

{{formGroup.get('label').value}}

+
+
+ +
+ + + {{baseErrorModel.label}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + +

{{'DMP-PROFILE-EDITOR.FIELDS.TITLE' | translate}}

+
+
+ + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{baseErrorModel.label}} + + + + {{ + getDMPProfileFieldTypeWithLanguage(fieldType) | translate}} + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{baseErrorModel.type}} + + + + {{ + getDMPProfileFieldDataTypeWithLanguage(fieldDataType) | translate}} + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{baseErrorModel.dataType}} + +
+ {{'DMP-PROFILE-EDITOR.FIELDS.REQUIRED' | translate}} +
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.scss b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.scss new file mode 100644 index 000000000..90bce5b9e --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.scss @@ -0,0 +1,6 @@ +.dmp-profile-editor { + .centered-row-item { + align-items: center; + display: flex; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.ts new file mode 100644 index 000000000..210c94be6 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.ts @@ -0,0 +1,185 @@ +import { AfterViewInit, Component } from '@angular/core'; +import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; +import { MatSnackBar } from '@angular/material'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { takeUntil } from 'rxjs/operators'; +import { environment } from '../../../../../environments/environment'; +import { BaseComponent } from '../../../../core/common/base/base.component'; +import { DmpProfileFieldDataType } from '../../../../core/common/enum/dmp-profile-field-type'; +import { DmpProfileType } from '../../../../core/common/enum/dmp-profile-type'; +import { DmpProfile } from '../../../../core/model/dmp-profile/dmp-profile'; +import { DmpProfileService } from '../../../../core/services/dmp/dmp-profile.service'; +import { EnumUtils } from '../../../../core/services/utilities/enum-utils.service'; +import { SnackBarNotificationComponent } from '../../../../library/notification/snack-bar/snack-bar-notification.component'; +import { DmpProfileEditorModel, DmpProfileFieldEditorModel } from './dmp-profile-editor.model'; + +@Component({ + selector: 'app-dmp-profile-editor-component', + templateUrl: 'dmp-profile-editor.component.html', + styleUrls: ['./dmp-profile-editor.component.scss'] +}) +export class DmpProfileEditorComponent extends BaseComponent implements AfterViewInit { + + isNew = true; + dmpProfileModel: DmpProfileEditorModel; + formGroup: FormGroup = null; + host = environment.Server; + baseErrorModel: BaseErrorModel; + + constructor( + private dmpProfileService: DmpProfileService, + private route: ActivatedRoute, + private snackBar: MatSnackBar, + private router: Router, + private language: TranslateService, + private enumUtils: EnumUtils + ) { + super(); + } + + ngAfterViewInit() { + this.route.params + .pipe(takeUntil(this._destroyed)) + .subscribe((params: Params) => { + const itemId = params['id']; + + if (itemId != null) { + this.isNew = false; + this.dmpProfileService.getSingle(itemId).map(data => data as DmpProfile) + .pipe(takeUntil(this._destroyed)) + .subscribe(data => { + this.dmpProfileModel = new DmpProfileEditorModel().fromModel(data); + //this.baseErrorModel = this.dmpProfileModel.errorModel; + this.formGroup = this.dmpProfileModel.buildForm(); + }); + } else { + this.dmpProfileModel = new DmpProfileEditorModel(); + //this.baseErrorModel = this.dmpProfileModel.errorModel; + + setTimeout(() => { + this.formGroup = this.dmpProfileModel.buildForm(); + }); + } + }); + } + + formSubmit(): void { + this.touchAllFormFields(this.formGroup); + if (!this.isFormValid()) { return; } + this.onSubmit(); + } + + public isFormValid() { + return this.formGroup.valid; + } + + onSubmit(): void { + this.dmpProfileService.createDmp(this.formGroup.value) + .pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) + ); + } + + onCallbackSuccess(): void { + this.snackBar.openFromComponent(SnackBarNotificationComponent, { + data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, + duration: 3000, + }); + this.router.navigate(['/dmp-profiles']); + } + + onCallbackError(errorResponse: any) { + this.setErrorModel(errorResponse.error); + this.validateAllFormFields(this.formGroup); + } + + public setErrorModel(errorModel: BaseErrorModel) { + // Object.keys(errorModel).forEach(item => { + // (this.dmpProfileModel.errorModel)[item] = (errorModel)[item]; + // }); + } + + public cancel(): void { + this.router.navigate(['/dmp-profiles']); + } + + + public touchAllFormFields(formControl: AbstractControl) { + if (formControl instanceof FormControl) { + formControl.markAsTouched(); + } else if (formControl instanceof FormGroup) { + Object.keys(formControl.controls).forEach(item => { + const control = formControl.get(item); + this.touchAllFormFields(control); + }); + } else if (formControl instanceof FormArray) { + formControl.controls.forEach(item => { + this.touchAllFormFields(item); + }); + } + } + + public validateAllFormFields(formControl: AbstractControl) { + if (formControl instanceof FormControl) { + formControl.updateValueAndValidity({ emitEvent: false }); + } else if (formControl instanceof FormGroup) { + Object.keys(formControl.controls).forEach(item => { + const control = formControl.get(item); + this.validateAllFormFields(control); + }); + } else if (formControl instanceof FormArray) { + formControl.controls.forEach(item => { + this.validateAllFormFields(item); + }); + } + } + + addField() { + (this.formGroup.get('definition').get('fields')).push(new DmpProfileFieldEditorModel().buildForm()); + } + + removeField(index: number) { + (this.formGroup.get('definition').get('fields')).controls.splice(index, 1); + } + + getDMPProfileFieldDataTypeValues(): Number[] { + let keys: string[] = Object.keys(DmpProfileFieldDataType); + keys = keys.slice(0, keys.length / 2); + const values: Number[] = keys.map(Number); + return values; + } + + getDMPProfileFieldDataTypeWithLanguage(fieldType: DmpProfileFieldDataType): string { + let result = ''; + this.language.get(this.enumUtils.toDmpProfileFieldDataTypeString(fieldType)) + .pipe(takeUntil(this._destroyed)) + .subscribe((value: string) => { + result = value; + }); + return result; + } + + getDMPProfileFieldTypeValues(): Number[] { + let keys: string[] = Object.keys(DmpProfileType); + keys = keys.slice(0, keys.length / 2); + const values: Number[] = keys.map(Number); + return values; + } + + getDMPProfileFieldTypeWithLanguage(profileType: DmpProfileType): string { + let result = ''; + this.language.get(this.enumUtils.toDmpProfileTypeString(profileType)) + .pipe(takeUntil(this._destroyed)) + .subscribe((value: string) => { + result = value; + }); + return result; + } + + delete() { + //TODO + } +} diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.model.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.model.ts new file mode 100644 index 000000000..cd933a9e4 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.model.ts @@ -0,0 +1,90 @@ +import { FormBuilder, FormGroup } from '@angular/forms'; +import { ValidationErrorModel } from '../../../../common/forms/validation/error-model/validation-error-model'; +import { DmpProfileFieldDataType } from '../../../../core/common/enum/dmp-profile-field-type'; +import { DmpProfileType } from '../../../../core/common/enum/dmp-profile-type'; +import { DmpProfile, DmpProfileDefinition } from '../../../../core/model/dmp-profile/dmp-profile'; +import { DmpProfileField } from '../../../../core/model/dmp-profile/dmp-profile-field'; + +export class DmpProfileEditorModel { + + public id: string; + public label: string; + public definition: DmpProfileDefinitionEditorModel = new DmpProfileDefinitionEditorModel(); + public status: number; + public created: Date; + public modified: Date; + public errorModel: ValidationErrorModel = new ValidationErrorModel(); + + fromModel(item: DmpProfile): DmpProfileEditorModel { + this.id = item.id; + this.label = item.label; + this.definition = new DmpProfileDefinitionEditorModel().fromModel(item.definition); + this.status = item.status; + this.created = item.created; + this.modified = item.modified; + return this; + } + + buildForm(): FormGroup { + const formGroup = new FormBuilder().group({ + id: [this.id], + label: [this.label], + status: [this.status], + created: [this.created], + modified: [this.modified] + }); + formGroup.addControl('definition', this.definition.buildForm()); + return formGroup; + } +} + +export class DmpProfileDefinitionEditorModel { + + public fields: DmpProfileFieldEditorModel[] = new Array(); + + fromModel(item: DmpProfileDefinition): DmpProfileDefinitionEditorModel { + if (item.fields) { item.fields.map(x => this.fields.push(new DmpProfileFieldEditorModel().fromModel(x))); } + return this; + } + + buildForm(): FormGroup { + const formBuilder = new FormBuilder(); + const formGroup = formBuilder.group({}); + const fieldsFormArray = new Array(); + this.fields.forEach(item => { + const form: FormGroup = item.buildForm(); + fieldsFormArray.push(form); + }); + formGroup.addControl('fields', formBuilder.array(fieldsFormArray)); + return formGroup; + } +} + +export class DmpProfileFieldEditorModel { + public id: string; + public type: DmpProfileType; + public dataType: DmpProfileFieldDataType; + public required = false; + public label: string; + public value: any; + + fromModel(item: DmpProfileField): DmpProfileFieldEditorModel { + this.type = item.type; + this.dataType = item.dataType; + this.required = item.required; + this.label = item.label; + this.id = item.id; + this.value = item.value; + return this; + } + + buildForm(): FormGroup { + return new FormBuilder().group({ + type: [this.type], + id: [this.id], + dataType: [this.dataType], + required: [this.required], + label: [this.label] + }); + } +} \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.html b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.html new file mode 100644 index 000000000..d3102c1dc --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.html @@ -0,0 +1,10 @@ +
+ +
+ + + {{baseErrorModel['Criteria.like']}} + +
+
+
diff --git a/dmp-frontend/src/app/shared/components/criteria/datamanagementplanprofile/dmp-profile-criteria.component.scss b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.scss similarity index 100% rename from dmp-frontend/src/app/shared/components/criteria/datamanagementplanprofile/dmp-profile-criteria.component.scss rename to dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.scss diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.ts new file mode 100644 index 000000000..51bb34bef --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.ts @@ -0,0 +1,47 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { ValidationErrorModel } from '../../../../../common/forms/validation/error-model/validation-error-model'; +import { ProjectModel } from '../../../../../core/model/project/project'; +import { DmpCriteria } from '../../../../../core/query/dmp/dmp-criteria'; +import { DmpProfileCriteria } from '../../../../../core/query/dmp/dmp-profile-criteria'; +import { BaseCriteriaComponent } from '../../../../misc/criteria/base-criteria.component'; + +@Component({ + selector: 'app-dmp-profile-criteria-component', + templateUrl: './dmp-profile-criteria.component.html', + styleUrls: ['./dmp-profile-criteria.component.scss'], +}) +export class DmpProfileCriteriaComponent extends BaseCriteriaComponent implements OnInit { + + @Input() + showProject: boolean; + public criteria: DmpProfileCriteria = new DmpProfileCriteria(); + filteringProjectsAsync = false; + filteredProjects: ProjectModel[]; + + constructor( + ) { + super(new ValidationErrorModel()); + } + + ngOnInit() { + super.ngOnInit(); + if (this.criteria == null) { this.criteria = new DmpCriteria(); } + } + + setCriteria(criteria: DmpProfileCriteria): void { + this.criteria = criteria; + } + + onCallbackError(error: any) { + this.setErrorModel(error.error); + } + + controlModified(): void { + this.clearErrorModel(); + if (this.refreshCallback != null && + (this.criteria.like == null || this.criteria.like.length === 0 || this.criteria.like.length > 2) + ) { + this.refreshCallback(); + } + } +} diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.html b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.html new file mode 100644 index 000000000..ba556a6a8 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.html @@ -0,0 +1,40 @@ +
+

{{titlePrefix}} {{'DMP-PROFILE-LISTING.TITLE' | translate}}

+ + + + + + + + {{'DMP-PROFILE-LISTING.COLUMNS.NAME' | translate}} + {{row.label}} + + + + + {{'DMP-PROFILE-LISTING.COLUMNS.STATUS' | translate}} + {{row.status}} + + + + + {{'DMP-PROFILE-LISTING.COLUMNS.CREATED' | translate}} + {{row.created | date:'shortDate'}} + + + + + + + + + + + + + + +
diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.scss b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.scss new file mode 100644 index 000000000..b75b9130e --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.scss @@ -0,0 +1,26 @@ +.dmp-profile-listing { + + .mat-row { + cursor: pointer; + } + + .mat-card { + margin: 1em 0; + } + + mat-row:hover { + background-color: lightgray; + } + + mat-row:nth-child(odd) { + background-color: #eef0fb; + } + + .mat-fab-bottom-right { + top: auto !important; + right: 20px !important; + bottom: 10px !important; + left: auto !important; + position: fixed !important; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.ts new file mode 100644 index 000000000..d36c06e13 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.ts @@ -0,0 +1,132 @@ +import { DataSource } from '@angular/cdk/table'; +import { Component, OnInit, ViewChild } from '@angular/core'; +import { MatPaginator, MatSnackBar, MatSort, PageEvent } from '@angular/material'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../core/common/base/base.component'; +import { DmpProfileListing } from '../../../../core/model/dmp-profile/dmp-profile-listing'; +import { DmpProfileCriteria } from '../../../../core/query/dmp/dmp-profile-criteria'; +import { DmpProfileService } from '../../../../core/services/dmp/dmp-profile.service'; +import { DataTableRequest } from '../../../../core/model/data-table/data-table-request'; +import { DmpProfileCriteriaComponent } from './criteria/dmp-profile-criteria.component'; + +@Component({ + selector: 'app-dmp-profile-listing-component', + templateUrl: 'dmp-profile-listing.component.html', + styleUrls: ['./dmp-profile-listing.component.scss'] +}) +export class DmpProfileListingComponent extends BaseComponent implements OnInit { + + @ViewChild(MatPaginator) _paginator: MatPaginator; + @ViewChild(MatSort) sort: MatSort; + @ViewChild(DmpProfileCriteriaComponent) criteria: DmpProfileCriteriaComponent; + + dataSource: DatasetDataSource | null; + displayedColumns: String[] = ['label', 'status', 'created']; + pageEvent: PageEvent; + titlePrefix: String; + dmpId: String; + + statuses = [ + { value: '0', viewValue: 'Active' }, + { value: '1', viewValue: 'Inactive' } + ]; + + constructor( + private router: Router, + private languageService: TranslateService, + public snackBar: MatSnackBar, + public route: ActivatedRoute, + public dmpProfileService: DmpProfileService + ) { + super(); + } + + + ngOnInit() { + this.route.params + .pipe(takeUntil(this._destroyed)) + .subscribe((params: Params) => { + this.dmpId = params['dmpId']; + this.criteria.setCriteria(this.getDefaultCriteria()); + this.refresh(); + this.criteria.setRefreshCallback(() => this.refresh()); + }); + } + + refresh() { + this.dataSource = new DatasetDataSource(this.dmpProfileService, this._paginator, this.sort, this.criteria); + } + + rowClick(rowId: String) { + this.router.navigate(['dmp-profiles/' + rowId]); + } + + getDefaultCriteria(): DmpProfileCriteria { + const defaultCriteria = new DmpProfileCriteria(); + return defaultCriteria; + } + + // makeItPublic(id: String) { + // debugger; + // this.datasetService.makeDatasetPublic(id).pipe(takeUntil(this._destroyed)).subscribe(); + // } + +} + +export class DatasetDataSource extends DataSource { + + totalCount = 0; + + constructor( + private _service: DmpProfileService, + private _paginator: MatPaginator, + private _sort: MatSort, + private _criteria: DmpProfileCriteriaComponent + ) { + super(); + + } + + connect(): Observable { + const displayDataChanges = [ + this._paginator.page + //this._sort.matSortChange + ]; + + + return Observable.merge(...displayDataChanges) + .startWith(null) + .switchMap(() => { + const startIndex = this._paginator.pageIndex * this._paginator.pageSize; + let fields: Array = new Array(); + if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; } + const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); + request.criteria = this._criteria.criteria; + return this._service.getPaged(request); + }) + /*.catch((error: any) => { + this._snackBar.openFromComponent(SnackBarNotificationComponent, { + data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService }, + duration: 3000, + extraClasses: ['snackbar-warning'] + }); + //this._criteria.criteria.onCallbackError(error); + return Observable.of(null); + })*/ + .map(result => { + return result; + }) + .map(result => { + if (!result) { return []; } + if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; } + return result.data; + }); + } + + disconnect() { + // No-op + } +} diff --git a/dmp-frontend/src/app/ui/admin/user/listing/criteria/user-criteria.component.html b/dmp-frontend/src/app/ui/admin/user/listing/criteria/user-criteria.component.html new file mode 100644 index 000000000..546010f02 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/user/listing/criteria/user-criteria.component.html @@ -0,0 +1,14 @@ +
+ +
+ + + + + + {{getPrincipalAppRoleWithLanguage(role)}} + + +
+
+
diff --git a/dmp-frontend/src/app/ui/admin/user/listing/criteria/user-criteria.component.scss b/dmp-frontend/src/app/ui/admin/user/listing/criteria/user-criteria.component.scss new file mode 100644 index 000000000..af2a32097 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/user/listing/criteria/user-criteria.component.scss @@ -0,0 +1,2 @@ +.user-roles-criteria { +} diff --git a/dmp-frontend/src/app/ui/admin/user/listing/criteria/user-criteria.component.ts b/dmp-frontend/src/app/ui/admin/user/listing/criteria/user-criteria.component.ts new file mode 100644 index 000000000..b170d8c52 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/user/listing/criteria/user-criteria.component.ts @@ -0,0 +1,85 @@ +import { Component, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { takeUntil } from 'rxjs/operators'; +import { ValidationErrorModel } from '../../../../../common/forms/validation/error-model/validation-error-model'; +import { Validation, ValidationContext } from '../../../../../common/forms/validation/validation-context'; +import { AppRole } from '../../../../../core/common/enum/app-role'; +import { UserCriteria } from '../../../../../core/query/user/user-criteria'; +import { EnumUtils } from '../../../../../core/services/utilities/enum-utils.service'; +import { BaseCriteriaComponent } from '../../../../misc/criteria/base-criteria.component'; + +@Component({ + selector: 'app-user-criteria-component', + templateUrl: './user-criteria.component.html', + styleUrls: ['./user-criteria.component.scss'] +}) +export class UserCriteriaComponent extends BaseCriteriaComponent implements OnInit { + + public role: AppRole; + public criteria: UserCriteria = new UserCriteria(); + + constructor( + private language: TranslateService, + private formBuilder: FormBuilder, + private enumUtils: EnumUtils + ) { + super(new ValidationErrorModel()); + } + + ngOnInit() { + super.ngOnInit(); + if (this.criteria == null) { this.criteria = new UserCriteria(); } + if (this.formGroup == null) { this.formGroup = this.buildForm(); } + } + + setCriteria(criteria: UserCriteria): void { + this.criteria = criteria; + this.formGroup = this.buildForm(); + } + + public fromJSONObject(item: any): UserCriteria { + this.criteria = new UserCriteria(); + this.criteria.label = item.Label; + this.criteria.appRoles = item.appRoles; + return this.criteria; + } + + buildForm(): FormGroup { + const context: ValidationContext = this.createValidationContext(); + + return this.formBuilder.group({ + like: [this.criteria.label, context.getValidation('label').validators], + appRoles: [this.criteria.appRoles, context.getValidation('appRoles').validators], + }); + } + + createValidationContext(): ValidationContext { + const validationContext: ValidationContext = new ValidationContext(); + const validationArray: Validation[] = new Array(); + + validationArray.push({ key: 'label' }); + validationArray.push({ key: 'appRoles' }); + + validationContext.validation = validationArray; + return validationContext; + } + + getPrincipalAppRoleValues(): Number[] { + let keys: string[] = Object.keys(AppRole); + keys = keys.slice(0, keys.length / 2); + const values: Number[] = keys.map(Number); + return values; + } + + getPrincipalAppRoleWithLanguage(role: AppRole): string { + let result = ''; + this.language.get(this.enumUtils.convertFromPrincipalAppRole(role)) + .pipe(takeUntil(this._destroyed)) + .subscribe((value: string) => { + result = value; + }); + return result; + } + +} diff --git a/dmp-frontend/src/app/users/components/roles/user-role-editor.component.html b/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.html similarity index 100% rename from dmp-frontend/src/app/users/components/roles/user-role-editor.component.html rename to dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.html diff --git a/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/datarepository/datarepository-referenced-model-helper.component.scss b/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.scss similarity index 100% rename from dmp-frontend/src/app/datasets/dataset-referenced-models-helper/datarepository/datarepository-referenced-model-helper.component.scss rename to dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.scss diff --git a/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.ts b/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.ts new file mode 100644 index 000000000..d4a43c2ba --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.ts @@ -0,0 +1,166 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { AbstractControl, FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms'; +import { MatSnackBar } from '@angular/material'; +import { TranslateService } from '@ngx-translate/core'; +import { takeUntil } from 'rxjs/operators'; +import { Validation, ValidationContext } from '../../../../../common/forms/validation/validation-context'; +import { BaseComponent } from '../../../../../core/common/base/base.component'; +import { AppRole } from '../../../../../core/common/enum/app-role'; +import { UserListingModel } from '../../../../../core/model/user/user-listing'; +import { UserService } from '../../../../../core/services/user/user.service'; +import { EnumUtils } from '../../../../../core/services/utilities/enum-utils.service'; +import { SnackBarNotificationComponent } from '../../../../../library/notification/snack-bar/snack-bar-notification.component'; + +@Component({ + selector: 'app-user-role-editor-component', + templateUrl: './user-role-editor.component.html', + styleUrls: ['./user-role-editor.component.scss'] +}) +export class UserRoleEditorComponent extends BaseComponent implements OnInit { + + @Input() public item: UserListingModel; + public formGroup: FormGroup = null; + public nowEditing = false; + //public errorModel: UserErrorModel; + + constructor( + private language: TranslateService, + private userService: UserService, + private formBuilder: FormBuilder, + private snackBar: MatSnackBar, + private enumUtils: EnumUtils + ) { super(); } + + ngOnInit() { + // if (this.errorModel == null) { this.errorModel = new UserErrorModel(); } + if (this.formGroup == null) { this.formGroup = this.buildForm(); } + } + + buildForm(): FormGroup { + const context: ValidationContext = this.createValidationContext(); + + return this.formBuilder.group({ + appRoles: new FormControl({ value: this.item.appRoles, disabled: true }, context.getValidation('appRoles').validators) + }); + } + + createValidationContext(): ValidationContext { + const validationContext: ValidationContext = new ValidationContext(); + const validationArray: Validation[] = new Array(); + + validationArray.push({ key: 'appRoles' }); + + validationContext.validation = validationArray; + return validationContext; + } + + formSubmit(): void { + this.clearErrorModel(); + + const modifiedItem = this.item; + modifiedItem.appRoles = this.getFormControl('appRoles').value; + + if (!this.isFormValid()) { return; } + this.userService.updateRoles(modifiedItem) + .pipe(takeUntil(this._destroyed)) + .subscribe( + (res) => this.onCallbackSuccess(), + (error) => this.onCallbackError(error) + ); + } + + editItem(): void { + this.formGroup.enable(); + this.nowEditing = true; + } + + isFormValid(): boolean { + this.touchAllFormFields(this.formGroup); + this.validateAllFormFields(this.formGroup); + return this.formGroup.valid; + } + + getFormData(): any { + return this.formGroup.value; + } + + getFormControl(controlName: string): AbstractControl { + return this.formGroup.get(controlName); + } + + validateAllFormFields(formControl: AbstractControl) { + if (formControl instanceof FormControl) { + formControl.updateValueAndValidity({ emitEvent: false }); + } else if (formControl instanceof FormGroup) { + Object.keys(formControl.controls).forEach(item => { + const control = formControl.get(item); + this.validateAllFormFields(control); + }); + } else if (formControl instanceof FormArray) { + formControl.controls.forEach(item => { + this.validateAllFormFields(item); + }); + } + } + + touchAllFormFields(formControl: AbstractControl) { + if (formControl instanceof FormControl) { + formControl.markAsTouched(); + } else if (formControl instanceof FormGroup) { + Object.keys(formControl.controls).forEach(item => { + const control = formControl.get(item); + this.touchAllFormFields(control); + }); + } else if (formControl instanceof FormArray) { + formControl.controls.forEach(item => { + this.touchAllFormFields(item); + }); + } + } + + setErrorModel(errorModel: any) { + // Object.keys(errorModel).forEach(item => { + // (this.errorModel)[item] = (errorModel)[item]; + // }); + } + + clearErrorModel() { + // Object.keys(this.errorModel).forEach(item => { + // (this.errorModel)[item] = ''; + // }); + } + + onCallbackSuccess() { + this.nowEditing = false; + this.formGroup.disable(); + this.snackBar.openFromComponent(SnackBarNotificationComponent, { + data: { message: 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, + duration: 3000, + }); + } + onCallbackError(error: any) { + this.setErrorModel(error.error); + this.validateAllFormFields(this.formGroup); + this.snackBar.openFromComponent(SnackBarNotificationComponent, { + data: { message: 'GENERAL.SNACK-BAR.UNSUCCESSFUL-UPDATE', language: this.language }, + duration: 3000, + }); + } + + getPrincipalAppRoleValues(): Number[] { + let keys: string[] = Object.keys(AppRole); + keys = keys.slice(0, keys.length / 2); + const values: Number[] = keys.map(Number); + return values; + } + + getPrincipalAppRoleWithLanguage(role: AppRole): string { + let result = ''; + this.language.get(this.enumUtils.convertFromPrincipalAppRole(role)) + .pipe(takeUntil(this._destroyed)) + .subscribe((value: string) => { + result = value; + }); + return result; + } +} diff --git a/dmp-frontend/src/app/ui/admin/user/listing/user-listing.component.html b/dmp-frontend/src/app/ui/admin/user/listing/user-listing.component.html new file mode 100644 index 000000000..93c57fe64 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/user/listing/user-listing.component.html @@ -0,0 +1,39 @@ +
+

{{'USERS.LISTING.TITLE' | translate}}

+ + + + + + + + {{'USERS.LISTING.LABEL' | translate}} + {{row.name}} + + + + {{'USERS.LISTING.EMAIL' | translate}} + {{row.email}} + + + + {{'USERS.LISTING.LAST-LOGGED-IN' | translate}} + {{row.lastloggedin | date:'shortDate'}} + + + + + {{'USERS.LISTING.ROLES' | translate}} + + + + + + + + + + + + +
diff --git a/dmp-frontend/src/app/ui/admin/user/listing/user-listing.component.scss b/dmp-frontend/src/app/ui/admin/user/listing/user-listing.component.scss new file mode 100644 index 000000000..69f12238e --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/user/listing/user-listing.component.scss @@ -0,0 +1,14 @@ +.user-listing { + + .mat-card { + margin: 1em 0; + } + + mat-row:hover { + background-color: lightgray; + } + + mat-row:nth-child(odd) { + background-color: #eef0fb; + } +} \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/user/listing/user-listing.component.ts b/dmp-frontend/src/app/ui/admin/user/listing/user-listing.component.ts new file mode 100644 index 000000000..ee69e25c4 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/user/listing/user-listing.component.ts @@ -0,0 +1,127 @@ +import { DataSource } from '@angular/cdk/table'; +import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core'; +import { MatPaginator, MatSnackBar, MatSort } from '@angular/material'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { UserListingModel } from '../../../../core/model/user/user-listing'; +import { UserCriteria } from '../../../../core/query/user/user-criteria'; +import { UserService } from '../../../../core/services/user/user.service'; +import { SnackBarNotificationComponent } from '../../../../library/notification/snack-bar/snack-bar-notification.component'; +import { DataTableRequest } from '../../../../core/model/data-table/data-table-request'; +import { UserCriteriaComponent } from './criteria/user-criteria.component'; + +export class UsersDataSource extends DataSource { + + totalCount = 0; + + constructor( + private _service: UserService, + private _paginator: MatPaginator, + private _sort: MatSort, + private _languageService: TranslateService, + private _snackBar: MatSnackBar, + private _criteria: UserCriteriaComponent + ) { + super(); + + //this._paginator.page.pipe(takeUntil(this._destroyed)).subscribe((pageEvent: PageEvent) => { + // this.store.dispatch(new LoadPhotosRequestAction(pageEvent.pageIndex, pageEvent.pageSize)) + //}) + } + + connect(): Observable { + const displayDataChanges = [ + this._paginator.page + //this._sort.matSortChange + ]; + + // If the user changes the sort order, reset back to the first page. + //this._sort.matSortChange.pipe(takeUntil(this._destroyed)).subscribe(() => { + // this._paginator.pageIndex = 0; + //}) + + return Observable.merge(...displayDataChanges) + .startWith(null) + .switchMap(() => { + const startIndex = this._paginator.pageIndex * this._paginator.pageSize; + let fields: Array = new Array(); + if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; } + const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); + request.criteria = this._criteria.getFormData(); + return this._service.getPaged(request); + }) + .catch((error: any) => { + this._snackBar.openFromComponent(SnackBarNotificationComponent, { + data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService }, + duration: 3000, + }); + this._criteria.onCallbackError(error); + return Observable.of(null); + }) + .map(result => { + return result; + }) + .map(result => { + if (!result) { return []; } + if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; } + //result.data.forEach((element: any) => { + // const roles: String[] = []; + // element.roles.forEach((role: any) => { + // this._languageService.get(this._utilities.convertFromPrincipalAppRole(role)).pipe(takeUntil(this._destroyed)).subscribe( + // value => roles.push(value) + // ); + // }); + // element.roles = roles; + //}); + return result.data; + }); + } + + disconnect() { + // No-op + } +} + +@Component({ + selector: 'app-user-listing-component', + templateUrl: './user-listing.component.html', + styleUrls: ['./user-listing.component.scss'] +}) +export class UserListingComponent implements OnInit, AfterViewInit { + + @ViewChild(MatPaginator) _paginator: MatPaginator; + @ViewChild(MatSort) sort: MatSort; + @ViewChild(UserCriteriaComponent) criteria: UserCriteriaComponent; + + dataSource: UsersDataSource | null; + displayedColumns: String[] = ['name', 'email', 'lastloggedin', 'roles']; + + constructor( + private userService: UserService, + private languageService: TranslateService, + public snackBar: MatSnackBar + ) { + + } + + ngOnInit() { + //this.refresh(); //called on ngAfterViewInit with default criteria + } + + ngAfterViewInit() { + setTimeout(() => { + this.criteria.setRefreshCallback(() => this.refresh()); + this.criteria.setCriteria(this.getDefaultCriteria()); + this.criteria.controlModified(); + }); + } + + refresh() { + this.dataSource = new UsersDataSource(this.userService, this._paginator, this.sort, this.languageService, this.snackBar, this.criteria); + } + + getDefaultCriteria(): UserCriteria { + const defaultCriteria = new UserCriteria(); + return defaultCriteria; + } +} diff --git a/dmp-frontend/src/app/ui/admin/user/user.module.ts b/dmp-frontend/src/app/ui/admin/user/user.module.ts new file mode 100644 index 000000000..18257c942 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/user/user.module.ts @@ -0,0 +1,24 @@ +import { NgModule } from '@angular/core'; +import { CommonFormsModule } from '../../../common/forms/common-forms.module'; +import { CommonUiModule } from '../../../common/ui/common-ui.module'; +import { FormattingModule } from '../../../core/formatting.module'; +import { UserCriteriaComponent } from './listing/criteria/user-criteria.component'; +import { UserRoleEditorComponent } from './listing/role-editor/user-role-editor.component'; +import { UserListingComponent } from './listing/user-listing.component'; +import { UserRoutingModule } from './user.routing'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule, + FormattingModule, + UserRoutingModule + ], + declarations: [ + UserListingComponent, + UserCriteriaComponent, + UserRoleEditorComponent + ], +}) + +export class UserModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/user/user.routing.ts b/dmp-frontend/src/app/ui/admin/user/user.routing.ts new file mode 100644 index 000000000..500a5a7e4 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/user/user.routing.ts @@ -0,0 +1,14 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { UserListingComponent } from './listing/user-listing.component'; + +const routes: Routes = [ + { path: '', component: UserListingComponent }, + // { path: ':id', component: UserProfileComponent } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class UserRoutingModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/user-management/admin-login/admin-login.component.html b/dmp-frontend/src/app/ui/auth/admin-login/admin-login.component.html similarity index 100% rename from dmp-frontend/src/app/user-management/admin-login/admin-login.component.html rename to dmp-frontend/src/app/ui/auth/admin-login/admin-login.component.html diff --git a/dmp-frontend/src/app/user-management/admin-login/admin-login.component.scss b/dmp-frontend/src/app/ui/auth/admin-login/admin-login.component.scss similarity index 100% rename from dmp-frontend/src/app/user-management/admin-login/admin-login.component.scss rename to dmp-frontend/src/app/ui/auth/admin-login/admin-login.component.scss diff --git a/dmp-frontend/src/app/ui/auth/admin-login/admin-login.component.ts b/dmp-frontend/src/app/ui/auth/admin-login/admin-login.component.ts new file mode 100644 index 000000000..a57af703a --- /dev/null +++ b/dmp-frontend/src/app/ui/auth/admin-login/admin-login.component.ts @@ -0,0 +1,52 @@ +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../core/common/base/base.component'; +import { Credential } from '../../../core/model/auth/credential'; +import { CultureService } from '../../../core/services/culture/culture-service'; +import { SnackBarNotificationLevel, UiNotificationService } from '../../../core/services/notification/ui-notification-service'; +import { AuthService } from '../../../core/services/auth/auth.service'; + +@Component({ + selector: 'app-admin-login', + templateUrl: './admin-login.component.html', + styleUrls: ['./admin-login.component.scss'] +}) +export class AdminLoginComponent extends BaseComponent implements OnInit { + + public auth2: any; + public credential: Credential = new Credential(); + + constructor( + private authService: AuthService, + private uiNotificationService: UiNotificationService, + private language: TranslateService, + private cultureService: CultureService, + private router: Router + ) { super(); } + + + + ngOnInit() { + } + + public nativeLogin() { + this.authService.nativeLogin(this.credential) + .pipe(takeUntil(this._destroyed)) + .subscribe( + res => this.onLogInSuccess(res), + error => this.onLogInError(error) + ); + } + + public onLogInSuccess(loginResponse: any) { + this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Success); + if (this.authService.current().culture) { this.cultureService.cultureSelected(this.authService.current().culture); } + this.router.navigate(['/']); + } + + public onLogInError(errorMessage: string) { + this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Error); + } +} diff --git a/dmp-frontend/src/app/ui/auth/admin-login/admin-login.module.ts b/dmp-frontend/src/app/ui/auth/admin-login/admin-login.module.ts new file mode 100644 index 000000000..c4c98b17d --- /dev/null +++ b/dmp-frontend/src/app/ui/auth/admin-login/admin-login.module.ts @@ -0,0 +1,17 @@ +import { NgModule } from '@angular/core'; +import { CommonFormsModule } from '../../../common/forms/common-forms.module'; +import { CommonUiModule } from '../../../common/ui/common-ui.module'; +import { AdminLoginComponent } from './admin-login.component'; +import { AdminLoginRoutingModule } from './admin-login.routing'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule, + AdminLoginRoutingModule + ], + declarations: [ + AdminLoginComponent + ] +}) +export class AdminLoginModule { } diff --git a/dmp-frontend/src/app/ui/auth/admin-login/admin-login.routing.ts b/dmp-frontend/src/app/ui/auth/admin-login/admin-login.routing.ts new file mode 100644 index 000000000..b3e6deae3 --- /dev/null +++ b/dmp-frontend/src/app/ui/auth/admin-login/admin-login.routing.ts @@ -0,0 +1,16 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { AdminLoginComponent } from './admin-login.component'; + +const routes: Routes = [ + { + path: '', + component: AdminLoginComponent, + }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class AdminLoginRoutingModule { } diff --git a/dmp-frontend/src/app/user-management/login/b2access/b2access-login.component.html b/dmp-frontend/src/app/ui/auth/login/b2access/b2access-login.component.html similarity index 100% rename from dmp-frontend/src/app/user-management/login/b2access/b2access-login.component.html rename to dmp-frontend/src/app/ui/auth/login/b2access/b2access-login.component.html diff --git a/dmp-frontend/src/app/ui/auth/login/b2access/b2access-login.component.ts b/dmp-frontend/src/app/ui/auth/login/b2access/b2access-login.component.ts new file mode 100644 index 000000000..c18b6b0bc --- /dev/null +++ b/dmp-frontend/src/app/ui/auth/login/b2access/b2access-login.component.ts @@ -0,0 +1,53 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { takeUntil } from 'rxjs/operators'; +import { environment } from '../../../../../environments/environment'; +import { BaseComponent } from '../../../../core/common/base/base.component'; +import { LoginService } from '../utilities/login.service'; + +@Component({ + selector: 'app-b2access-login', + templateUrl: './b2access-login.component.html', +}) +export class B2AccessLoginComponent extends BaseComponent implements OnInit { + + private returnUrl: string; + + constructor( + private router: Router, + private route: ActivatedRoute, + private loginService: LoginService + ) { + super(); + } + + ngOnInit(): void { + this.route.queryParams + .pipe(takeUntil(this._destroyed)) + .subscribe((params: Params) => { + const returnUrl = params['returnUrl']; + if (returnUrl) { this.returnUrl = returnUrl; } + if (!params['code']) { this.b2AccessGetAuthCode(); } else { this.b2AccessLogin(params['code']); } + }); + } + + public b2AccessGetAuthCode() { + window.location.href = environment.loginProviders.b2accessConfiguration.oauthUrl + '?response_type=code&client_id=' + environment.loginProviders.b2accessConfiguration.clientId + '&redirect_uri=' + environment.loginProviders.b2accessConfiguration.redirectUri + '&state=987654321&scope=USER_PROFILE'; + } + + public b2AccessLogin(code: String) { + // let headers = new HttpHeaders(); + // headers = headers.set('Content-Type', 'application/json'); + // headers = headers.set('Accept', 'application/json'); + // this.httpClient.post(environment.Server + 'auth/b2AccessRequestToken', { code: code }, { headers: headers }) + // .pipe(takeUntil(this._destroyed)) + // .subscribe((data: any) => { + // this.authService.login({ ticket: data.payload.accessToken, provider: AuthProvider.B2Accesss, data: null }) + // .pipe(takeUntil(this._destroyed)) + // .subscribe( + // res => this.onLogInSuccess(res), + // error => this.onLogInError(error) + // ); + // }); + } +} diff --git a/dmp-frontend/src/app/user-management/login/img/b2access.png b/dmp-frontend/src/app/ui/auth/login/img/b2access.png similarity index 100% rename from dmp-frontend/src/app/user-management/login/img/b2access.png rename to dmp-frontend/src/app/ui/auth/login/img/b2access.png diff --git a/dmp-frontend/src/app/user-management/login/img/b2access_medium.png b/dmp-frontend/src/app/ui/auth/login/img/b2access_medium.png similarity index 100% rename from dmp-frontend/src/app/user-management/login/img/b2access_medium.png rename to dmp-frontend/src/app/ui/auth/login/img/b2access_medium.png diff --git a/dmp-frontend/src/app/user-management/login/img/b2access_small.png b/dmp-frontend/src/app/ui/auth/login/img/b2access_small.png similarity index 100% rename from dmp-frontend/src/app/user-management/login/img/b2access_small.png rename to dmp-frontend/src/app/ui/auth/login/img/b2access_small.png diff --git a/dmp-frontend/src/app/user-management/login/linkedin-login/linkedin-login.component.html b/dmp-frontend/src/app/ui/auth/login/linkedin-login/linkedin-login.component.html similarity index 100% rename from dmp-frontend/src/app/user-management/login/linkedin-login/linkedin-login.component.html rename to dmp-frontend/src/app/ui/auth/login/linkedin-login/linkedin-login.component.html diff --git a/dmp-frontend/src/app/ui/auth/login/linkedin-login/linkedin-login.component.ts b/dmp-frontend/src/app/ui/auth/login/linkedin-login/linkedin-login.component.ts new file mode 100644 index 000000000..5af22cde4 --- /dev/null +++ b/dmp-frontend/src/app/ui/auth/login/linkedin-login/linkedin-login.component.ts @@ -0,0 +1,49 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Params } from '@angular/router'; +import { takeUntil } from 'rxjs/operators'; +import { environment } from '../../../../../environments/environment'; +import { BaseComponent } from '../../../../core/common/base/base.component'; +import { AuthProvider } from '../../../../core/common/enum/auth-provider'; +import { AuthService } from '../../../../core/services/auth/auth.service'; +import { LoginService } from '../utilities/login.service'; + +@Component({ + selector: 'app-linkedin-login', + templateUrl: './linkedin-login.component.html', +}) +export class LinkedInLoginComponent extends BaseComponent implements OnInit { + + private returnUrl: string; + + constructor( + private route: ActivatedRoute, + private loginService: LoginService, + private authService: AuthService + ) { + super(); + } + + ngOnInit(): void { + this.route.queryParams + .pipe(takeUntil(this._destroyed)) + .subscribe((params: Params) => { + const returnUrl = params['returnUrl']; + if (returnUrl) { this.returnUrl = returnUrl; } + if (!params['code']) { this.linkedinAuthorize(); } else { this.linkedInLoginUser(params['code']); } + }); + } + + public linkedinAuthorize() { + window.location.href = environment.loginProviders.linkedInConfiguration.oauthUrl + '?response_type=code&client_id=' + environment.loginProviders.linkedInConfiguration.clientId + '&redirect_uri=' + environment.loginProviders.linkedInConfiguration.redirectUri + '&state=987654321'; + } + + + public linkedInLoginUser(code: string) { + this.authService.login({ ticket: code, provider: AuthProvider.LinkedIn }) + .pipe(takeUntil(this._destroyed)) + .subscribe( + res => this.loginService.onLogInSuccess(res, this.returnUrl), + error => this.loginService.onLogInError(error) + ); + } +} diff --git a/dmp-frontend/src/app/ui/auth/login/login.component.html b/dmp-frontend/src/app/ui/auth/login/login.component.html new file mode 100644 index 000000000..338a9ed59 --- /dev/null +++ b/dmp-frontend/src/app/ui/auth/login/login.component.html @@ -0,0 +1,28 @@ +
+
+
+
+

Login

+ + +
+

You dont need to have a registered account for OpenDMP

+
+
+
diff --git a/dmp-frontend/src/app/user-management/login/login.component.scss b/dmp-frontend/src/app/ui/auth/login/login.component.scss similarity index 100% rename from dmp-frontend/src/app/user-management/login/login.component.scss rename to dmp-frontend/src/app/ui/auth/login/login.component.scss diff --git a/dmp-frontend/src/app/ui/auth/login/login.component.ts b/dmp-frontend/src/app/ui/auth/login/login.component.ts new file mode 100644 index 000000000..3d0928966 --- /dev/null +++ b/dmp-frontend/src/app/ui/auth/login/login.component.ts @@ -0,0 +1,156 @@ +import { AfterViewInit, Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { takeUntil } from 'rxjs/operators'; +import { environment } from '../../../../environments/environment'; +import { BaseComponent } from '../../../core/common/base/base.component'; +import { AuthProvider } from '../../../core/common/enum/auth-provider'; +import { AuthService } from '../../../core/services/auth/auth.service'; +import { LoginService } from './utilities/login.service'; +/// +/// + +@Component({ + selector: 'app-login', + templateUrl: './login.component.html', + styleUrls: ['./login.component.scss'] +}) +export class LoginComponent extends BaseComponent implements OnInit, AfterViewInit { + + public auth2: any; + private returnUrl: string; + + constructor( + private router: Router, + private route: ActivatedRoute, + private loginService: LoginService, + private authService: AuthService + ) { super(); } + + ngOnInit(): void { + this.route.queryParams + .pipe(takeUntil(this._destroyed)) + .subscribe((params: Params) => { + const returnUrl = params['returnUrl']; + if (returnUrl) { this.returnUrl = returnUrl; } + }); + } + + ngAfterViewInit() { + this.initProviders(); + } + + public linkedInLogin() { + this.router.navigate(['/login/linkedin']); + } + + public twitterLogin() { + this.router.navigate(['/login/twitter']); + } + + public b2AccessLogin() { + this.router.navigate(['/api/oauth/authorized/b2access']); + } + + public hasFacebookOauth(): boolean { + return this.hasProvider(AuthProvider.Facebook); + } + + public hasLinkedInOauth(): boolean { + return this.hasProvider(AuthProvider.LinkedIn); + } + + public hasTwitterOauth(): boolean { + return this.hasProvider(AuthProvider.Twitter); + } + + public hasGoogleOauth(): boolean { + return this.hasProvider(AuthProvider.Google); + } + + public hasB2AccessOauth(): boolean { + return this.hasProvider(AuthProvider.B2Access); + } + + public initProviders() { + if (this.hasProvider(AuthProvider.Google)) { this.initializeGoogleOauth(); } + if (this.hasProvider(AuthProvider.Facebook)) { this.initializeFacebookOauth(); } + } + + public hasProvider(provider: AuthProvider) { + for (let i = 0; i < environment.loginProviders.enabled.length; i++) { + if (provider === environment.loginProviders.enabled[i]) { return this.isProviderProperlyConfigured(provider); } + } + return false; + } + + private isProviderProperlyConfigured(provider: AuthProvider) { + switch (provider) { + case AuthProvider.Facebook: return this.hasAllRequiredFieldsConfigured(environment.loginProviders.facebookConfiguration); + case AuthProvider.Google: return this.hasAllRequiredFieldsConfigured(environment.loginProviders.googleConfiguration); + case AuthProvider.LinkedIn: return this.hasAllRequiredFieldsConfigured(environment.loginProviders.linkedInConfiguration); + case AuthProvider.Twitter: return this.hasAllRequiredFieldsConfigured(environment.loginProviders.twitterConfiguration); + case AuthProvider.B2Access: return this.hasAllRequiredFieldsConfigured(environment.loginProviders.b2accessConfiguration); + default: throw new Error('Unsupported Provider Type'); + } + } + + private hasAllRequiredFieldsConfigured(configuration: any) { + if (configuration != null && configuration.clientId != null) { return true; } + return false; + } + + /* + * GOOGLE SIGN IN + */ + private initializeGoogleOauth(): void { + gapi.load('auth2', () => { + this.auth2 = gapi.auth2.init({ + client_id: environment.loginProviders.googleConfiguration.clientId, + scope: 'profile email' + }); + this.attachGoogleSignΙn(document.getElementById('googleSignInButton')); + }); + } + + public attachGoogleSignΙn(element) { + if (!element) { return; } + this.auth2.attachClickHandler(element, {}, + (googleUser) => { + const id_token = googleUser.getAuthResponse().id_token; + if (id_token) { + this.authService.login({ ticket: id_token, provider: AuthProvider.Google }) + .pipe(takeUntil(this._destroyed)) + .subscribe( + res => this.loginService.onLogInSuccess(res, this.returnUrl), + error => this.loginService.onLogInError(error) + ); + } + }, (error) => { + }); + } + + /* + * FACEBOOK SIGN IN + */ + private initializeFacebookOauth(): void { + FB.init({ + appId: environment.loginProviders.facebookConfiguration.clientId, + cookie: false, + xfbml: true, + version: 'v2.8' + }); + } + + public facebookLogin() { + FB.login((response: any) => { + if (response.status === 'connected' || 'not_authorized') { + this.authService.login({ ticket: response.authResponse.accessToken, provider: AuthProvider.Facebook }) + .pipe(takeUntil(this._destroyed)) + .subscribe( + res => this.loginService.onLogInSuccess(res, this.returnUrl), + error => this.loginService.onLogInError(error) + ); + } + }, { scope: 'user_friends,email' }); + } +} diff --git a/dmp-frontend/src/app/ui/auth/login/login.module.ts b/dmp-frontend/src/app/ui/auth/login/login.module.ts new file mode 100644 index 000000000..5edc6af4c --- /dev/null +++ b/dmp-frontend/src/app/ui/auth/login/login.module.ts @@ -0,0 +1,23 @@ +import { NgModule } from '@angular/core'; +import { CommonFormsModule } from '../../../common/forms/common-forms.module'; +import { CommonUiModule } from '../../../common/ui/common-ui.module'; +import { LinkedInLoginComponent } from './linkedin-login/linkedin-login.component'; +import { LoginComponent } from './login.component'; +import { LoginRoutingModule } from './login.routing'; +import { TwitterLoginComponent } from './twitter-login/twitter-login.component'; +import { LoginService } from './utilities/login.service'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule, + LoginRoutingModule + ], + declarations: [ + LoginComponent, + LinkedInLoginComponent, + TwitterLoginComponent, + ], + providers: [LoginService] +}) +export class LoginModule { } diff --git a/dmp-frontend/src/app/ui/auth/login/login.routing.ts b/dmp-frontend/src/app/ui/auth/login/login.routing.ts new file mode 100644 index 000000000..5f84e5562 --- /dev/null +++ b/dmp-frontend/src/app/ui/auth/login/login.routing.ts @@ -0,0 +1,17 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { LinkedInLoginComponent } from './linkedin-login/linkedin-login.component'; +import { LoginComponent } from './login.component'; +import { TwitterLoginComponent } from './twitter-login/twitter-login.component'; + +const routes: Routes = [ + { path: '', component: LoginComponent }, + { path: 'linkedin', component: LinkedInLoginComponent }, + { path: 'twitter', component: TwitterLoginComponent } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class LoginRoutingModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/user-management/login/twitter-login/twitter-login.component.html b/dmp-frontend/src/app/ui/auth/login/twitter-login/twitter-login.component.html similarity index 100% rename from dmp-frontend/src/app/user-management/login/twitter-login/twitter-login.component.html rename to dmp-frontend/src/app/ui/auth/login/twitter-login/twitter-login.component.html diff --git a/dmp-frontend/src/app/ui/auth/login/twitter-login/twitter-login.component.ts b/dmp-frontend/src/app/ui/auth/login/twitter-login/twitter-login.component.ts new file mode 100644 index 000000000..da8f59971 --- /dev/null +++ b/dmp-frontend/src/app/ui/auth/login/twitter-login/twitter-login.component.ts @@ -0,0 +1,58 @@ +import { HttpHeaders } from '@angular/common/http'; +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Params } from '@angular/router'; +import { takeUntil } from 'rxjs/operators'; +import { environment } from '../../../../../environments/environment'; +import { BaseComponent } from '../../../../core/common/base/base.component'; +import { AuthService } from '../../../../core/services/auth/auth.service'; +import { BaseHttpService } from '../../../../core/services/http/base-http.service'; +import { LoginService } from '../utilities/login.service'; +import { AuthProvider } from '../../../../core/common/enum/auth-provider'; + +@Component({ + selector: 'app-twitter-login', + templateUrl: './twitter-login.component.html', +}) +export class TwitterLoginComponent extends BaseComponent implements OnInit { + + private returnUrl: string; + + constructor( + private route: ActivatedRoute, + private authService: AuthService, + private httpClient: BaseHttpService, + private loginService: LoginService + ) { + super(); + } + + ngOnInit(): void { + this.route.queryParams + .pipe(takeUntil(this._destroyed)) + .subscribe((params: Params) => { + const returnUrl = params['returnUrl']; + if (returnUrl) { this.returnUrl = returnUrl; } + if (!params['oauth_token'] && !params['oauth_verifier']) { this.twitterAuthorize(); } else { this.twitterLogin(params['oauth_token'], params['oauth_verifier']); } + }); + } + + public twitterAuthorize() { + let headers = new HttpHeaders(); + headers = headers.set('Content-Type', 'application/json'); + headers = headers.set('Accept', 'application/json'); + this.httpClient.get(environment.Server + 'auth/twitterRequestToken', { headers: headers }) + .pipe(takeUntil(this._destroyed)) + .subscribe((data: any) => { + window.location.href = environment.loginProviders.twitterConfiguration.oauthUrl + '?oauth_token=' + data.payload.value; + }); + } + + public twitterLogin(token: string, verifier: string) { + this.authService.login({ ticket: token, provider: AuthProvider.Twitter, data: verifier }) + .pipe(takeUntil(this._destroyed)) + .subscribe( + res => this.loginService.onLogInSuccess(res, this.returnUrl), + error => this.loginService.onLogInError(error) + ); + } +} diff --git a/dmp-frontend/src/app/ui/auth/login/utilities/login.service.ts b/dmp-frontend/src/app/ui/auth/login/utilities/login.service.ts new file mode 100644 index 000000000..8f925dd2b --- /dev/null +++ b/dmp-frontend/src/app/ui/auth/login/utilities/login.service.ts @@ -0,0 +1,55 @@ +import { Injectable, NgZone } from '@angular/core'; +import { Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { BaseService } from '../../../../core/common/base/base.service'; +import { CultureService } from '../../../../core/services/culture/culture-service'; +import { UiNotificationService, SnackBarNotificationLevel } from '../../../../core/services/notification/ui-notification-service'; +import { AuthService } from '../../../../core/services/auth/auth.service'; + +@Injectable() +export class LoginService extends BaseService { + + constructor( + private router: Router, + private authService: AuthService, + private language: TranslateService, + private zone: NgZone, + private cultureService: CultureService, + private uiNotificationService: UiNotificationService + ) { + super(); + } + + + + + // /* + // * NATIVE LOGIN + // */ + + // public nativeLogin(credentials: Credential) { + // this.authService.nativeLogin(credentials) + // .pipe(takeUntil(this._destroyed)) + // .subscribe( + // res => this.onLogInSuccess(res), + // error => this.onLogInError(error) + // ); + // } + + + // /* + // * LOGIN HANDLERS + // */ + + + public onLogInSuccess(loginResponse: any, returnUrl: string) { + this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Success); + if (this.authService.current().culture) { this.cultureService.cultureSelected(this.authService.current().culture); } + const redirectUrl = returnUrl || '/'; + this.router.navigate([redirectUrl]); + } + + public onLogInError(errorMessage: string) { + this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Error); + } +} diff --git a/dmp-frontend/src/app/shared/components/figurecard/figurecard.component.html b/dmp-frontend/src/app/ui/dashboard/card/card.component.html similarity index 100% rename from dmp-frontend/src/app/shared/components/figurecard/figurecard.component.html rename to dmp-frontend/src/app/ui/dashboard/card/card.component.html diff --git a/dmp-frontend/src/app/shared/components/figurecard/figurecard.component.scss b/dmp-frontend/src/app/ui/dashboard/card/card.component.scss similarity index 100% rename from dmp-frontend/src/app/shared/components/figurecard/figurecard.component.scss rename to dmp-frontend/src/app/ui/dashboard/card/card.component.scss diff --git a/dmp-frontend/src/app/ui/dashboard/card/card.component.ts b/dmp-frontend/src/app/ui/dashboard/card/card.component.ts new file mode 100644 index 000000000..d73b83814 --- /dev/null +++ b/dmp-frontend/src/app/ui/dashboard/card/card.component.ts @@ -0,0 +1,41 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { AuthService } from '../../../core/services/auth/auth.service'; + +@Component({ + selector: 'app-dashboard-card', + templateUrl: './card.component.html', + styleUrls: ['./card.component.scss'] +}) +export class CardComponent implements OnInit { + @Input() headerIcon: string; + @Input() category: string; + @Input() title: string; + @Input() footerIcon: string; + @Input() footContent: string; + @Input() linearColor: string; + @Input() boxShadow: string; + @Input() routelLink: string; + @Input() hasFootContent = false; + @Input() buttonTitle: string; + @Input() buttonRedirectLink: string; + + constructor(private router: Router, private authService: AuthService) { } + + ngOnInit() { + } + + navigateToUrl() { + if (!this.isAuthenticated()) { return; } + this.router.navigate([this.routelLink]); + } + + createNew() { + this.router.navigate([this.buttonRedirectLink]); + } + + isAuthenticated() { + return this.authService.current() != null; + } + +} diff --git a/dmp-frontend/src/app/ui/dashboard/dashboard.component.html b/dmp-frontend/src/app/ui/dashboard/dashboard.component.html new file mode 100644 index 000000000..2bb207abf --- /dev/null +++ b/dmp-frontend/src/app/ui/dashboard/dashboard.component.html @@ -0,0 +1,85 @@ +
+
+
+
+
+

{{ 'HOMEPAGE.OPEN-DMPS.STATS' | translate }}

+

{{ 'HOMEPAGE.MY-DMPS.STATS' | translate }}

+
+
+
+
+
+
+
+ + + + + + {{'RECENT-ACTIVITY.MY-TITLE-DMP' | translate}} + + + + + +

+ {{activity.label}} +

+

+ {{activity.timestamp | date:'shortDate'}} +

+
+
+
+
+
+
+ + + + + + {{'RECENT-ACTIVITY.MY-TITLE-PROJECT' | translate}} + + + + + +

+ {{activity.label}} +

+

+ {{activity.timestamp | date:'shortDate'}} +

+
+
+
+
+
+
+ + + + + + {{'RECENT-ACTIVITY.MY-TITLE-DATASET' | translate}} + + + + + +

+ {{activity.label}} +

+

+ {{activity.timestamp | date:'shortDate'}} +

+
+
+
+
+
+
+
+
diff --git a/dmp-frontend/src/app/ui/dashboard/dashboard.component.scss b/dmp-frontend/src/app/ui/dashboard/dashboard.component.scss new file mode 100644 index 000000000..8f731bd9d --- /dev/null +++ b/dmp-frontend/src/app/ui/dashboard/dashboard.component.scss @@ -0,0 +1,61 @@ +.dashboard { + .card { + padding: 25px 20px 20px 20px; + display: flex; + flex-direction: column; + align-items: center; + } + + .card h6, + p { + color: #999; + } + + .icon { + margin-top: 20px; + width: 130px; + height: 130px; + border: 1px solid #e5e5e5; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + } + + .icon i { + font-size: 55px; + color: #e91e63; + } + + .card-title { + margin-top: 30px; + margin-bottom: 3px; + } + + .card-description { + margin-bottom: 20px; + } + + .card-dataset { + display: flex; + flex-direction: column; + padding: 20px; + position: relative; + margin-top: 40px; + } + + .card { + box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.14); + border-radius: 6px; + color: rgba(0, 0, 0, 0.87); + background: #fff; + } + + .card-raised { + box-shadow: 0 10px 30px -12px rgba(0, 0, 0, 0.42), 0 4px 25px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); + } + + .full-width { + width: 100%; + } +} diff --git a/dmp-frontend/src/app/ui/dashboard/dashboard.component.ts b/dmp-frontend/src/app/ui/dashboard/dashboard.component.ts new file mode 100644 index 000000000..39a99348c --- /dev/null +++ b/dmp-frontend/src/app/ui/dashboard/dashboard.component.ts @@ -0,0 +1,124 @@ +import { Component, OnInit } from '@angular/core'; +import { FormControl } from '@angular/forms'; +import { Router } from '@angular/router'; +import { Observable } from 'rxjs/internal/Observable'; +import { takeUntil } from 'rxjs/operators'; +import { JsonSerializer } from '../../common/types/json/json-serializer'; +import { BaseComponent } from '../../core/common/base/base.component'; +import { RecentActivityType } from '../../core/common/enum/recent-activity-type'; +import { DashboardStatisticsModel } from '../../core/model/dashboard/dashboard-statistics-model'; +import { SearchBarItem } from '../../core/model/dashboard/search-bar-item'; +import { ProjectCriteria } from '../../core/query/project/project-criteria'; +import { AuthService } from '../../core/services/auth/auth.service'; +import { DashboardService } from '../../core/services/dashboard/dashboard.service'; +import { ProjectService } from '../../core/services/project/project.service'; +import { SearchBarService } from '../../core/services/search-bar/search-bar.service'; +import { UserService } from '../../core/services/user/user.service'; +import { SingleAutoCompleteConfiguration } from '../../library/auto-complete/single/single-auto-complete-configuration'; +import { RequestItem } from '../../core/query/request-item'; + +@Component({ + selector: 'app-dashboard', + templateUrl: './dashboard.component.html', + styleUrls: ['./dashboard.component.scss'], +}) +export class DashboardComponent extends BaseComponent implements OnInit { + + public userInfo: any; + datasetActivities: any[]; + projectActivities: any[]; + dmpActivities: any[]; + public dashboardStatisticsData: DashboardStatisticsModel; + public formControl = new FormControl(); + projectAutoCompleteConfiguration: SingleAutoCompleteConfiguration; + public searchControl = new FormControl(); + filteredOptions: Observable; + recentActivityTypeEnum = RecentActivityType; + public search = false; + + constructor( + private router: Router, + private projectService: ProjectService, + private dashboardService: DashboardService, + private searchBarService: SearchBarService, + private authentication: AuthService, + private userService: UserService + + ) { + super(); + // this.dashboardStatisticsData.totalDataManagementPlanCount = 0; + // this.dashboardStatisticsData.totalDataSetCount = 0; + // this.dashboardStatisticsData.totalProjectCount = 0; + } + + + ngOnInit() { + + if (this.isAuthenticated()) { + this.userService.getRecentActivity() + .pipe(takeUntil(this._destroyed)) + .subscribe(response => { + this.datasetActivities = response['recentDatasetActivities']; + this.dmpActivities = response['recentDmpActivities']; + this.projectActivities = response['recentProjectActivities']; + }); + } + + // this.projectAutoCompleteConfiguration = { + // filterFn: this.searchProject.bind(this), + // items: this.searchProject(''), + // displayFn: (item) => item['label'], + // titleFn: (item) => item['label'], + // //mapFn: (item) => new JsonSerializer().fromJSONArray(item, ProjectReference).map(item => item.toDropdownList()), + // loadDataOnStart: true + // }; + + if (!this.isAuthenticated()) { + this.dashboardService.getStatistics() + .pipe(takeUntil(this._destroyed)) + .subscribe(results => { + //let data = results['payload']; + this.dashboardStatisticsData = results; + }); + } else { + this.dashboardService.getUserStatistics() + .pipe(takeUntil(this._destroyed)) + .subscribe(results => { + this.dashboardStatisticsData = results; + }); + } + + this.filteredOptions = this.searchControl.valueChanges.flatMap(x => { + return this.searchBarService.search(x); + }); + } + + public isAuthenticated(): boolean { + return !(!this.authentication.current()); + } + + searchProject(query: string) { + const projectRequestItem: RequestItem = new RequestItem(); + projectRequestItem.criteria = new ProjectCriteria(); + projectRequestItem.criteria.like = query; + return this.projectService.getWithExternal(projectRequestItem); + } + + redirect(id: string, type: RecentActivityType) { + switch (type) { + case RecentActivityType.Project: { + this.router.navigate(['projects/edit/' + id]); + return; + } + case RecentActivityType.Dataset: { + this.router.navigate(['datasets/edit/' + id]); + return; + } + case RecentActivityType.Dmp: { + this.router.navigate(['plans/edit/' + id]); + return; + } + default: throw new Error('Unsupported Activity Type '); + } + } +} diff --git a/dmp-frontend/src/app/ui/dashboard/dashboard.module.ts b/dmp-frontend/src/app/ui/dashboard/dashboard.module.ts new file mode 100644 index 000000000..03ff37b8d --- /dev/null +++ b/dmp-frontend/src/app/ui/dashboard/dashboard.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from '@angular/core'; +import { CommonUiModule } from '../../common/ui/common-ui.module'; +import { CardComponent } from './card/card.component'; +import { DashboardComponent } from './dashboard.component'; +import { DashboardRoutingModule } from './dashboard.routing'; +import { RecentActivityComponent } from './recent-activity/recent-activity.component'; + +@NgModule({ + imports: [ + CommonUiModule, + DashboardRoutingModule + ], + declarations: [ + DashboardComponent, + RecentActivityComponent, + CardComponent + ] +}) +export class DashboardModule { } diff --git a/dmp-frontend/src/app/ui/dashboard/dashboard.routing.ts b/dmp-frontend/src/app/ui/dashboard/dashboard.routing.ts new file mode 100644 index 000000000..f0d5ceefd --- /dev/null +++ b/dmp-frontend/src/app/ui/dashboard/dashboard.routing.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { DashboardComponent } from './dashboard.component'; + +const routes: Routes = [ + { path: '', component: DashboardComponent } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class DashboardRoutingModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/dashboard/recent-activity/recent-activity.component.html b/dmp-frontend/src/app/ui/dashboard/recent-activity/recent-activity.component.html new file mode 100644 index 000000000..778456c42 --- /dev/null +++ b/dmp-frontend/src/app/ui/dashboard/recent-activity/recent-activity.component.html @@ -0,0 +1,67 @@ +
+
+ + + + {{'RECENT-ACTIVITY.MY-TITLE-DMP' | translate}} + + + + + +

+ {{activity.label}} +

+

+ {{activity.timestamp | date:'shortDate'}} +

+
+
+
+
+
+
+ + + + {{'RECENT-ACTIVITY.MY-TITLE-PROJECT' | translate}} + + + + + +

+ {{activity.label}} +

+

+ {{activity.timestamp | date:'shortDate'}} +

+
+
+
+ +
+
+
+ + + + {{'RECENT-ACTIVITY.MY-TITLE-DATASET' | translate}} + + + + + +

+ {{activity.label}} +

+

+ {{activity.timestamp | date:'shortDate'}} +

+
+
+ +
+
+
+
diff --git a/dmp-frontend/src/app/users/activity/recent-activity.component.scss b/dmp-frontend/src/app/ui/dashboard/recent-activity/recent-activity.component.scss similarity index 100% rename from dmp-frontend/src/app/users/activity/recent-activity.component.scss rename to dmp-frontend/src/app/ui/dashboard/recent-activity/recent-activity.component.scss diff --git a/dmp-frontend/src/app/ui/dashboard/recent-activity/recent-activity.component.ts b/dmp-frontend/src/app/ui/dashboard/recent-activity/recent-activity.component.ts new file mode 100644 index 000000000..6ca7fc0fe --- /dev/null +++ b/dmp-frontend/src/app/ui/dashboard/recent-activity/recent-activity.component.ts @@ -0,0 +1,53 @@ +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../core/common/base/base.component'; +import { RecentActivityType } from '../../../core/common/enum/recent-activity-type'; +import { UserService } from '../../../core/services/user/user.service'; + +@Component({ + selector: 'app-recent-activity', + templateUrl: './recent-activity.component.html', + styleUrls: ['./recent-activity.component.scss'] +}) +export class RecentActivityComponent extends BaseComponent implements OnInit { + + datasetActivities: any[]; + projectActivities: any[]; + dmpActivities: any[]; + recentActivityTypeEnum = RecentActivityType; + + constructor( + private router: Router, + private userService: UserService + ) { super(); } + + ngOnInit() { + this.userService.getRecentActivity() + .pipe(takeUntil(this._destroyed)) + .subscribe(response => { + this.datasetActivities = response['recentDatasetActivities']; + this.dmpActivities = response['recentDmpActivities']; + this.projectActivities = response['recentProjectActivities']; + }); + } + + redirect(id: string, type: RecentActivityType) { + switch (type) { + case RecentActivityType.Project: { + this.router.navigate(['projects/edit/' + id]); + return; + } + case RecentActivityType.Dataset: { + this.router.navigate(['datasets/edit/' + id]); + return; + } + case RecentActivityType.Dmp: { + this.router.navigate(['plans/edit/' + id]); + return; + } + default: throw new Error('Unsupported Activity Type '); + } + + } +} diff --git a/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-editor/dataset-editor.component.html b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-editor/dataset-editor.component.html new file mode 100644 index 000000000..685779a10 --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-editor/dataset-editor.component.html @@ -0,0 +1,17 @@ +
+ + + {{baseErrorModel.label}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + {{baseErrorModel.uri}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + {{errorModel.description}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
diff --git a/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-editor/dataset-editor.component.scss b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-editor/dataset-editor.component.scss new file mode 100644 index 000000000..4d7d33f4d --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-editor/dataset-editor.component.scss @@ -0,0 +1 @@ +.dataset-editor {} diff --git a/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-editor/dataset-editor.component.ts b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-editor/dataset-editor.component.ts new file mode 100644 index 000000000..fbe61f231 --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-editor/dataset-editor.component.ts @@ -0,0 +1,23 @@ +import { Component, Input } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { Router } from '@angular/router'; +import { BaseComponent } from '../../../../core/common/base/base.component'; + +@Component({ + selector: 'app-dataset-editor-component', + templateUrl: 'dataset-editor.component.html', + styleUrls: ['./dataset-editor.component.scss'] +}) +export class DatasetEditorComponent extends BaseComponent { + + @Input() formGroup: FormGroup = null; + + constructor( + private router: Router, + ) { super(); } + + + public cancel(): void { + this.router.navigate(['/datasets']); + } +} diff --git a/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard-editor.model.ts b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard-editor.model.ts new file mode 100644 index 000000000..c61db713c --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard-editor.model.ts @@ -0,0 +1,325 @@ +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; +import { BackendErrorValidator } from "../../../common/forms/validation/custom-validator"; +import { ValidationErrorModel } from "../../../common/forms/validation/error-model/validation-error-model"; +import { ValidationContext } from "../../../common/forms/validation/validation-context"; +import { ExternalDatasetType } from "../../../core/common/enum/external-dataset-type"; +import { DataRepositoryModel } from "../../../core/model/data-repository/data-repository"; +import { DatasetProfileModel } from "../../../core/model/dataset/dataset-profile"; +import { DatasetWizardModel } from "../../../core/model/dataset/dataset-wizard"; +import { DmpModel } from "../../../core/model/dmp/dmp"; +import { ExternalDatasetModel } from "../../../core/model/external-dataset/external-dataset"; +import { RegistryModel } from "../../../core/model/registry/registry"; +import { ServiceModel } from "../../../core/model/service/service"; +import { TagModel } from "../../../core/model/tag/tag"; +import { DatasetDescriptionFormEditorModel } from "../../misc/dataset-description-form/dataset-description-form.model"; + +export class DatasetWizardEditorModel { + public id: string; + public label: string; + public profile: DatasetProfileModel; + public uri: String; + public status: number; + public description: String; + public services: ExternalServiceEditorModel[] = []; + public registries: ExternalRegistryEditorModel[] = []; + public dataRepositories: ExternalDataRepositoryEditorModel[] = []; + public tags: TagModel[] = []; + public externalDatasets: ExternalDatasetEditorModel[] = []; + public dmp: DmpModel; + public datasetProfileDefinition: DatasetDescriptionFormEditorModel; + public errorModel: ValidationErrorModel = new ValidationErrorModel(); + + fromModel(item: DatasetWizardModel): DatasetWizardEditorModel { + this.id = item.id; + this.label = item.label; + this.profile = item.profile; + this.uri = item.uri; + this.status = item.status; + this.description = item.description; + if (item.services) { this.services = item.services.map(x => new ExternalServiceEditorModel().fromModel(x)); } + if (item.registries) { this.registries = item.registries.map(x => new ExternalRegistryEditorModel().fromModel(x)); } + if (item.dataRepositories) { this.dataRepositories = item.dataRepositories.map(x => new ExternalDataRepositoryEditorModel().fromModel(x)); } + if (item.externalDatasets) { this.externalDatasets = item.externalDatasets.map(x => new ExternalDatasetEditorModel().fromModel(x)); } + this.dmp = item.dmp; + this.profile = item.profile; + if (item.datasetProfileDefinition) { this.datasetProfileDefinition = new DatasetDescriptionFormEditorModel().fromModel(item.datasetProfileDefinition); } + this.tags = item.tags; + return this; + } + + buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { + if (context == null) { context = this.createValidationContext(); } + const formBuilder = new FormBuilder(); + const formGroup = formBuilder.group({ + id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators], + label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators], + uri: [{ value: this.uri, disabled: disabled }, context.getValidation('uri').validators], + status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators], + description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators], + dmp: [{ value: this.dmp, disabled: disabled }, context.getValidation('dmp').validators], + //externalDatasets: [{ value: this.externalDatasets, disabled: disabled }, context.getValidation('externalDatasets').validators], + tags: [{ value: this.tags, disabled: disabled }, context.getValidation('tags').validators], + //registries: [{ value: this.registries, disabled: disabled }, context.getValidation('registries').validators], + //dataRepositories: [{ value: this.dataRepositories, disabled: disabled }, context.getValidation('dataRepositories').validators], + //services: [{ value: this.services, disabled: disabled }, context.getValidation('services').validators], + profile: [{ value: this.profile, disabled: disabled }, context.getValidation('profile').validators], + }); + + const externalDatasetsFormArray = new Array(); + //if (this.externalDatasets && this.externalDatasets.length > 0) { + this.externalDatasets.forEach(item => { + externalDatasetsFormArray.push(item.buildForm(context.getValidation('externalDatasets').descendantValidations, disabled)); + }); + // } else { + // //externalDatasetsFormArray.push(new ExternalDatasetModel().buildForm(context.getValidation('externalDatasets').descendantValidations, disabled)); + // } + formGroup.addControl('externalDatasets', formBuilder.array(externalDatasetsFormArray)); + + // const tagsFormArray = new Array(); + // if (this.tags && this.tags.length > 0) { + // this.tags.forEach(item => { + // tagsFormArray.push(item.buildForm(context.getValidation('tags').descendantValidations, disabled)); + // }); + // } else { + // //externalDatasetsFormArray.push(new ExternalDatasetModel().buildForm(context.getValidation('externalDatasets').descendantValidations, disabled)); + // } + // formGroup.addControl('tags', formBuilder.array(tagsFormArray)); + + const registriesFormArray = new Array(); + //if (this.registries && this.registries.length > 0) { + this.registries.forEach(item => { + registriesFormArray.push(item.buildForm(context.getValidation('registries').descendantValidations, disabled)); + }); + // } else { + // //externalDatasetsFormArray.push(new ExternalDatasetModel().buildForm(context.getValidation('externalDatasets').descendantValidations, disabled)); + // } + formGroup.addControl('registries', formBuilder.array(registriesFormArray)); + + const dataRepositoriesFormArray = new Array(); + //if (this.dataRepositories && this.dataRepositories.length > 0) { + this.dataRepositories.forEach(item => { + dataRepositoriesFormArray.push(item.buildForm(context.getValidation('dataRepositories').descendantValidations, disabled)); + }); + // } else { + // //externalDatasetsFormArray.push(new ExternalDatasetModel().buildForm(context.getValidation('externalDatasets').descendantValidations, disabled)); + // } + formGroup.addControl('dataRepositories', formBuilder.array(dataRepositoriesFormArray)); + + const servicesFormArray = new Array(); + // if (this.services && this.services.length > 0) { + this.services.forEach(item => { + servicesFormArray.push(item.buildForm(context.getValidation('services').descendantValidations, disabled)); + }); + // } else { + // //externalDatasetsFormArray.push(new ExternalDatasetModel().buildForm(context.getValidation('externalDatasets').descendantValidations, disabled)); + // } + formGroup.addControl('services', formBuilder.array(servicesFormArray)); + + if (this.datasetProfileDefinition) { formGroup.addControl('datasetProfileDefinition', this.datasetProfileDefinition.buildForm()); } + // formGroup.addControl('profile', this.profile.buildForm()); + return formGroup; + } + + createValidationContext(): ValidationContext { + const baseContext: ValidationContext = new ValidationContext(); + baseContext.validation.push({ key: 'id', validators: [BackendErrorValidator(this.errorModel, 'id')] }); + baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'label')] }); + baseContext.validation.push({ key: 'profile', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'profile')] }); + baseContext.validation.push({ key: 'uri', validators: [BackendErrorValidator(this.errorModel, 'uri')] }); + baseContext.validation.push({ key: 'status', validators: [BackendErrorValidator(this.errorModel, 'status')] }); + baseContext.validation.push({ key: 'description', validators: [BackendErrorValidator(this.errorModel, 'description')] }); + baseContext.validation.push({ key: 'services', validators: [BackendErrorValidator(this.errorModel, 'services')] }); + baseContext.validation.push({ key: 'registries', validators: [BackendErrorValidator(this.errorModel, 'registries')] }); + baseContext.validation.push({ key: 'dataRepositories', validators: [BackendErrorValidator(this.errorModel, 'dataRepositories')] }); + baseContext.validation.push({ key: 'externalDatasets', validators: [BackendErrorValidator(this.errorModel, 'externalDatasets')] }); + baseContext.validation.push({ key: 'dmp', validators: [BackendErrorValidator(this.errorModel, 'dmp')] }); //TODO + baseContext.validation.push({ key: 'datasetProfileDefinition', validators: [BackendErrorValidator(this.errorModel, 'datasetProfileDefinition')] }); //TODO + baseContext.validation.push({ key: 'tags', validators: [BackendErrorValidator(this.errorModel, 'datasetProfileDefinition')] }); //TODO + + return baseContext; + } +} + +export class ExternalServiceEditorModel { + public id: String; + public abbreviation: String; + public definition: String; + public uri: String; + public label: String; + public reference: String; + + constructor(id?: String, abbreviation?: String, definition?: String, uri?: String, label?: String, reference?: String) { + this.id = id; + this.abbreviation = abbreviation; + this.definition = definition; + this.uri = uri; + this.label = label; + this.reference = reference; + } + + fromModel(item: ServiceModel): ExternalServiceEditorModel { + this.id = item.id; + this.abbreviation = item.abbreviation; + this.definition = item.definition; + this.uri = item.uri; + this.label = item.label; + this.reference = item.reference; + return this; + } + + buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { + return new FormBuilder().group({ + id: [this.id], + abbreviation: [this.abbreviation], + label: [this.label], + reference: [this.reference], + uri: [this.uri], + definition: [this.definition] + }); + } +} + +export class ExternalRegistryEditorModel { + public abbreviation: String; + public definition: String; + public id: String; + public label: String; + public reference: String; + public uri: String; + + constructor(abbreviation?: String, definition?: String, id?: String, label?: String, reference?: String, uri?: String) { + this.abbreviation = abbreviation; + this.definition = definition; + this.id = id; + this.label = label; + this.reference = reference; + this.uri = uri; + } + + fromModel(item: RegistryModel): ExternalRegistryEditorModel { + this.abbreviation = item.abbreviation; + this.definition = item.definition; + this.id = item.id; + this.label = item.label; + this.reference = item.reference; + this.uri = item.uri; + + return this; + } + + buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { + return new FormBuilder().group({ + id: [this.id], + abbreviation: [this.abbreviation], + label: [this.label], + reference: [this.reference], + uri: [this.uri], + definition: [this.definition] + }); + } +} + +export class ExternalDatasetEditorModel { + + public abbreviation: String; + public id: String; + public label: String; + public reference: String; + public type: ExternalDatasetType; + public info: String; + public errorModel: ValidationErrorModel = new ValidationErrorModel(); + + constructor(id?: string, abbreviation?: string, label?: string, reference?: string, info?: string, type?: ExternalDatasetType) { + this.id = id; + this.label = label; + this.abbreviation = abbreviation; + this.reference = reference; + this.info = info; + this.type = type; + } + + fromModel(item: ExternalDatasetModel): ExternalDatasetEditorModel { + this.abbreviation = item.abbreviation; + this.id = item.id; + this.label = item.label; + this.reference = item.reference; + this.type = item.type; + this.info = item.info; + return this; + } + + buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { + return new FormBuilder().group({ + id: [this.id], + abbreviation: [this.abbreviation], + label: [this.label], + reference: [this.reference], + type: [this.type], + info: [this.info] + }); + } +} + +export class ExternalDataRepositoryEditorModel { + public id: string; + public label: string; + public abbreviation: string; + public uri: string; + public reference: string; + public info: string; + public created: Date; + public modified: Date; + + constructor(id?: string, label?: string, abbreviation?: string, uri?: string, reference?: string) { + this.id = id; + this.label = label; + this.abbreviation = abbreviation; + this.uri = uri; + this.reference = reference; + } + + fromModel(item: DataRepositoryModel): ExternalDataRepositoryEditorModel { + this.id = item.id; + this.label = item.label; + this.abbreviation = item.abbreviation; + this.uri = item.uri; + this.info = item.info; + this.reference = item.pid; + return this; + } + + buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { + return new FormBuilder().group({ + id: [this.id], + label: [this.label], + abbreviation: [this.abbreviation], + uri: [this.uri], + info: [this.info], + reference: [this.reference] + }); + } +} + +// export class TagModel implements Serializable { + +// public id: string; +// public name: string; + +// constructor(id?: string, name?: string) { +// this.id = id; +// this.name = name; +// } + +// fromJSONObject(item: any): TagModel { +// this.id = item.id; +// this.name = item.name; +// return this; +// } + +// buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { +// return new FormBuilder().group({ +// id: [this.id], +// name: [this.name] +// }); +// } +// } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.html b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.html new file mode 100644 index 000000000..836b4bbb9 --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.html @@ -0,0 +1,92 @@ +
+

{{ 'DATASET-WIZARD.TITLE.NEW' | translate }}

+
+
+

{{datasetWizardModel?.label}} {{ 'GENERAL.NAMES.DATASET' | translate }}

+

- {{ 'GENERAL.STATUSES.EDIT' | translate }}

+

- {{'GENERAL.STATUSES.FINALISED' | translate }}

+
+
+ + +
+
+ + + + + +
+
+
+ + + {{'DATASET-WIZARD.FIRST-STEP.TITLE' | translate}} +
+
+ + + + + + + + {{profile.label}} + + + {{baseErrorModel['Criteria.status']}} + + +
+
+
+
+
+
+
+
+
+ + {{'DATASET-WIZARD.SECOND-STEP.TITLE' | translate}} +
+
+ +
+
+
+
+
+
+
+
+
+ + {{'DATASET-WIZARD.THIRD-STEP.TITLE' | translate}} +
+ +
+
+
+
+
+
+
+ +
+
+
diff --git a/dmp-frontend/src/app/datasets/dataset-wizard/dataset-wizard.component.scss b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.scss similarity index 100% rename from dmp-frontend/src/app/datasets/dataset-wizard/dataset-wizard.component.scss rename to dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.scss diff --git a/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.ts b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.ts new file mode 100644 index 000000000..fe8dc621e --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.ts @@ -0,0 +1,411 @@ +import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { MatDialog, MatSnackBar, MatStepper } from '@angular/material'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import * as FileSaver from 'file-saver'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { ValidationErrorModel } from '../../../common/forms/validation/error-model/validation-error-model'; +import { BaseComponent } from '../../../core/common/base/base.component'; +import { DatasetStatus } from '../../../core/common/enum/dataset-status'; +import { DatasetProfileModel } from '../../../core/model/dataset/dataset-profile'; +import { DmpModel } from '../../../core/model/dmp/dmp'; +import { DmpListingModel } from '../../../core/model/dmp/dmp-listing'; +import { DatasetProfileCriteria } from '../../../core/query/dataset-profile/dataset-profile-criteria'; +import { DmpCriteria } from '../../../core/query/dmp/dmp-criteria'; +import { RequestItem } from '../../../core/query/request-item'; +import { DatasetWizardService } from '../../../core/services/dataset-wizard/dataset-wizard.service'; +import { DmpService } from '../../../core/services/dmp/dmp.service'; +import { ExternalSourcesConfigurationService } from '../../../core/services/external-sources/external-sources-configuration.service'; +import { ExternalSourcesService } from '../../../core/services/external-sources/external-sources.service'; +import { SingleAutoCompleteConfiguration } from '../../../library/auto-complete/single/single-auto-complete-configuration'; +import { SnackBarNotificationComponent } from '../../../library/notification/snack-bar/snack-bar-notification.component'; +import { BreadcrumbItem } from '../../misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '../../misc/breadcrumb/definition/IBreadCrumbComponent'; +import { DatasetDescriptionFormEditorModel } from '../../misc/dataset-description-form/dataset-description-form.model'; +import { DatasetWizardEditorModel } from './dataset-wizard-editor.model'; + +@Component({ + selector: 'app-dataset-wizard-component', + templateUrl: 'dataset-wizard.component.html', + styleUrls: ['./dataset-wizard.component.scss'] +}) +export class DatasetWizardComponent extends BaseComponent implements OnInit, AfterViewInit, IBreadCrumbComponent { + + breadCrumbs: Observable; + viewOnly = false; + @ViewChild('stepper') stepper: MatStepper; + editMode = false; + + DatasetStatus = DatasetStatus; + dmpAutoCompleteConfiguration: SingleAutoCompleteConfiguration; + + datasetWizardModel: DatasetWizardEditorModel; + isNew = true; + formGroup: FormGroup; + datasetProfileDefinitionModel: DatasetDescriptionFormEditorModel; + + availableProfiles: DatasetProfileModel[] = []; + itemId: string; + isLinear = false; + firstStepFormGroup: FormGroup; + secondFormGroup: FormGroup; + + + + constructor( + private datasetWizardService: DatasetWizardService, + private route: ActivatedRoute, + public snackBar: MatSnackBar, + public router: Router, + public language: TranslateService, + public externalSourcesService: ExternalSourcesService, + public dmpService: DmpService, + public dialog: MatDialog, + public externalSourcesConfigurationService: ExternalSourcesConfigurationService + ) { + super(); + } + + + ngOnInit() { + this.route + .data + .pipe(takeUntil(this._destroyed)) + .subscribe(v => this.viewOnly = v['public']); + + const dmpRequestItem: RequestItem = new RequestItem(); + dmpRequestItem.criteria = new DmpCriteria(); + + // const externalDatasetRequestItem: RequestItem = new RequestItem(); + // externalDatasetRequestItem.criteria = new ExternalDatasetCriteria(); + // this.externalDatasetAutoCompleteConfiguration = new AutoCompleteConfiguration(this.externalSourcesService.searchDatasetSExternalDatasetservice.bind(this.externalSourcesService), + // externalDatasetRequestItem, new BehaviorSubject(false)); + + // const registriesRequestItem: RequestItem = new RequestItem(); + // registriesRequestItem.criteria = new RegistryCriteria(); + // this.registriesAutoCompleteConfiguration = new AutoCompleteConfiguration(this.externalSourcesService.searchDatasetRegistry.bind(this.externalSourcesService), + // registriesRequestItem, new BehaviorSubject(false)); + + // const dataRepositoriesRequestItem: RequestItem = new RequestItem(); + // dataRepositoriesRequestItem.criteria = new DataRepositoryCriteria(); + // this.dataRepositoriesAutoCompleteConfiguration = new AutoCompleteConfiguration(this.externalSourcesService.searchDatasetRepository.bind(this.externalSourcesService), + // dataRepositoriesRequestItem, new BehaviorSubject(false)); + + // const servicesRequestItem: RequestItem = new RequestItem(); + // servicesRequestItem.criteria = new ServiceCriteria(); + // this.servicesAutoCompleteConfiguration = new AutoCompleteConfiguration(this.externalSourcesService.searchDatasetService.bind(this.externalSourcesService), + // servicesRequestItem, new BehaviorSubject(false)); + + // const tagsRequestItem: RequestItem = new RequestItem(); + // tagsRequestItem.criteria = new TagCriteria(); + // this.tagsAutoCompleteConfiguration = new AutoCompleteConfiguration(this.externalSourcesService.searchDatasetTags.bind(this.externalSourcesService), + // tagsRequestItem, new BehaviorSubject(false)); + + this.dmpAutoCompleteConfiguration = { + filterFn: this.searchDmp.bind(this), + initialItems: (extraData) => this.searchDmp(''), + displayFn: (item) => item['label'], + titleFn: (item) => item['label'], + loadDataOnStart: true + }; + + const params = this.route.snapshot.params; + this.itemId = params['id']; + const dmpId = params['dmpId']; + if (this.itemId != null) { + this.isNew = false; + this.datasetWizardService.getSingle(this.itemId) + .pipe(takeUntil(this._destroyed)) + .subscribe(data => { + this.datasetWizardModel = new DatasetWizardEditorModel().fromModel(data); + this.breadCrumbs = Observable.of([ + { + parentComponentName: null, + label: 'Datasets', + url: '/datasets', + notFoundResolver: [ + { + parentComponentName: null, + label: this.datasetWizardModel.dmp.project.label, + url: '/projects/edit/' + this.datasetWizardModel.dmp.project.id + }, + { + parentComponentName: null, + label: this.datasetWizardModel.dmp.label, + url: '/plans/edit/' + this.datasetWizardModel.dmp.id, + }, + ] + }]); + this.formGroup = this.datasetWizardModel.buildForm(); + this.editMode = this.datasetWizardModel.status === DatasetStatus.Draft; + if (this.datasetWizardModel.status === 1) { + this.formGroup.disable(); + this.viewOnly = true; + } + if (this.viewOnly) { this.formGroup.disable(); } + this.loadDatasetProfiles(); + }); + } else if (dmpId != null) { + this.isNew = true; + this.dmpService.getSingle(dmpId).map(data => data as DmpModel) + .pipe(takeUntil(this._destroyed)) + .subscribe(data => { + this.datasetWizardModel = new DatasetWizardEditorModel(); + setTimeout(() => { + this.datasetWizardModel.dmp = data; + this.formGroup = this.datasetWizardModel.buildForm(); + this.editMode = this.datasetWizardModel.status === DatasetStatus.Draft; + if (this.datasetWizardModel.status === 1) { + this.formGroup.disable(); + this.viewOnly = true; + } + this.loadDatasetProfiles(); + this.breadCrumbs = Observable.of([ + { + parentComponentName: null, + label: 'Datasets', + url: '/datasets', + notFoundResolver: [ + { + parentComponentName: null, + label: this.datasetWizardModel.dmp.project.label, + url: '/projects/edit/' + this.datasetWizardModel.dmp.project.id + }, + { + parentComponentName: null, + label: this.datasetWizardModel.dmp.label, + url: '/plans/edit/' + this.datasetWizardModel.dmp.id, + }] + }]); + }); + }); + } else { + this.datasetWizardModel = new DatasetWizardEditorModel(); + this.formGroup = this.datasetWizardModel.buildForm(); + this.editMode = this.datasetWizardModel.status === DatasetStatus.Draft; + if (this.datasetWizardModel.status === 1) { + this.formGroup.disable(); + this.viewOnly = true; + } + if (this.viewOnly) { this.formGroup.disable(); } + this.formGroup.get('dmp').valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => { + this.loadDatasetProfiles(); + }); + } + } + + ngAfterViewInit() { + this.route.params + .pipe(takeUntil(this._destroyed)) + .subscribe((params: Params) => { + const itemId = params['id']; + if (itemId != null) { this.stepper.selectedIndex = 2; } + }); + } + + searchDmp(query: string): Observable { + const dmpRequestItem: RequestItem = new RequestItem(); + dmpRequestItem.criteria = new DmpCriteria(); + dmpRequestItem.criteria.like = query; + return this.dmpService.get(dmpRequestItem); + } + + loadDatasetProfiles() { + const datasetProfileRequestItem: RequestItem = new RequestItem(); + datasetProfileRequestItem.criteria = new DatasetProfileCriteria(); + datasetProfileRequestItem.criteria.id = this.formGroup.get('dmp').value.id; + if (datasetProfileRequestItem.criteria.id) { + this.datasetWizardService.getAvailableProfiles(datasetProfileRequestItem) + .pipe(takeUntil(this._destroyed)) + .subscribe(items => { + this.availableProfiles = items; + }); + } + } + + public cancel(): void { + //this.router.navigate(['/plans']); + } + + getDefinition() { + if (this.formGroup.invalid) { this.stepper.selectedIndex = 0; return; } + if (this.isNew) { + this.datasetWizardService.getDefinition(this.formGroup.get('profile').value) + .pipe(takeUntil(this._destroyed)) + .subscribe(item => { + this.datasetWizardModel.datasetProfileDefinition = new DatasetDescriptionFormEditorModel().fromModel(item); + this.datasetProfileDefinitionModel = this.datasetWizardModel.datasetProfileDefinition; + this.formGroup.addControl('datasetProfileDefinition', this.datasetProfileDefinitionModel.buildForm()); + }); + } + } + + + formSubmit(): void { + if (!this.isFormValid()) { return; } + this.onSubmit(); + } + + public isFormValid() { + return this.formGroup.valid; + } + + onSubmit(): void { + this.datasetWizardService.createDataset(this.formGroup.value) + .pipe(takeUntil(this._destroyed)) + .subscribe( + complete => { + this.datasetWizardService.getSingle(complete.id) + .pipe(takeUntil(this._destroyed)) + .subscribe( + result => { + this.datasetWizardModel = new DatasetWizardEditorModel().fromModel(result); + } + ); + this.onCallbackSuccess(); + }, + error => this.onCallbackError(error) + ); + } + + submit() { + this.datasetWizardService.createDataset(this.formGroup.value) + .pipe(takeUntil(this._destroyed)) + .subscribe(data => { + this.router.navigateByUrl('/datasets/dmp/' + this.formGroup.get('dmp').value.id); + }); + } + + + save() { + if (!this.isFormValid()) { return; } + this.formGroup.get('status').setValue('0'); + this.submit(); + } + + saveFinalize() { + if (!this.isFormValid()) { return; } + this.formGroup.get('status').setValue('1'); + this.submit(); + } + + onCallbackSuccess(): void { + this.snackBar.openFromComponent(SnackBarNotificationComponent, { + data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, + duration: 3000, + }); + } + + onCallbackError(error: any) { + this.setErrorModel(error.error); + } + + public setErrorModel(errorModel: ValidationErrorModel) { + Object.keys(errorModel).forEach(item => { + (this.datasetWizardModel.errorModel)[item] = (errorModel)[item]; + }); + } + + downloadPDF(): void { + this.datasetWizardService.downloadPDF(this.itemId) + .pipe(takeUntil(this._destroyed)) + .subscribe(response => { + const blob = new Blob([response.body], { type: 'application/pdf' }); + const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition')); + + FileSaver.saveAs(blob, filename); + }); + } + + downloadXML(): void { + this.datasetWizardService.downloadXML(this.itemId) + .pipe(takeUntil(this._destroyed)) + .subscribe(response => { + const blob = new Blob([response.body], { type: 'application/xml' }); + const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition')); + + FileSaver.saveAs(blob, filename); + }); + } + + getFilenameFromContentDispositionHeader(header: string): string { + const regex: RegExp = new RegExp(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/g); + + const matches = header.match(regex); + let filename: string; + for (let i = 0; i < matches.length; i++) { + const match = matches[i]; + if (match.includes('filename="')) { + filename = match.substring(10, match.length - 1); + break; + } else if (match.includes('filename=')) { + filename = match.substring(9); + break; + } + } + return filename; + } + + public redirectToProject() { + this.router.navigate(['projects/edit/' + this.datasetWizardModel.dmp.project.id]); + } + + public redirectToDmp() { + this.router.navigate(['plans/edit/' + this.datasetWizardModel.dmp.id]); + } + + public enableForm() { + if (this.formGroup.get('status').value !== DatasetStatus.Finalized) { + this.editMode = true; + this.viewOnly = false; + this.formGroup.enable(); + } else { + this.datasetWizardService.unlock(this.formGroup.get('id').value) + .pipe(takeUntil(this._destroyed)) + .subscribe(x => { + this.editMode = true; + this.viewOnly = false; + this.datasetWizardModel.status = DatasetStatus.Draft; + this.formGroup.get('status').patchValue(DatasetStatus.Draft); + this.formGroup.enable(); + }); + } + } + + public disableForm() { + this.editMode = false; + this.viewOnly = true; + this.formGroup.disable(); + } + + isActiveStep(index: number) { + return this.stepper.selectedIndex === index; + } + + openConfirm(dmpLabel, id): void { + // this._dialogService.openConfirm({ + // message: 'Are you sure you want to delete the "' + dmpLabel + '"', + // disableClose: true || false, + // viewContainerRef: this._viewContainerRef, + // title: 'Confirm', + // cancelButton: 'No', + // acceptButton: 'Yes' + // }).afterClosed() + // .pipe(takeUntil(this._destroyed)) + // .subscribe((accept: boolean) => { + // if (accept) { + // this.datasetWizardService.delete(id) + // .pipe(takeUntil(this._destroyed)) + // .subscribe(() => { + // this.router.navigate(['/datasets']); + // }); + // } else { + // // DO SOMETHING ELSE + // } + // }); + } +} diff --git a/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/dataset-external-references-editor.component.html b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/dataset-external-references-editor.component.html new file mode 100644 index 000000000..a0f0ebb21 --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/dataset-external-references-editor.component.html @@ -0,0 +1,162 @@ +
+ +
+
+

{{'DATASET-EDITOR.FIELDS.DATAREPOSITORIES' | translate}}

+
+
+
+
+
+ + + +
+ + {{i+1}}) {{suggestion.get('label').value}} + +
+ + + +
+
+ +
+
+
+
+ +
+
+

{{'DATASET-EDITOR.FIELDS.EXTERNAL-DATASETS' | translate}}

+
+
+
+
+
+ + + + +
+
+

+ {{i+1}}) {{suggestion.get('label').value}} +

+
+
+ + + +
+ +
+ + + {{'TYPES.EXTERNAL-DATASET-TYPE.SOURCE' | translate}} + {{'TYPES.EXTERNAL-DATASET-TYPE.OUTPUT' | translate}} + + +
+
+ +
+
+
+
+ + +
+
+

{{'DATASET-EDITOR.FIELDS.REGISTRIES' | translate}}

+
+
+
+
+
+ + + + +
+
+

+ {{i+1}}) {{suggestion.get('label').value}} +

+
+
+ +
+
+
+
+ + +
+
+

{{'DATASET-EDITOR.FIELDS.SERVICES' | translate}}

+
+
+ +
+
+
+ + + + +
+
+

+ {{i+1}}) {{suggestion.get('label').value}} +

+
+
+ +
+
+
+
+ + +
+
+

{{'DATASET-EDITOR.FIELDS.TAGS' | translate}}

+
+
+ + + + +
+
+

+ {{i+1}}) {{suggestion.get('name').value}} +

+
+
+ +
+
+
+
+
diff --git a/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/dataset-external-references-editor.component.scss b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/dataset-external-references-editor.component.scss new file mode 100644 index 000000000..7e0294573 --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/dataset-external-references-editor.component.scss @@ -0,0 +1 @@ +.dataset-external-references-editor {} diff --git a/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/dataset-external-references-editor.component.ts b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/dataset-external-references-editor.component.ts new file mode 100644 index 000000000..01685947f --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/dataset-external-references-editor.component.ts @@ -0,0 +1,233 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormArray, FormGroup } from '@angular/forms'; +import { MatDialog } from '@angular/material'; +import { Router } from '@angular/router'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../core/common/base/base.component'; +import { ExternalSourceItemModel } from '../../../../core/model/external-sources/external-source-item'; +import { ExternalSourcesConfiguration } from '../../../../core/model/external-sources/external-sources-configuration'; +import { DataRepositoryCriteria } from '../../../../core/query/data-repository/data-repository-criteria'; +import { ExternalDatasetCriteria } from '../../../../core/query/external-dataset/external-dataset-criteria'; +import { RegistryCriteria } from '../../../../core/query/registry/registry-criteria'; +import { ServiceCriteria } from '../../../../core/query/service/service-criteria'; +import { TagCriteria } from '../../../../core/query/tag/tag-criteria'; +import { ExternalSourcesConfigurationService } from '../../../../core/services/external-sources/external-sources-configuration.service'; +import { ExternalSourcesService } from '../../../../core/services/external-sources/external-sources.service'; +import { SingleAutoCompleteConfiguration } from '../../../../library/auto-complete/single/single-auto-complete-configuration'; +import { RequestItem } from '../../../../core/query/request-item'; +import { ExternalDataRepositoryEditorModel, ExternalDatasetEditorModel, ExternalRegistryEditorModel, ExternalServiceEditorModel } from '../dataset-wizard-editor.model'; +import { DatasetExternalDataRepositoryDialogEditorComponent } from './editors/data-repository/dataset-external-data-repository-dialog-editor.component'; +import { DatasetExternalDatasetDialogEditorComponent } from './editors/external-dataset/dataset-external-dataset-dialog-editor.component'; +import { DatasetExternalRegistryDialogEditorComponent } from './editors/registry/dataset-external-registry-dialog-editor.component'; +import { DatasetExternalServiceDialogEditorComponent } from './editors/service/dataset-external-service-dialog-editor.component'; + +@Component({ + selector: 'app-dataset-external-references-editor-component', + templateUrl: 'dataset-external-references-editor.component.html', + styleUrls: ['./dataset-external-references-editor.component.scss'] +}) +export class DatasetExternalReferencesEditorComponent extends BaseComponent implements OnInit { + + @Input() formGroup: FormGroup = null; + + externalDatasetAutoCompleteConfiguration: SingleAutoCompleteConfiguration; + registriesAutoCompleteConfiguration: SingleAutoCompleteConfiguration; + dataRepositoriesAutoCompleteConfiguration: SingleAutoCompleteConfiguration; + servicesAutoCompleteConfiguration: SingleAutoCompleteConfiguration; + tagsAutoCompleteConfiguration: SingleAutoCompleteConfiguration; + + externalSourcesConfiguration: ExternalSourcesConfiguration; + + // new AutoCompleteConfiguration(this.externalSourcesService.searchDatasetRepository.bind(this.externalSourcesService), + + constructor( + private dialog: MatDialog, + private router: Router, + private externalSourcesService: ExternalSourcesService, + private externalSourcesConfigurationService: ExternalSourcesConfigurationService + ) { super(); } + + ngOnInit() { + + this.externalSourcesConfigurationService.getExternalSourcesConfiguration() + .pipe(takeUntil(this._destroyed)) + .subscribe(result => { + this.externalSourcesConfiguration = result; + this.externalSourcesConfiguration.dataRepositories.push({ key: '', label: 'All' }); + this.externalSourcesConfiguration.externalDatasets.push({ key: '', label: 'All' }); + this.externalSourcesConfiguration.registries.push({ key: '', label: 'All' }); + this.externalSourcesConfiguration.services.push({ key: '', label: 'All' }); + this.externalSourcesConfiguration.tags.push({ key: '', label: 'All' }); + }); + + this.externalDatasetAutoCompleteConfiguration = { + filterFn: this.searchDatasetExternalDatasets.bind(this), + initialItems: (type) => this.searchDatasetExternalDatasets('', type),//.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1), + displayFn: (item) => item ? item.label : null, + titleFn: (item) => item ? item.label : null, + subtitleFn: (item) => item ? item.tag : null, + }; + + this.registriesAutoCompleteConfiguration = { + filterFn: this.searchDatasetExternalRegistries.bind(this), + initialItems: (type) => this.searchDatasetExternalRegistries('', type), + displayFn: (item) => item ? item.label : null, + titleFn: (item) => item ? item.label : null, + subtitleFn: (item) => item ? item.tag : null + }; + + this.dataRepositoriesAutoCompleteConfiguration = { + filterFn: this.searchDatasetExternalDataRepositories.bind(this), + initialItems: (type) => this.searchDatasetExternalDataRepositories('', type), + displayFn: (item) => item ? item.label : null, + titleFn: (item) => item ? item.label : null, + subtitleFn: (item) => item ? item.tag : null + }; + + this.servicesAutoCompleteConfiguration = { + filterFn: this.searchDatasetExternalServices.bind(this), + initialItems: (type) => this.searchDatasetExternalServices('', type), + displayFn: (item) => item ? item.label : null, + titleFn: (item) => item ? item.label : null, + subtitleFn: (item) => item ? item.tag : null + }; + + this.tagsAutoCompleteConfiguration = { + filterFn: this.searchDatasetTags.bind(this), + initialItems: (type) => this.searchDatasetTags('', type), + displayFn: (item) => item ? item.name : null, + titleFn: (item) => item ? item.name : null + }; + } + + public cancel(): void { + this.router.navigate(['/datasets']); + } + + externalDatasetsOnItemChange(event) { + const externalDatasetModel = new ExternalDatasetEditorModel(event.id, event.abbreviation, event.label, event.reference); + (this.formGroup.get('externalDatasets')).push(externalDatasetModel.buildForm()); + } + + registriesOnItemChange(event) { + const registryModel = new ExternalRegistryEditorModel(event.abbreviation, event.definition, event.id, event.label, event.reference, event.uri); + (this.formGroup.get('registries')).push(registryModel.buildForm()); + } + + servicesOnItemChange(event) { + const serviceModel = new ExternalServiceEditorModel(event.abbreviation, event.definition, event.id, event.label, event.reference, event.uri); + (this.formGroup.get('services')).push(serviceModel.buildForm()); + } + + tagsOnItemChange(event) { + // const serviceModel = new TagModel(event.id, event.name); + // (this.formGroup.get('tags')).push(serviceModel.buildForm()); + } + + + dataRepositoriesOnItemChange(event) { + const dataRepositoryModel = new ExternalDataRepositoryEditorModel(event.id, event.name, event.abbreviation, event.uri, event.pid); + (this.formGroup.get('dataRepositories')).push(dataRepositoryModel.buildForm()); + } + + addDataRepository() { + const dialogRef = this.dialog.open(DatasetExternalDataRepositoryDialogEditorComponent, { + data: { + + } + }); + dialogRef.afterClosed() + .pipe(takeUntil(this._destroyed)) + .subscribe(result => { + if (!result) { return; } + const dataRepositoryModel = new ExternalDataRepositoryEditorModel(result.id, result.label, result.pid, result.uri, result.reference); + (this.formGroup.get('dataRepositories')).push(dataRepositoryModel.buildForm()); + }); + } + + addRegistry() { + const dialogRef = this.dialog.open(DatasetExternalRegistryDialogEditorComponent, { + data: { + + } + }); + dialogRef.afterClosed() + .pipe(takeUntil(this._destroyed)) + .subscribe(result => { + if (!result) { return; } + const registryModel = new ExternalRegistryEditorModel(result.abbreviation, result.definition, result.id, result.label, result.reference, result.uri); + (this.formGroup.get('registries')).push(registryModel.buildForm()); + }); + } + + addExternalDataset() { + const dialogRef = this.dialog.open(DatasetExternalDatasetDialogEditorComponent, { + data: { + + } + }); + dialogRef.afterClosed() + .pipe(takeUntil(this._destroyed)) + .subscribe(result => { + if (!result) { return; } + const externalDatasetModel = new ExternalDatasetEditorModel(result.id, result.abbreviation, result.label, result.reference); + (this.formGroup.get('externalDatasets')).push(externalDatasetModel.buildForm()); + }); + } + + addService() { + const dialogRef = this.dialog.open(DatasetExternalServiceDialogEditorComponent, { + data: { + + } + }); + dialogRef.afterClosed() + .pipe(takeUntil(this._destroyed)) + .subscribe(result => { + if (!result) { return; } + const serviceModel = new ExternalServiceEditorModel(result.id, result.abbreviation, result.definition, result.uri, result.label, result.reference); + (this.formGroup.get('services')).push(serviceModel.buildForm()); + }); + } + + searchDatasetExternalDatasets(query: string, type: string): Observable { + const requestItem: RequestItem = new RequestItem(); + requestItem.criteria = new ExternalDatasetCriteria(); + requestItem.criteria.like = query; + requestItem.criteria.type = type; + return this.externalSourcesService.searchDatasetSExternalDatasetservice(requestItem); + } + + searchDatasetExternalDataRepositories(query: string, type: string): Observable { + const requestItem: RequestItem = new RequestItem(); + requestItem.criteria = new DataRepositoryCriteria(); + requestItem.criteria.like = query; + requestItem.criteria.type = type; + return this.externalSourcesService.searchDatasetRepository(requestItem); + } + + searchDatasetExternalRegistries(query: string, type: string): Observable { + const requestItem: RequestItem = new RequestItem(); + requestItem.criteria = new RegistryCriteria(); + requestItem.criteria.like = query; + requestItem.criteria.type = type; + return this.externalSourcesService.searchDatasetRegistry(requestItem); + } + + searchDatasetExternalServices(query: string, type: string): Observable { + const requestItem: RequestItem = new RequestItem(); + requestItem.criteria = new ServiceCriteria(); + requestItem.criteria.like = query; + requestItem.criteria.type = type; + return this.externalSourcesService.searchDatasetService(requestItem); + } + + searchDatasetTags(query: string, type: string): Observable { + const requestItem: RequestItem = new RequestItem(); + requestItem.criteria = new TagCriteria(); + requestItem.criteria.like = query; + requestItem.criteria.type = type; + return this.externalSourcesService.searchDatasetService(requestItem); + } +} diff --git a/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/datarepository/datarepository-referenced-model-helper.component.html b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/data-repository/dataset-external-data-repository-dialog-editor.component.html similarity index 100% rename from dmp-frontend/src/app/datasets/dataset-referenced-models-helper/datarepository/datarepository-referenced-model-helper.component.html rename to dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/data-repository/dataset-external-data-repository-dialog-editor.component.html diff --git a/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/externalDataset/externaldataset-referenced-model-helper.component.scss b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/data-repository/dataset-external-data-repository-dialog-editor.component.scss similarity index 100% rename from dmp-frontend/src/app/datasets/dataset-referenced-models-helper/externalDataset/externaldataset-referenced-model-helper.component.scss rename to dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/data-repository/dataset-external-data-repository-dialog-editor.component.scss diff --git a/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/data-repository/dataset-external-data-repository-dialog-editor.component.ts b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/data-repository/dataset-external-data-repository-dialog-editor.component.ts new file mode 100644 index 000000000..450c3fb39 --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/data-repository/dataset-external-data-repository-dialog-editor.component.ts @@ -0,0 +1,35 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../../../core/common/base/base.component'; +import { ExternalDataRepositoryService } from '../../../../../../core/services/external-sources/data-repository/extternal-data-repository.service'; +import { ExternalDataRepositoryEditorModel } from '../../../dataset-wizard-editor.model'; + +@Component({ + templateUrl: 'dataset-external-data-repository-dialog-editor.component.html', + styleUrls: ['./dataset-external-data-repository-dialog-editor.component.scss'] +}) +export class DatasetExternalDataRepositoryDialogEditorComponent extends BaseComponent implements OnInit { + public formGroup: FormGroup; + + constructor( + private externalDataRepositoryService: ExternalDataRepositoryService, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any + ) { super(); } + + ngOnInit(): void { + const datarepo = new ExternalDataRepositoryEditorModel(); + this.formGroup = datarepo.buildForm(); + } + + + send(value: any) { + this.externalDataRepositoryService.create(this.formGroup.value) + .pipe(takeUntil(this._destroyed)) + .subscribe( + (item) => this.dialogRef.close(item) + ); + } +} diff --git a/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/externalDataset/externaldataset-referenced-model-helper.component.html b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/external-dataset/dataset-external-dataset-dialog-editor.component.html similarity index 100% rename from dmp-frontend/src/app/datasets/dataset-referenced-models-helper/externalDataset/externaldataset-referenced-model-helper.component.html rename to dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/external-dataset/dataset-external-dataset-dialog-editor.component.html diff --git a/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/registry/registry-referenced-model-helper.component.scss b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/external-dataset/dataset-external-dataset-dialog-editor.component.scss similarity index 100% rename from dmp-frontend/src/app/datasets/dataset-referenced-models-helper/registry/registry-referenced-model-helper.component.scss rename to dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/external-dataset/dataset-external-dataset-dialog-editor.component.scss diff --git a/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/external-dataset/dataset-external-dataset-dialog-editor.component.ts b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/external-dataset/dataset-external-dataset-dialog-editor.component.ts new file mode 100644 index 000000000..2f9a97d9e --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/external-dataset/dataset-external-dataset-dialog-editor.component.ts @@ -0,0 +1,35 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../../../core/common/base/base.component'; +import { ExternalDatasetService } from '../../../../../../core/services/external-sources/dataset/external-dataset.service'; +import { ExternalDatasetEditorModel } from '../../../dataset-wizard-editor.model'; + +@Component({ + templateUrl: 'dataset-external-dataset-dialog-editor.component.html', + styleUrls: ['./dataset-external-dataset-dialog-editor.component.scss'] +}) +export class DatasetExternalDatasetDialogEditorComponent extends BaseComponent implements OnInit { + public formGroup: FormGroup; + + constructor( + private externalDatasetService: ExternalDatasetService, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any + ) { super(); } + + ngOnInit(): void { + const externalDatasetModel = new ExternalDatasetEditorModel(); + this.formGroup = externalDatasetModel.buildForm(); + } + + + send(value: any) { + this.externalDatasetService.create(this.formGroup.value) + .pipe(takeUntil(this._destroyed)) + .subscribe( + (item) => this.dialogRef.close(item) + ); + } +} diff --git a/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/registry/registry-referenced-model-helper.component.html b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/registry/dataset-external-registry-dialog-editor.component.html similarity index 100% rename from dmp-frontend/src/app/datasets/dataset-referenced-models-helper/registry/registry-referenced-model-helper.component.html rename to dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/registry/dataset-external-registry-dialog-editor.component.html diff --git a/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/services/services-referenced-model-helper.component.scss b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/registry/dataset-external-registry-dialog-editor.component.scss similarity index 100% rename from dmp-frontend/src/app/datasets/dataset-referenced-models-helper/services/services-referenced-model-helper.component.scss rename to dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/registry/dataset-external-registry-dialog-editor.component.scss diff --git a/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/registry/dataset-external-registry-dialog-editor.component.ts b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/registry/dataset-external-registry-dialog-editor.component.ts new file mode 100644 index 000000000..bfdb4e797 --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/registry/dataset-external-registry-dialog-editor.component.ts @@ -0,0 +1,35 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../../../core/common/base/base.component'; +import { ExternalRegistryService } from '../../../../../../core/services/external-sources/registry/external-registry.service'; +import { ExternalRegistryEditorModel } from '../../../dataset-wizard-editor.model'; + +@Component({ + templateUrl: 'dataset-external-registry-dialog-editor.component.html', + styleUrls: ['./dataset-external-registry-dialog-editor.component.scss'] +}) +export class DatasetExternalRegistryDialogEditorComponent extends BaseComponent implements OnInit { + public formGroup: FormGroup; + + constructor( + private externalRegistryService: ExternalRegistryService, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any + ) { super(); } + + ngOnInit(): void { + const registryModel = new ExternalRegistryEditorModel(); + this.formGroup = registryModel.buildForm(); + } + + + send(value: any) { + this.externalRegistryService.create(this.formGroup.value) + .pipe(takeUntil(this._destroyed)) + .subscribe( + (item) => this.dialogRef.close(item) + ); + } +} diff --git a/dmp-frontend/src/app/datasets/dataset-referenced-models-helper/services/services-referenced-model-helper.component.html b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/service/dataset-external-service-dialog-editor.component.html similarity index 100% rename from dmp-frontend/src/app/datasets/dataset-referenced-models-helper/services/services-referenced-model-helper.component.html rename to dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/service/dataset-external-service-dialog-editor.component.html diff --git a/dmp-frontend/src/app/dmps/editor/dmp-finalise-dialog/dmp-finalise-dialog.component.scss b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/service/dataset-external-service-dialog-editor.component.scss similarity index 100% rename from dmp-frontend/src/app/dmps/editor/dmp-finalise-dialog/dmp-finalise-dialog.component.scss rename to dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/service/dataset-external-service-dialog-editor.component.scss diff --git a/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/service/dataset-external-service-dialog-editor.component.ts b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/service/dataset-external-service-dialog-editor.component.ts new file mode 100644 index 000000000..ac12d5369 --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/dataset-wizard/external-references/editors/service/dataset-external-service-dialog-editor.component.ts @@ -0,0 +1,34 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../../../core/common/base/base.component'; +import { ExternalServiceService } from '../../../../../../core/services/external-sources/service/external-service.service'; +import { ExternalServiceEditorModel } from '../../../dataset-wizard-editor.model'; + +@Component({ + templateUrl: 'dataset-external-service-dialog-editor.component.html', + styleUrls: ['./dataset-external-service-dialog-editor.component.scss'] +}) +export class DatasetExternalServiceDialogEditorComponent extends BaseComponent implements OnInit { + public formGroup: FormGroup; + + constructor( + private externalServiceService: ExternalServiceService, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any + ) { super(); } + + ngOnInit(): void { + const serviceModel = new ExternalServiceEditorModel(); + this.formGroup = serviceModel.buildForm(); + } + + send() { + this.externalServiceService.create(this.formGroup.value) + .pipe(takeUntil(this._destroyed)) + .subscribe( + (item) => this.dialogRef.close(item) + ); + } +} diff --git a/dmp-frontend/src/app/ui/dataset/dataset.module.ts b/dmp-frontend/src/app/ui/dataset/dataset.module.ts new file mode 100644 index 000000000..d83b0c9ee --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/dataset.module.ts @@ -0,0 +1,49 @@ +import { NgModule } from '@angular/core'; +import { CommonFormsModule } from '../../common/forms/common-forms.module'; +import { CommonUiModule } from '../../common/ui/common-ui.module'; +import { AutoCompleteModule } from '../../library/auto-complete/auto-complete.module'; +import { ConfirmationDialogModule } from '../../library/confirmation-dialog/confirmation-dialog.module'; +import { UrlListingModule } from '../../library/url-listing/url-listing.module'; +import { DatasetDescriptionFormModule } from '../misc/dataset-description-form/dataset-description-form.module'; +import { ExternalSourcesModule } from '../misc/external-sources/external-sources.module'; +import { DatasetEditorComponent } from './dataset-wizard/dataset-editor/dataset-editor.component'; +import { DatasetWizardComponent } from './dataset-wizard/dataset-wizard.component'; +import { DatasetExternalReferencesEditorComponent } from './dataset-wizard/external-references/dataset-external-references-editor.component'; +import { DatasetExternalDataRepositoryDialogEditorComponent } from './dataset-wizard/external-references/editors/data-repository/dataset-external-data-repository-dialog-editor.component'; +import { DatasetExternalDatasetDialogEditorComponent } from './dataset-wizard/external-references/editors/external-dataset/dataset-external-dataset-dialog-editor.component'; +import { DatasetExternalRegistryDialogEditorComponent } from './dataset-wizard/external-references/editors/registry/dataset-external-registry-dialog-editor.component'; +import { DatasetExternalServiceDialogEditorComponent } from './dataset-wizard/external-references/editors/service/dataset-external-service-dialog-editor.component'; +import { DatasetRoutingModule } from './dataset.routing'; +import { DatasetCriteriaComponent } from './listing/criteria/dataset-criteria.component'; +import { DatasetListingComponent } from './listing/dataset-listing.component'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule, + UrlListingModule, + ConfirmationDialogModule, + AutoCompleteModule, + ExternalSourcesModule, + DatasetDescriptionFormModule, + DatasetRoutingModule + ], + declarations: [ + DatasetListingComponent, + DatasetCriteriaComponent, + DatasetWizardComponent, + DatasetEditorComponent, + DatasetExternalReferencesEditorComponent, + DatasetExternalDataRepositoryDialogEditorComponent, + DatasetExternalDatasetDialogEditorComponent, + DatasetExternalRegistryDialogEditorComponent, + DatasetExternalServiceDialogEditorComponent + ], + entryComponents: [ + DatasetExternalDataRepositoryDialogEditorComponent, + DatasetExternalDatasetDialogEditorComponent, + DatasetExternalRegistryDialogEditorComponent, + DatasetExternalServiceDialogEditorComponent + ] +}) +export class DatasetModule { } diff --git a/dmp-frontend/src/app/ui/dataset/dataset.routing.ts b/dmp-frontend/src/app/ui/dataset/dataset.routing.ts new file mode 100644 index 000000000..3afd5859d --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/dataset.routing.ts @@ -0,0 +1,63 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { AuthGuard } from '../../core/auth-guard.service'; +import { DatasetWizardComponent } from './dataset-wizard/dataset-wizard.component'; +import { DatasetListingComponent } from './listing/dataset-listing.component'; + +const routes: Routes = [ + { + path: 'new/:dmpId', + component: DatasetWizardComponent, + canActivate: [AuthGuard], + data: { + breadcrumb: true + }, + }, + { + path: 'edit/:id', + component: DatasetWizardComponent, + canActivate: [AuthGuard], + data: { + breadcrumb: true, + public: false + }, + }, + { + path: 'publicEdit/:id', + component: DatasetWizardComponent, + canActivate: [AuthGuard], + data: { + public: true + } + }, + { + path: 'new', + component: DatasetWizardComponent, + canActivate: [AuthGuard], + data: { + breadcrumb: true + }, + }, + { + path: '', + component: DatasetListingComponent, + canActivate: [AuthGuard], + data: { + breadcrumb: true + }, + }, + { + path: 'dmp/:dmpId', + component: DatasetListingComponent, + canActivate: [AuthGuard], + data: { + breadcrumb: true + }, + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class DatasetRoutingModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria.component.html b/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria.component.html new file mode 100644 index 000000000..e38e321b3 --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria.component.html @@ -0,0 +1,26 @@ +
+ + + +

{{'CRITERIA.FILTERS'| translate}}

+
+
+
+ + + {{baseErrorModel['Criteria.like']}} + + + + + {{enumUtils.toDatasetStatusString(statuses.Draft)}} + {{enumUtils.toDatasetStatusString(statuses.Finalized)}} + + {{baseErrorModel['Criteria.status']}} + + + + +
+
+
diff --git a/dmp-frontend/src/app/shared/components/criteria/datasets/datasets-criteria.component.scss b/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria.component.scss similarity index 100% rename from dmp-frontend/src/app/shared/components/criteria/datasets/datasets-criteria.component.scss rename to dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria.component.scss diff --git a/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria.component.ts b/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria.component.ts new file mode 100644 index 000000000..2bcc3f26e --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria.component.ts @@ -0,0 +1,74 @@ +import { Component, OnInit } from '@angular/core'; +import { Observable } from 'rxjs'; +import { ValidationErrorModel } from '../../../../common/forms/validation/error-model/validation-error-model'; +import { DatasetStatus } from '../../../../core/common/enum/dataset-status'; +import { ExternalSourceItemModel } from '../../../../core/model/external-sources/external-source-item'; +import { DatasetCriteria } from '../../../../core/query/dataset/dataset-criteria'; +import { TagCriteria } from '../../../../core/query/tag/tag-criteria'; +import { ExternalSourcesService } from '../../../../core/services/external-sources/external-sources.service'; +import { EnumUtils } from '../../../../core/services/utilities/enum-utils.service'; +import { RequestItem } from '../../../../core/query/request-item'; +import { BaseCriteriaComponent } from '../../../misc/criteria/base-criteria.component'; + +@Component({ + selector: 'app-dataset-criteria-component', + templateUrl: './dataset-criteria.component.html', + styleUrls: ['./dataset-criteria.component.scss'] +}) +export class DatasetCriteriaComponent extends BaseCriteriaComponent implements OnInit { + + public criteria: any; + public filteringTagsAsync = false; + public filteredTags: ExternalSourceItemModel[]; + + statuses = DatasetStatus; + + tagsAutoCompleteConfiguration = { + filterFn: this.filterTags.bind(this), + initialItems: (excludedItems: any[]) => this.filterTags('').map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1)), + displayFn: (item) => item['name'], + titleFn: (item) => item['name'] + }; + + constructor( + private externalSourcesService: ExternalSourcesService, + public enumUtils: EnumUtils + ) { + super(new ValidationErrorModel()); + } + + ngOnInit() { + super.ngOnInit(); + if (this.criteria == null) { this.criteria = {}; } + } + + setCriteria(criteria: DatasetCriteria): void { + this.criteria = criteria; + } + + onCallbackError(error: any) { + this.setErrorModel(error.error); + } + + controlModified(): void { + this.clearErrorModel(); + if (this.refreshCallback != null && + (this.criteria.like == null || this.criteria.like.length === 0 || this.criteria.like.length > 2) + ) { + this.refreshCallback(); + } + } + + filterTags(value: string): Observable { + + this.filteredTags = undefined; + this.filteringTagsAsync = true; + + const requestItem: RequestItem = new RequestItem(); + const criteria: TagCriteria = new TagCriteria(); + criteria.like = value; + requestItem.criteria = criteria; + return this.externalSourcesService.searchDatasetTags(requestItem); + + } +} diff --git a/dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.html b/dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.html new file mode 100644 index 000000000..d8b8a93ae --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.html @@ -0,0 +1,93 @@ +
+

{{'DATASET-LISTING.TITLE' | translate}} {{titlePrefix}}

+ + + + + + + + {{'DATASET-LISTING.COLUMNS.NAME' | translate}} + {{row.label}} + + + + + {{'DATASET-LISTING.COLUMNS.PROJECT' | + translate}} + {{row.project}} + + + + + {{'DATASET-LISTING.COLUMNS.DMP' | + translate}} + {{row.dmp}} + + + + + {{'DATASET-LISTING.COLUMNS.PROFILE' | + translate}} + {{row.profile}} + + + + + {{'DATASET-LISTING.COLUMNS.STATUS' | translate}} + {{enumUtils.toDatasetStatusString(row.status)}} + + + + + + + + + + + + + + + + + {{'DATASET-LISTING.COLUMNS.DESCRIPTION' | translate}} + {{row.description}} + + + + + {{'DATASET-LISTING.COLUMNS.CREATED' | translate}} + {{row.created | date:'shortDate'}} + + + + + + + + + + + + + +
diff --git a/dmp-frontend/src/app/datasets/listing/dataset-listing.component.scss b/dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.scss similarity index 100% rename from dmp-frontend/src/app/datasets/listing/dataset-listing.component.scss rename to dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.scss diff --git a/dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.ts b/dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.ts new file mode 100644 index 000000000..e00fc6bd4 --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.ts @@ -0,0 +1,156 @@ +import { DataSource } from '@angular/cdk/table'; +import { Component, OnInit, ViewChild } from '@angular/core'; +import { MatPaginator, MatSnackBar, MatSort, PageEvent } from '@angular/material'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../core/common/base/base.component'; +import { DataTableRequest } from '../../../core/model/data-table/data-table-request'; +import { DatasetListingModel } from '../../../core/model/dataset/dataset-listing'; +import { DatasetCriteria } from '../../../core/query/dataset/dataset-criteria'; +import { DatasetService } from '../../../core/services/dataset/dataset.service'; +import { DmpService } from '../../../core/services/dmp/dmp.service'; +import { EnumUtils } from '../../../core/services/utilities/enum-utils.service'; +import { BreadcrumbItem } from '../../misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '../../misc/breadcrumb/definition/IBreadCrumbComponent'; +import { DatasetCriteriaComponent } from './criteria/dataset-criteria.component'; + +@Component({ + selector: 'app-dataset-listing-component', + templateUrl: 'dataset-listing.component.html', + styleUrls: ['./dataset-listing.component.scss'] +}) +export class DatasetListingComponent extends BaseComponent implements OnInit, IBreadCrumbComponent { + + @ViewChild(MatPaginator) _paginator: MatPaginator; + @ViewChild(MatSort) sort: MatSort; + @ViewChild(DatasetCriteriaComponent) criteria: DatasetCriteriaComponent; + + breadCrumbs: Observable; + + dataSource: DatasetDataSource | null; + displayedColumns: String[] = ['label', 'project', 'dmp', 'profile', 'status', 'description', 'created']; + pageEvent: PageEvent; + titlePrefix: String; + dmpId: string; + + constructor( + private datasetService: DatasetService, + private router: Router, + private languageService: TranslateService, + private snackBar: MatSnackBar, + private route: ActivatedRoute, + private dmpService: DmpService, + public enumUtils: EnumUtils + ) { + super(); + } + + + ngOnInit() { + + this.route.params + .pipe(takeUntil(this._destroyed)) + .subscribe(async (params: Params) => { + this.dmpId = params['dmpId']; + this.criteria.setCriteria(this.getDefaultCriteria(this.dmpId)); + this.refresh(); + this.criteria.setRefreshCallback(() => this.refresh()); + if (this.dmpId != null) { + const dmp = await this.dmpService.getSingle(this.dmpId).toPromise(); + this.breadCrumbs = Observable.of([{ parentComponentName: 'DmpEditorComponent', label: dmp.label, url: 'plans/edit/' + this.dmpId }]); + if (params['dmpLabel'] !== undefined) { + this.titlePrefix = 'for ' + params['dmpLabel']; + } + } else { + this.breadCrumbs = Observable.of([]); + } + }); + } + + refresh() { + this.dataSource = new DatasetDataSource(this.datasetService, this._paginator, this.sort, this.languageService, this.snackBar, this.criteria, this.dmpId); + } + + rowClick(rowId: String) { + this.router.navigate(['/datasets/edit/' + rowId]); + } + + getDefaultCriteria(dmpId: String): DatasetCriteria { + const defaultCriteria = new DatasetCriteria(); + if (dmpId != null) { + defaultCriteria.dmpIds.push(dmpId); + } + return defaultCriteria; + } + + makeItPublic(id: String) { + this.datasetService.makeDatasetPublic(id) + .pipe(takeUntil(this._destroyed)) + .subscribe(); + } + +} + +export class DatasetDataSource extends DataSource { + + totalCount = 0; + constructor( + private _service: DatasetService, + private _paginator: MatPaginator, + private _sort: MatSort, + private _languageService: TranslateService, + private _snackBar: MatSnackBar, + private _criteria: DatasetCriteriaComponent, + private dmpId: String + ) { + super(); + + } + + connect(): Observable { + const displayDataChanges = [ + this._paginator.page + //this._sort.matSortChange + ]; + + + return Observable.merge(...displayDataChanges) + .startWith(null) + .switchMap(() => { + const startIndex = this._paginator.pageIndex * this._paginator.pageSize; + let fields: Array = new Array(); + if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; } + const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); + request.criteria = this._criteria.criteria; + if (this.dmpId) { request.criteria.allVersions = true; } + return this._service.getPaged(request); + }) + /*.catch((error: any) => { + this._snackBar.openFromComponent(SnackBarNotificationComponent, { + data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService }, + duration: 3000, + extraClasses: ['snackbar-warning'] + }); + //this._criteria.criteria.onCallbackError(error); + return Observable.of(null); + })*/ + .map(result => { + result.data = result.data; + return result; + }) + .map(result => { + return result; + }) + .map(result => { + if (!result) { return []; } + if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; } + return result.data; + }); + } + + disconnect() { + // No-op + } +} diff --git a/dmp-frontend/src/app/ui/dmp/dmp.module.ts b/dmp-frontend/src/app/ui/dmp/dmp.module.ts new file mode 100644 index 000000000..3a094e1be --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/dmp.module.ts @@ -0,0 +1,53 @@ +import { NgModule } from '@angular/core'; +import { CommonFormsModule } from '../../common/forms/common-forms.module'; +import { CommonUiModule } from '../../common/ui/common-ui.module'; +import { FormattingModule } from '../../core/formatting.module'; +import { AutoCompleteModule } from '../../library/auto-complete/auto-complete.module'; +import { ConfirmationDialogModule } from '../../library/confirmation-dialog/confirmation-dialog.module'; +import { UrlListingModule } from '../../library/url-listing/url-listing.module'; +import { DmpRoutingModule } from './dmp.routing'; +import { AddResearcherComponent } from './editor/add-researcher/add-researcher.component'; +import { AvailableProfilesComponent } from './editor/available-profiles/available-profiles.component'; +import { DmpEditorComponent } from './editor/dmp-editor.component'; +import { InvitationAcceptedComponent } from './invitation/accepted/dmp-invitation-accepted.component'; +import { DmpInvitationDialogComponent } from './invitation/dmp-invitation.component'; +import { DmpCriteriaComponent } from './listing/criteria/dmp-criteria.component'; +import { DmpListingComponent } from './listing/dmp-listing.component'; +import { DmpWizardComponent } from './wizard/dmp-wizard.component'; +import { DmpWizardEditorComponent } from './wizard/editor/dmp-wizard-editor.component'; +import { DmpWizardDatasetListingComponent } from './wizard/listing/dmp-wizard-dataset-listing.component'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule, + UrlListingModule, + ConfirmationDialogModule, + FormattingModule, + AutoCompleteModule, + DmpRoutingModule + ], + declarations: [ + DmpListingComponent, + DmpCriteriaComponent, + DmpEditorComponent, + DmpInvitationDialogComponent, + InvitationAcceptedComponent, + DmpWizardComponent, + DmpWizardEditorComponent, + DmpWizardDatasetListingComponent, + AddResearcherComponent, + AvailableProfilesComponent, + // DynamicDmpFieldResolverComponent, + // DynamicFieldsProjectComponent, + // DynamicFieldProjectComponent, + // DMPFinaliseDialogComponent + ], + entryComponents: [ + DmpInvitationDialogComponent, + AddResearcherComponent, + AvailableProfilesComponent, + // DMPFinaliseDialogComponent + ] +}) +export class DmpModule { } diff --git a/dmp-frontend/src/app/ui/dmp/dmp.routing.ts b/dmp-frontend/src/app/ui/dmp/dmp.routing.ts new file mode 100644 index 000000000..f8f632de3 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/dmp.routing.ts @@ -0,0 +1,73 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { DmpEditorComponent } from './editor/dmp-editor.component'; +import { InvitationAcceptedComponent } from './invitation/accepted/dmp-invitation-accepted.component'; +import { DmpListingComponent } from './listing/dmp-listing.component'; +import { DmpWizardComponent } from './wizard/dmp-wizard.component'; + +const routes: Routes = [ + { + path: '', + component: DmpListingComponent, + data: { + breadcrumb: true + }, + }, + { + path: 'versions/:groupId', + component: DmpListingComponent, + data: { + breadcrumb: true + }, + }, + { + path: 'project/:projectId', + component: DmpListingComponent, + data: { + breadcrumb: true + }, + }, + { + path: 'edit/:id', + component: DmpEditorComponent, + data: { + breadcrumb: true + }, + }, + { + path: 'new', + component: DmpEditorComponent, + data: { + breadcrumbs: 'new' + } + }, + { + path: 'new_version/:id', + component: DmpWizardComponent, + data: { + clone: false, + breadcrumb: true + }, + }, + { + path: 'clone/:id', + component: DmpWizardComponent, + data: { + clone: false, + breadcrumb: true + }, + }, + { + path: 'invitation/:id', + component: InvitationAcceptedComponent, + data: { + breadcrumb: true + }, + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class DmpRoutingModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/shared/components/add-researchers/add-researchers.component.html b/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.html similarity index 100% rename from dmp-frontend/src/app/shared/components/add-researchers/add-researchers.component.html rename to dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.html diff --git a/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.ts b/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.ts new file mode 100644 index 000000000..7302ec939 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.ts @@ -0,0 +1,36 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../core/common/base/base.component'; +import { ExternalResearcherService } from '../../../../core/services/external-sources/researcher/external-researcher.service'; +import { ResearcherEditorModel } from './add-researcher.model'; + +@Component({ + selector: 'app-add-researcher-component', + templateUrl: 'add-researcher.component.html', +}) +export class AddResearcherComponent extends BaseComponent implements OnInit { + + public formGroup: FormGroup; + + constructor( + private externalResearcherService: ExternalResearcherService, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any + ) { super(); } + + ngOnInit(): void { + const researcher = new ResearcherEditorModel(); + this.formGroup = researcher.buildForm(); + } + + + send(value: any) { + this.externalResearcherService.createResearcher(this.formGroup.value) + .pipe(takeUntil(this._destroyed)) + .subscribe( + null, null, () => this.dialogRef.close() + ); + } +} diff --git a/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.model.ts b/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.model.ts new file mode 100644 index 000000000..529a0bb3d --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.model.ts @@ -0,0 +1,29 @@ +import { FormBuilder, FormGroup } from '@angular/forms'; +import { ResearcherModel } from '../../../../core/model/researcher/researcher'; + +export class ResearcherEditorModel { + public id: String; + public name: String; + public lastName: String; + public uri: String; + public email: String; + + fromModel(item: ResearcherModel): ResearcherEditorModel { + this.id = item.id; + this.name = item.name; + this.email = item.email; + this.uri = item.uri; + + return this; + } + + buildForm(): FormGroup { + const formGroup = new FormBuilder().group({ + firstName: [this.name], + lastName: [this.lastName] + }); + + return formGroup; + } + +} diff --git a/dmp-frontend/src/app/shared/components/available-profiles/available-profiles.component.html b/dmp-frontend/src/app/ui/dmp/editor/available-profiles/available-profiles.component.html similarity index 100% rename from dmp-frontend/src/app/shared/components/available-profiles/available-profiles.component.html rename to dmp-frontend/src/app/ui/dmp/editor/available-profiles/available-profiles.component.html diff --git a/dmp-frontend/src/app/ui/dmp/editor/available-profiles/available-profiles.component.ts b/dmp-frontend/src/app/ui/dmp/editor/available-profiles/available-profiles.component.ts new file mode 100644 index 000000000..3a104fafa --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/available-profiles/available-profiles.component.ts @@ -0,0 +1,49 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../core/common/base/base.component'; +import { DatasetProfileModel } from '../../../../core/model/dataset/dataset-profile'; +import { DatasetService } from '../../../../core/services/dataset/dataset.service'; + +@Component({ + selector: 'app-available-profiles-component', + templateUrl: 'available-profiles.component.html', +}) +export class AvailableProfilesComponent extends BaseComponent implements OnInit { + + public formGroup: FormGroup; + public profiles: DatasetProfileModel[] = []; + public selectedProfiles: DatasetProfileModel[] = []; + public selectedOptions: any; + constructor( + private datasetService: DatasetService, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any + ) { super(); } + + ngOnInit(): void { + this.formGroup = this.data['profiles']; + this.datasetService.getDatasetProfiles() + .pipe(takeUntil(this._destroyed)) + .subscribe(data => { + this.profiles = data; + }); + } + + addProfiles(profiles) { + profiles.selectedOptions.selected.forEach(element => { + const selectedElement = { + id: element.value.id, + label: element.value.label + } + this.selectedProfiles.push(selectedElement); + }); + this.formGroup.setValue(this.selectedProfiles); + this.dialogRef.close(); + } + + isOptionSelected(profile: any) { + return this.formGroup.value.map(x => x.id).indexOf(profile.id) !== -1; + } +} diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.html b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.html new file mode 100644 index 000000000..9e3f0ffd5 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.html @@ -0,0 +1,144 @@ +
+
+ {{'DMP-EDITOR.TITLE.NEW' | translate}} + +

{{formGroup?.get('label')?.value}}

+
+
+
+ + +
+
+
+
+
+ +
+
+ +
+
+ +
+ + + + + + + + + +
+
+
+
+ +
+ + + {{baseErrorModel.label}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + {{errorModel.description}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + {{errorModel.description}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + + {{errorModel.description}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + + + + + {{errorModel.description}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + {{errorModel.description}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + + + + +
+ +

Associated Users

+ + person +
{{user.name}}
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+ +
diff --git a/dmp-frontend/src/app/dmps/editor/dmp-editor.component.scss b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.scss similarity index 100% rename from dmp-frontend/src/app/dmps/editor/dmp-editor.component.scss rename to dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.scss diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts new file mode 100644 index 000000000..d9b4d1130 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts @@ -0,0 +1,428 @@ +import { AfterViewInit, Component, ViewContainerRef } from '@angular/core'; +import { FormControl, FormGroup } from '@angular/forms'; +import { MatDialog, MatSnackBar } from '@angular/material'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import * as FileSaver from 'file-saver'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../core/common/base/base.component'; +import { DmpStatus } from '../../../core/common/enum/dmp-status'; +import { Status } from '../../../core/common/enum/Status'; +import { DatasetListingModel } from '../../../core/model/dataset/dataset-listing'; +import { DatasetProfileModel } from '../../../core/model/dataset/dataset-profile'; +import { DmpModel } from '../../../core/model/dmp/dmp'; +import { ExternalSourceItemModel } from '../../../core/model/external-sources/external-source-item'; +import { UserModel } from '../../../core/model/user/user'; +import { BaseCriteria } from '../../../core/query/base-criteria'; +import { DatasetProfileCriteria } from '../../../core/query/dataset-profile/dataset-profile-criteria'; +import { ProjectCriteria } from '../../../core/query/project/project-criteria'; +import { DmpProfileService } from '../../../core/services/dmp/dmp-profile.service'; +import { DmpService } from '../../../core/services/dmp/dmp.service'; +import { ExternalSourcesService } from '../../../core/services/external-sources/external-sources.service'; +import { ProjectService } from '../../../core/services/project/project.service'; +import { MultipleAutoCompleteConfiguration } from '../../../library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { SingleAutoCompleteConfiguration } from '../../../library/auto-complete/single/single-auto-complete-configuration'; +import { SnackBarNotificationComponent } from '../../../library/notification/snack-bar/snack-bar-notification.component'; +import { RequestItem } from '../../../core/query/request-item'; +import { BaseErrorModel } from '../../../models/error/BaseErrorModel'; +import { LanguageResolverService } from '../../../services/language-resolver/language-resolver.service'; +import { BreadcrumbItem } from '../../misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '../../misc/breadcrumb/definition/IBreadCrumbComponent'; +import { AddResearcherComponent } from './add-researcher/add-researcher.component'; +import { AvailableProfilesComponent } from './available-profiles/available-profiles.component'; +import { DmpEditorModel } from './dmp-editor.model'; +import { DmpFinalizeDialogComponent } from './dmp-finalize-dialog/dmp-finalize-dialog.component'; + +@Component({ + selector: 'app-dmp-editor-component', + templateUrl: 'dmp-editor.component.html', + styleUrls: ['./dmp-editor.component.scss'] +}) +export class DmpEditorComponent extends BaseComponent implements AfterViewInit, IBreadCrumbComponent { + + editMode = false; + + breadCrumbs: Observable; + isNew = true; + textCtrl = new FormControl(); + dmp: DmpEditorModel; + formGroup: FormGroup = null; + + filteringOrganisationsAsync = false; + filteringResearchersAsync = false; + filteredProfilesAsync = false; + filteredOrganisations: ExternalSourceItemModel[]; + filteredResearchers: ExternalSourceItemModel[]; + filteredProfiles: DatasetProfileModel[]; + + projectAutoCompleteConfiguration: SingleAutoCompleteConfiguration; + profilesAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; + organisationsAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; + researchersAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; + + createNewVersion; + associatedUsers: Array; + // filteredOptions: Observable; + + constructor( + private dmpProfileService: DmpProfileService, + private dmpService: DmpService, + private projectService: ProjectService, + private externalSourcesService: ExternalSourcesService, + private route: ActivatedRoute, + private snackBar: MatSnackBar, + private router: Router, + private language: TranslateService, + private _service: DmpService, + private dialog: MatDialog, + private _viewContainerRef: ViewContainerRef, + public languageResolverService: LanguageResolverService + ) { + super(); + // this.filteredOptions = dmpProfileService.getAll({ criteria: new DmpProfileCriteria() }); + } + + ngAfterViewInit() { + this.route.params + .pipe(takeUntil(this._destroyed)) + .subscribe((params: Params) => { + const itemId = params['id']; + + const projectRequestItem: RequestItem = new RequestItem(); + projectRequestItem.criteria = new ProjectCriteria(); + const organisationRequestItem: RequestItem = new RequestItem(); + organisationRequestItem.criteria = new BaseCriteria(); + + + + this.projectAutoCompleteConfiguration = { + filterFn: this.searchProject.bind(this), + initialItems:(extraData) => this.searchProject(''), + displayFn: (item) => item['label'], + titleFn: (item) => item['label'], + //mapFn: (item) => new JsonSerializer().fromJSONArray(item, ProjectReference).map(item => item.toDropdownList()), + loadDataOnStart: true + }; + + this.profilesAutoCompleteConfiguration = { + filterFn: this.filterProfiles.bind(this), + initialItems: (excludedItems: any[]) => this.filterProfiles('').map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1)), + displayFn: (item) => item['label'], + titleFn: (item) => item['label'], + //mapFn: (item) => new JsonSerializer().fromJSONArray(item, ProjectReference).map(item => item.toDropdownList()), + loadDataOnStart: true + }; + + this.organisationsAutoCompleteConfiguration = { + filterFn: this.filterOrganisations.bind(this), + initialItems: (excludedItems: any[]) => this.filterOrganisations('').map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1)), + displayFn: (item) => item['name'], + titleFn: (item) => item['name'], + loadDataOnStart: true + }; + + this.researchersAutoCompleteConfiguration = { + filterFn: this.filterResearchers.bind(this), + initialItems: (excludedItems: any[]) => this.filterResearchers('').map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1)), + displayFn: (item) => item['name'], + titleFn: (item) => item['name'], + loadDataOnStart: true + }; + + if (itemId != null) { + this.isNew = false; + this.dmpService.getSingle(itemId).map(data => data as DmpModel) + .pipe(takeUntil(this._destroyed)) + .subscribe(async data => { + this.dmp = new DmpEditorModel().fromModel(data); + this.formGroup = this.dmp.buildForm(); + if (!this.editMode || this.dmp.status === Status.Inactive) { this.formGroup.disable(); } + if (this.formGroup.get('profile') && this.formGroup.get('profile').value) { + this.textCtrl.patchValue(this.formGroup.get('profile').value); + } + this.breadCrumbs = Observable.of([ + { + parentComponentName: 'DmpListingComponent', + label: 'DMPs', + url: 'dmps', + notFoundResolver: [await this.projectService.getSingle(this.dmp.project.id).map(x => ({ label: x.label, url: '/projects/edit/' + x.id }) as BreadcrumbItem).toPromise()] + }] + ); + this.associatedUsers = data.associatedUsers; + }); + } else { + this.dmp = new DmpEditorModel(); + setTimeout(async () => { + this.formGroup = this.dmp.buildForm(); + if (this.formGroup.get('profile') && this.formGroup.get('profile').value) { + this.textCtrl.patchValue(this.formGroup.get('profile').value); + } + this.breadCrumbs = Observable.of([ + { + parentComponentName: 'DmpListingComponent', + label: 'DMPs', + url: 'dmps', + } + ]); + }); + } + + }); + this.route + .queryParams + .pipe(takeUntil(this._destroyed)) + .subscribe(params => { + this.createNewVersion = params['clone']; + }); + } + + searchProject(query: string) { + const projectRequestItem: RequestItem = new RequestItem(); + projectRequestItem.criteria = new ProjectCriteria(); + projectRequestItem.criteria.like = query; + return this.projectService.getWithExternal(projectRequestItem); + } + + formSubmit(): void { + //this.touchAllFormFields(this.formGroup); + if (!this.isFormValid()) { return; } + this.onSubmit(); + } + + public isFormValid() { + return this.formGroup.valid; + } + + onSubmit(): void { + this.dmpService.createDmp(this.formGroup.value) + .pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) + ); + } + + onCallbackSuccess(): void { + this.snackBar.openFromComponent(SnackBarNotificationComponent, { + data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, + duration: 3000, + }); + this.router.navigate(['/plans']); + } + + onCallbackError(error: any) { + this.setErrorModel(error.error); + //this.validateAllFormFields(this.formGroup); + } + + public setErrorModel(errorModel: BaseErrorModel) { + Object.keys(errorModel).forEach(item => { + (this.dmp.errorModel)[item] = (errorModel)[item]; + }); + } + + public cancel(): void { + this.router.navigate(['/plans']); + } + + public invite(): void { + this.router.navigate(['/invite/' + this.dmp.id]); + } + + filterOrganisations(value: string): Observable { + + this.filteredOrganisations = undefined; + this.filteringOrganisationsAsync = true; + + return this.externalSourcesService.searchDMPOrganizations(value); + } + + filterResearchers(value: string): Observable { + + this.filteredResearchers = undefined; + this.filteringResearchersAsync = true; + + return this.externalSourcesService.searchDMPResearchers({ criteria: { name: value, like: null } }); + } + + filterProfiles(value: string): Observable { + + this.filteredProfiles = undefined; + this.filteredProfilesAsync = true; + + const request = new RequestItem(); + const criteria = new DatasetProfileCriteria(); + criteria.like = value; + request.criteria = criteria; + return this._service.searchDMPProfiles(request); + } + + addResearcher(rowId: any, rowName: any) { + const dialogRef = this.dialog.open(AddResearcherComponent, { + data: { + dmpId: rowId, + dmpName: rowName + } + }); + + } + + availableProfiles() { + const dialogRef = this.dialog.open(AvailableProfilesComponent, { + // height: '355px', + // width: '700px', + data: { + profiles: this.formGroup.get('profiles') + } + }); + + return false; + } + + openConfirm(dmpLabel, id): void { + // this._dialogService.openConfirm({ + // message: 'Are you sure you want to delete the "' + dmpLabel + '"', + // disableClose: true || false, + // viewContainerRef: this._viewContainerRef, + // title: 'Confirm', + // cancelButton: 'No', + // acceptButton: 'Yes' + // }).afterClosed() + // .pipe(takeUntil(this._destroyed)) + // .subscribe((accept: boolean) => { + // if (accept) { + // this.dmpService.delete(id) + // .pipe(takeUntil(this._destroyed)) + // .subscribe(() => { + // this.router.navigate(['/plans']); + // }); + // } else { + // // DO SOMETHING ELSE + // } + // }); + } + + + selectOption(option: any) { + this.dmp.definition = null; + this.formGroup.get('profile').patchValue(option, { emitEvent: false }); + this.dmpProfileService.getSingle(option.id) + .pipe(takeUntil(this._destroyed)) + .subscribe(result => { + this.dmp.definition = result.definition; + }); + } + + displayWith(item: any) { + if (!item) { return null; } + return item['label']; + } + + redirectToProject() { + this.router.navigate(['projects/edit/' + this.dmp.project.id]); + } + + redirectToDatasets() { + this.router.navigate(['datasets/dmp/' + this.dmp.id]); + } + + newVersion(id: String, label: String) { + this.router.navigate(['/plans/new_version/' + id, { dmpLabel: label }]); + } + + clone(id: String) { + this.router.navigate(['/plans/clone/' + id]); + } + + viewVersions(rowId: String, rowLabel: String) { + this.router.navigate(['/plans/versions/' + rowId], { queryParams: { groupLabel: rowLabel } }); + } + + downloadXml(id: string) { + this.dmpService.downloadXML(id) + .pipe(takeUntil(this._destroyed)) + .subscribe(response => { + const blob = new Blob([response.body], { type: 'application/xml' }); + const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition')); + + FileSaver.saveAs(blob, filename); + }); + } + + downloadDocx(id: string) { + this.dmpService.downloadDocx(id) + .pipe(takeUntil(this._destroyed)) + .subscribe(response => { + const blob = new Blob([response.body], { type: 'application/octet-stream' }); + const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition')); + + FileSaver.saveAs(blob, filename); + }); + } + + downloadPDF(id: string) { + this.dmpService.downloadPDF(id) + .pipe(takeUntil(this._destroyed)) + .subscribe(response => { + const blob = new Blob([response.body], { type: 'application/octet-stream' }); + const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition')); + + FileSaver.saveAs(blob, filename); + }); + } + + getFilenameFromContentDispositionHeader(header: string): string { + const regex: RegExp = new RegExp(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/g); + + const matches = header.match(regex); + let filename: string; + for (let i = 0; i < matches.length; i++) { + const match = matches[i]; + if (match.includes('filename="')) { + filename = match.substring(10, match.length - 1); + break; + } else if (match.includes('filename=')) { + filename = match.substring(9); + break; + } + } + return filename; + } + + public enableForm() { + if (this.formGroup.get('status').value !== DmpStatus.Finalized) { + this.editMode = true; + this.formGroup.enable(); + } else { + this.dmpService.unlock(this.formGroup.get('id').value) + .pipe(takeUntil(this._destroyed)) + .subscribe(x => { + this.editMode = true; + this.formGroup.get('status').patchValue(DmpStatus.Draft); + this.formGroup.enable(); + }); + } + } + + public disableForm() { + this.editMode = false; + this.formGroup.disable(); + } + + saveAndFinalize() { + const dialogRef = this.dialog.open(DmpFinalizeDialogComponent, { + data: { + submitFunction: (items: DatasetListingModel[]) => { + this.formGroup.get('status').setValue('1'); + this.formGroup.addControl('datasets', new FormControl(items)); + this.formSubmit(); + dialogRef.close(); + }, + dmp: this.dmp + } + }); + } + + +} diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.model.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.model.ts new file mode 100644 index 000000000..a35f738a6 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.model.ts @@ -0,0 +1,149 @@ +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; +import { BackendErrorValidator } from "../../../common/forms/validation/custom-validator"; +import { ValidationErrorModel } from "../../../common/forms/validation/error-model/validation-error-model"; +import { ValidationContext } from "../../../common/forms/validation/validation-context"; +import { Status } from "../../../core/common/enum/Status"; +import { DmpProfile, DmpProfileDefinition } from "../../../core/model/dmp-profile/dmp-profile"; +import { DmpModel } from "../../../core/model/dmp/dmp"; +import { DmpDynamicField } from "../../../core/model/dmp/dmp-dynamic-field"; +import { DmpDynamicFieldDependency } from "../../../core/model/dmp/dmp-dynamic-field-dependency"; +import { OrganizationModel } from "../../../core/model/organisation/organization"; +import { ProjectModel } from "../../../core/model/project/project"; +import { ResearcherModel } from "../../../core/model/researcher/researcher"; +import { UserModel } from "../../../core/model/user/user"; +import { ValidJsonValidator } from "../../../library/auto-complete/auto-complete-custom-validator"; + +export class DmpEditorModel { + public id: string; + public label: string; + public groupId: String; + public profile: String; + public version: number; + public lockable: boolean; + public creator: UserModel; + public status: Status = Status.Active; + public description: String; + public project: ProjectModel; + public organisations: OrganizationModel[] = []; + public researchers: ResearcherModel[] = []; + public profiles: DmpProfile[] = []; + public associatedUsers: UserModel[] = []; + public definition: DmpProfileDefinition; + public dynamicFields: Array = []; + public errorModel: ValidationErrorModel = new ValidationErrorModel(); + + fromModel(item: DmpModel): DmpEditorModel { + this.id = item.id; + this.profile = item.profile; + this.label = item.label; + this.groupId = item.groupId; + this.version = item.version; + this.status = item.status; + this.lockable = item.lockable; + this.description = item.description; + this.project = item.project; + this.organisations = item.organisations; + this.researchers = item.researchers; + this.profiles = item.profiles; + this.associatedUsers = item.associatedUsers; + if (item.definition) { this.definition = item.definition; } + if (item.dynamicFields) { item.dynamicFields.map(x => this.dynamicFields.push(new DmpDynamicFieldEditorModel().fromModel(x))); } + this.creator = item.creator; + return this; + } + + buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { + if (context == null) { context = this.createValidationContext(); } + + const formGroup = new FormBuilder().group({ + id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators], + profile: [{ value: this.profile, disabled: disabled }, context.getValidation('profile').validators], + label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators], + groupId: [{ value: this.groupId, disabled: disabled }, context.getValidation('groupId').validators], + version: [{ value: this.version, disabled: disabled }, context.getValidation('version').validators], + status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators], + description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators], + project: [{ value: this.project, disabled: disabled }, context.getValidation('project').validators], + organisations: [{ value: this.organisations, disabled: disabled }, context.getValidation('organisations').validators], + researchers: [{ value: this.researchers, disabled: disabled }, context.getValidation('researchers').validators], + profiles: [{ value: this.profiles, disabled: disabled }, context.getValidation('profiles').validators], + associatedUsers: [{ value: this.associatedUsers, disabled: disabled }, context.getValidation('associatedUsers').validators], + }); + + const dynamicFields = new Array(); + if (this.dynamicFields) { this.dynamicFields.forEach(item => dynamicFields.push(item.buildForm())); } + + formGroup.addControl('dynamicFields', new FormBuilder().array(dynamicFields)); + + return formGroup; + } + + createValidationContext(): ValidationContext { + const baseContext: ValidationContext = new ValidationContext(); + baseContext.validation.push({ key: 'id', validators: [BackendErrorValidator(this.errorModel, 'id')] }); + baseContext.validation.push({ key: 'profile', validators: [BackendErrorValidator(this.errorModel, 'profile')] }); + baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'label')] }); + baseContext.validation.push({ key: 'groupId', validators: [BackendErrorValidator(this.errorModel, 'groupId')] }); + baseContext.validation.push({ key: 'version', validators: [BackendErrorValidator(this.errorModel, 'version')] }); + baseContext.validation.push({ key: 'status', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'status')] }); + baseContext.validation.push({ key: 'description', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'description')] }); + baseContext.validation.push({ key: 'project', validators: [Validators.required, ValidJsonValidator, BackendErrorValidator(this.errorModel, 'project')] }); + baseContext.validation.push({ key: 'organisations', validators: [BackendErrorValidator(this.errorModel, 'organisations')] }); + baseContext.validation.push({ key: 'researchers', validators: [BackendErrorValidator(this.errorModel, 'researchers')] }); + baseContext.validation.push({ key: 'profiles', validators: [Validators.required, ValidJsonValidator, BackendErrorValidator(this.errorModel, 'profiles')] }); + baseContext.validation.push({ key: 'associatedUsers', validators: [BackendErrorValidator(this.errorModel, 'associatedUsers')] }); + + return baseContext; + } +} + +export class DmpDynamicFieldEditorModel { + + public id: string; + public name: string; + public required: boolean; + public queryProperty; + public value: string; + public dependencies: Array = []; + + fromModel(item: DmpDynamicField): DmpDynamicFieldEditorModel { + this.id = item.id; + this.name = item.name; + this.required = item.required; + this.value = item.value; + this.queryProperty = item.queryProperty; + if (item.dependencies) { item.dependencies.map(x => this.dependencies.push(new DmpDynamicFieldDependencyEditorModel().fromModel(x))); } + return this; + } + + buildForm(): FormGroup { + const builder = new FormBuilder(); + const formGroup = builder.group({ + id: [this.id], + name: [this.name], + required: [this.required], + value: [this.value], + queryProperty: [this.queryProperty], + dependencies: [this.dependencies] + }); + return formGroup; + } +} + +export class DmpDynamicFieldDependencyEditorModel { + public id: string; + public queryProperty: string; + + fromModel(item: DmpDynamicFieldDependency): DmpDynamicFieldDependencyEditorModel { + this.id = item.id; + this.queryProperty = item.queryProperty; + return this; + } + + buildForm(): FormGroup { + return new FormBuilder().group({ + id: [this.id], + queryProperty: [this.queryProperty] + }); + } +} \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.html b/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.html new file mode 100644 index 000000000..562920e02 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.html @@ -0,0 +1,31 @@ +
+
+
+
+
+ {{'DMP-FINALISE-DIALOG.ALREADY-FINALISED-DATASETS' | translate}} + + +
{{ dataset.label }}
+
+
+
+
+ {{'DMP-FINALISE-DIALOG.FINALISE-TITLE' | translate}} + + + {{ dataset.label }} + + +
+ {{'DMP-FINALISE-DIALOG.VALIDATION.AT-LEAST-ONE-DATASET-FINALISED' + | translate}} +
+
+
+ +
+
+
diff --git a/dmp-frontend/src/app/dmps/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.scss b/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.scss similarity index 100% rename from dmp-frontend/src/app/dmps/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.scss rename to dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.scss diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.ts new file mode 100644 index 000000000..0379b476f --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.ts @@ -0,0 +1,104 @@ +import { Component, Inject, OnInit, ViewChild } from '@angular/core'; +import { AbstractControl, FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms'; +import { MatDialogRef, MatSelectionList, MAT_DIALOG_DATA } from '@angular/material'; +import { Router } from '@angular/router'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../core/common/base/base.component'; +import { DatasetStatus } from '../../../../core/common/enum/dataset-status'; +import { DataTableRequest } from '../../../../core/model/data-table/data-table-request'; +import { DatasetListingModel } from '../../../../core/model/dataset/dataset-listing'; +import { DmpModel } from '../../../../core/model/dmp/dmp'; +import { DatasetCriteria } from '../../../../core/query/dataset/dataset-criteria'; +import { DatasetService } from '../../../../core/services/dataset/dataset.service'; + +@Component({ + selector: 'app-dmp-finalize-dialog-component', + templateUrl: 'dmp-finalize-dialog.component.html', + +}) +export class DmpFinalizeDialogComponent extends BaseComponent implements OnInit { + + @ViewChild('datasetsDraftSelectionList') selectionList: MatSelectionList; + public formGroup: FormGroup; + public submitFunction: (items: DatasetListingModel[]) => any; + public dmp: DmpModel; + public datasetsFinalized: DatasetListingModel[]; + public datasetsDraft: DatasetListingModel[]; + constructor( + public router: Router, + public dialogRef: MatDialogRef, + public dmpService: DatasetService, + @Inject(MAT_DIALOG_DATA) public data: any + ) { + super(); + this.submitFunction = data['submitFunction']; + this.dmp = data['dmp']; + } + + ngOnInit(): void { + this.initialiseDatasetFinalizedRequest(); + this.initialiseDmpFinalizedRequest(); + } + + initialiseDatasetFinalizedRequest() { + const request = new DataTableRequest(null, null, null); + request.criteria = new DatasetCriteria(); + request.criteria.dmpIds = [this.dmp.id]; + request.criteria.status = DatasetStatus.Finalized; + this.dmpService.getPaged(request).map(x => x.data) + .pipe(takeUntil(this._destroyed)) + .subscribe(result => { + this.datasetsFinalized = result; + this.createFormGroup(); + }); + } + + initialiseDmpFinalizedRequest() { + const request = new DataTableRequest(null, null, null); + request.criteria = new DatasetCriteria(); + request.criteria.dmpIds = [this.dmp.id]; + request.criteria.status = DatasetStatus.Draft; + this.dmpService.getPaged(request).map(x => x.data) + .pipe(takeUntil(this._destroyed)) + .subscribe(result => { + this.datasetsDraft = result; + }); + } + + createFormGroup() { + this.formGroup = new FormBuilder().group({ + datasets: [this.datasetsFinalized, this.minLengthArray(1)] + }); + } + + onSubmit() { + //this.formGroup.get('datasets').patchValue(this.formGroup.get('datasets').value.push(this.selectionList.selectedOptions.selected.map(x => x.value))); + this.touchAllFormFields(this.formGroup); + if (!this.formGroup.valid) { return; } + this.submitFunction(this.formGroup.get('datasets').value); + } + + minLengthArray(min: number) { + return (c: AbstractControl): { [key: string]: any } => { + if (c.value.length >= min) { + return null; + } + return { 'minLengthArray': { valid: false } }; + }; + } + + public touchAllFormFields(formControl: AbstractControl) { + if (formControl instanceof FormControl) { + formControl.markAsTouched(); + } else if (formControl instanceof FormGroup) { + Object.keys(formControl.controls).forEach(item => { + const control = formControl.get(item); + this.touchAllFormFields(control); + }); + } else if (formControl instanceof FormArray) { + formControl.controls.forEach(item => { + this.touchAllFormFields(item); + }); + } + } +} diff --git a/dmp-frontend/src/app/ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.html b/dmp-frontend/src/app/ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.html new file mode 100644 index 000000000..8c4046ac3 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.html @@ -0,0 +1,15 @@ +
+
+ + + + + + + + + + + +
+
\ No newline at end of file diff --git a/dmp-frontend/src/app/dmps/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.scss b/dmp-frontend/src/app/ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.scss similarity index 100% rename from dmp-frontend/src/app/dmps/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.scss rename to dmp-frontend/src/app/ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.scss diff --git a/dmp-frontend/src/app/ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.ts new file mode 100644 index 000000000..b62fdf4fc --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.ts @@ -0,0 +1,39 @@ +import { Component, Input, OnDestroy, OnInit } from '@angular/core'; +import { FormArray, FormBuilder, FormGroup } from '@angular/forms'; +import { DmpProfileFieldDataType } from '../../../../core/common/enum/dmp-profile-field-type'; +import { DmpProfileType } from '../../../../core/common/enum/dmp-profile-type'; +import { DmpProfileDefinition } from '../../../../core/model/dmp-profile/dmp-profile'; + +@Component({ + selector: 'app-dynamic-dmp-field-resolver', + templateUrl: 'dynamic-dmp-field-resolver.component.html', + styleUrls: ['./dynamic-dmp-field-resolver.component.scss'] +}) +export class DynamicDmpFieldResolverComponent implements OnInit, OnDestroy { + + + dmpProfileFieldDataType = DmpProfileFieldDataType; + dmpProfileTypeEnum = DmpProfileType; + + @Input() + dmpProfileDefinition: DmpProfileDefinition; + + @Input() + formGroup: FormGroup; + + ngOnInit(): void { + this.formGroup.addControl('properties', new FormBuilder().group([])); + (this.formGroup.get('properties')).addControl('fields', new FormBuilder().array([])); + + this.dmpProfileDefinition.fields.forEach(item => { + (this.formGroup.get('properties').get('fields')).push(new FormBuilder().group({ + id: [item.id], + value: [item.value] + })); + }); + } + + ngOnDestroy(): void { + this.formGroup.removeControl('properties'); + } +} diff --git a/dmp-frontend/src/app/dmps/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.html b/dmp-frontend/src/app/ui/dmp/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.html similarity index 100% rename from dmp-frontend/src/app/dmps/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.html rename to dmp-frontend/src/app/ui/dmp/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.html diff --git a/dmp-frontend/src/app/dmps/editor/dynamic-fields-project/dynamic-fields-project.component.scss b/dmp-frontend/src/app/ui/dmp/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.scss similarity index 100% rename from dmp-frontend/src/app/dmps/editor/dynamic-fields-project/dynamic-fields-project.component.scss rename to dmp-frontend/src/app/ui/dmp/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.scss diff --git a/dmp-frontend/src/app/ui/dmp/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.ts new file mode 100644 index 000000000..b7a90c31e --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/dynamic-fields-project/dynamic-field-project/dynamic-field-project.component.ts @@ -0,0 +1,85 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { RequestItem } from '../../../../../core/query/request-item'; +import { DmpService } from '../../../../../core/services/dmp/dmp.service'; +import { SingleAutoCompleteConfiguration } from '../../../../../library/auto-complete/single/single-auto-complete-configuration'; +import { DynamicFieldProjectCriteria, DynamicFieldProjectCriteriaDependencies } from '../../../../../models/dynamic-field-project/DynamicFieldProjectCriteria'; + +@Component({ + selector: 'app-dynamic-field-project', + templateUrl: 'dynamic-field-project.component.html', + styleUrls: ['./dynamic-field-project.component.scss'] +}) +export class DynamicFieldProjectComponent implements OnInit { + + constructor( + private dmpService: DmpService + ) { } + + @Input() + dependencies: Array; + + @Input() + formGroup: FormGroup; + + autoCompleteConfiguration: SingleAutoCompleteConfiguration; + + ngOnInit(): void { + + this.autoCompleteConfiguration = { + filterFn: this.searchDynamicField.bind(this), + initialItems: (extraData) => this.searchDynamicField(''), + displayFn: (item) => item['label'], + titleFn: (item) => item['label'] + }; + + } + + searchDynamicField(query: string) { + const requestItem = new RequestItem(); + requestItem.criteria = { id: this.formGroup.get('id').value, dynamicFields: this.buildDependencies() }; + return this.dmpService.getDynamicField(requestItem); + } + + hasUnResolvedDependencies() { + if (this.dependencies == null || this.dependencies.length === 0) { + if (this.formGroup.get('value').disabled) { + this.updateConfiguration(); + this.formGroup.get('value').enable({ onlySelf: true, emitEvent: false }); + } + return false; + } + for (let i = 0; i < this.dependencies.length; i++) { + if (!this.dependencies[i].get('value').value) { + this.formGroup.get('value').disable({ onlySelf: true, emitEvent: false }); + return true; + } + } + if (this.formGroup.get('value').disabled) { + this.updateConfiguration(); + this.formGroup.get('value').enable({ onlySelf: true, emitEvent: false }); + } + return false; + } + + updateConfiguration() { + // const requestItem = new RequestItem(); + // requestItem.criteria = { id: this.formGroup.get('id').value, dynamicFields: this.buildDependencies() }; + // this.autoCompleteConfiguration = new AutoCompleteConfiguration(this.dmpService.getDynamicField.bind(this.dmpService), requestItem); + // this.autocomplete.inputData = this.autoCompleteConfiguration; + } + + buildDependencies(): Array { + if (!this.dependencies || this.dependencies.length === 0) { return []; } + const dependencies = new Array(); + for (let i = 0; i < this.dependencies.length; i++) { + dependencies.push({ property: this.dependencies[i].get('id').value, value: this.assignFunction(this.dependencies[i].get('value').value) }); + } + return dependencies; + } + + assignFunction(item: any): any { + if (!item) { return null; } + return item['id']; + } +} diff --git a/dmp-frontend/src/app/dmps/editor/dynamic-fields-project/dynamic-fields-project.component.html b/dmp-frontend/src/app/ui/dmp/editor/dynamic-fields-project/dynamic-fields-project.component.html similarity index 100% rename from dmp-frontend/src/app/dmps/editor/dynamic-fields-project/dynamic-fields-project.component.html rename to dmp-frontend/src/app/ui/dmp/editor/dynamic-fields-project/dynamic-fields-project.component.html diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-boolean-decision/dynamic-field-boolean-decision.component.css b/dmp-frontend/src/app/ui/dmp/editor/dynamic-fields-project/dynamic-fields-project.component.scss similarity index 100% rename from dmp-frontend/src/app/form/dynamic-fields/dynamic-field-boolean-decision/dynamic-field-boolean-decision.component.css rename to dmp-frontend/src/app/ui/dmp/editor/dynamic-fields-project/dynamic-fields-project.component.scss diff --git a/dmp-frontend/src/app/ui/dmp/editor/dynamic-fields-project/dynamic-fields-project.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dynamic-fields-project/dynamic-fields-project.component.ts new file mode 100644 index 000000000..9fec6e630 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/dynamic-fields-project/dynamic-fields-project.component.ts @@ -0,0 +1,32 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormArray, FormGroup } from '@angular/forms'; +import { DmpDynamicFieldDependency } from '../../../../core/model/dmp/dmp-dynamic-field-dependency'; + +@Component({ + selector: 'app-dynamic-fields-project', + templateUrl: 'dynamic-fields-project.component.html', + styleUrls: ['./dynamic-fields-project.component.scss'] +}) +export class DynamicFieldsProjectComponent implements OnInit { + + @Input() + formGroup: FormGroup; + + ngOnInit(): void { + } + + findDependencies(id: number) { + const formGroupDependencies: Array = new Array(); + const dynamicFieldDependency: DmpDynamicFieldDependency[] = (this.formGroup.get('dynamicFields')).at(id).get('dependencies').value; + if (dynamicFieldDependency.length > 0) { + dynamicFieldDependency.forEach(item => { + const length = (this.formGroup.get('dynamicFields')).length; + for (let i = 0; i < length; i++) { + const formGroup = (this.formGroup.get('dynamicFields')).at(i); + if (formGroup.get('id').value === item.id) { formGroupDependencies.push(formGroup); } + } + }); + } + return formGroupDependencies; + } +} diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-checkbox/dynamic-field-checkbox.css b/dmp-frontend/src/app/ui/dmp/invitation/accepted/dmp-invitation-accepted.component.html similarity index 100% rename from dmp-frontend/src/app/form/dynamic-fields/dynamic-field-checkbox/dynamic-field-checkbox.css rename to dmp-frontend/src/app/ui/dmp/invitation/accepted/dmp-invitation-accepted.component.html diff --git a/dmp-frontend/src/app/ui/dmp/invitation/accepted/dmp-invitation-accepted.component.ts b/dmp-frontend/src/app/ui/dmp/invitation/accepted/dmp-invitation-accepted.component.ts new file mode 100644 index 000000000..8441d4d6d --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/invitation/accepted/dmp-invitation-accepted.component.ts @@ -0,0 +1,31 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../core/common/base/base.component'; +import { DmpInvitationService } from '../../../../core/services/dmp/dmp-invitation.service'; + +@Component({ + selector: 'app-dmp-invitation-accepted-component', + templateUrl: 'dmp-invitation-accepted.component.html', + +}) +export class InvitationAcceptedComponent extends BaseComponent implements OnInit { + constructor( + private dmpInvitationService: DmpInvitationService, + private route: ActivatedRoute, + private router: Router + ) { super(); } + + ngOnInit(): void { + this.route.params + .pipe(takeUntil(this._destroyed)) + .subscribe(params => { + const id = params['id']; + this.dmpInvitationService.exchange(id) + .pipe(takeUntil(this._destroyed)) + .subscribe(result => { + this.router.navigate(['plans/edit/' + result]); + }); + }); + } +} diff --git a/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation.component.html b/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation.component.html new file mode 100644 index 000000000..69ca127ac --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation.component.html @@ -0,0 +1,13 @@ +
+

{{'INVITATION-EDITOR.TITLE' | translate}} {{data.dmpName}}

+
+ + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+ +
+
+
diff --git a/dmp-frontend/src/app/form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.scss b/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation.component.scss similarity index 100% rename from dmp-frontend/src/app/form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.scss rename to dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation.component.scss diff --git a/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation.component.ts b/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation.component.ts new file mode 100644 index 000000000..8a083a78b --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation.component.ts @@ -0,0 +1,76 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../core/common/base/base.component'; +import { DmpInvitation } from '../../../core/model/dmp/invitation/dmp-invitation'; +import { DmpInvitationUser } from '../../../core/model/dmp/invitation/dmp-invitation-user'; +import { DmpInvitationUserCriteria } from '../../../core/query/dmp/dmp-invitation-user-criteria'; +import { DmpInvitationService } from '../../../core/services/dmp/dmp-invitation.service'; +import { MultipleAutoCompleteConfiguration } from '../../../library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { RequestItem } from '../../../core/query/request-item'; + +@Component({ + selector: 'app-invitation-component', + templateUrl: 'dmp-invitation.component.html', +}) +export class DmpInvitationDialogComponent extends BaseComponent implements OnInit { + + public formGroup: FormGroup; + public filteredUsersAsync = false; + public filteredUsers: DmpInvitationUser[]; + + usersAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = { + filterFn: this.filterUsers.bind(this), + initialItems: (excludedItems: any[]) => this.filterUsers('').map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1)), + displayFn: (item) => item.name, + titleFn: (item) => item.name, + loadDataOnStart: true + }; + + constructor( + public invitationService: DmpInvitationService, + public route: ActivatedRoute, + public router: Router, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any + ) { super(); } + + ngOnInit(): void { + const invitation = new DmpInvitation(); + invitation.dataManagementPlan = this.data.dmpId; + this.formGroup = invitation.buildForm(); + } + + + send(value: any) { + this.invitationService.inviteDmpInvitationUsers(this.formGroup.value) + .pipe(takeUntil(this._destroyed)) + .subscribe( + null, null, () => this.dialogRef.close() + ); + } + + filterUsers(value: string): Observable { + this.filteredUsers = undefined; + + this.filteredUsersAsync = true; + const request = new RequestItem(); + request.criteria = { like: value }; + return this.invitationService.getDmpInvitationUsers(request) + .pipe(takeUntil(this._destroyed)); + // .subscribe(items => { + // this.filteredUsers = new JsonSerializer(DmpInvitationUser).fromJSONArray(items); + // if (!this.filteredUsers || this.filteredUsers.length === 0) { + // const user = new DmpInvitationUser(); + // user.email = value; + // user.name = value; + // this.filteredUsers.push(user); + // } + // this.filteredUsersAsync = false; + // }); + } +} + diff --git a/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.html b/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.html new file mode 100644 index 000000000..368208d99 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.html @@ -0,0 +1,19 @@ +
+ + + +

{{'CRITERIA.FILTERS'| translate}}

+
+
+
+ + + {{baseErrorModel['Criteria.like']}} + + + + + +
+
+
diff --git a/dmp-frontend/src/app/shared/components/criteria/data-management-plan/dmp-criteria.component.scss b/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.scss similarity index 100% rename from dmp-frontend/src/app/shared/components/criteria/data-management-plan/dmp-criteria.component.scss rename to dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.scss diff --git a/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.ts b/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.ts new file mode 100644 index 000000000..508c0ebc5 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.ts @@ -0,0 +1,81 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormBuilder, FormControl } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { takeUntil } from 'rxjs/operators'; +import { ValidationErrorModel } from '../../../../common/forms/validation/error-model/validation-error-model'; +import { ProjectModel } from '../../../../core/model/project/project'; +import { DmpCriteria } from '../../../../core/query/dmp/dmp-criteria'; +import { ProjectCriteria } from '../../../../core/query/project/project-criteria'; +import { ProjectService } from '../../../../core/services/project/project.service'; +import { MultipleAutoCompleteConfiguration } from '../../../../library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { RequestItem } from '../../../../core/query/request-item'; +import { BaseCriteriaComponent } from '../../../misc/criteria/base-criteria.component'; + +@Component({ + selector: 'app-dmp-criteria-component', + templateUrl: './dmp-criteria.component.html', + styleUrls: ['./dmp-criteria.component.scss'], +}) +export class DmpCriteriaComponent extends BaseCriteriaComponent implements OnInit { + + @Input() showProject: boolean; + filteringProjectsAsync = false; + filteredProjects: ProjectModel[]; + public formGroup = new FormBuilder().group({ + like: new FormControl(), + projects: new FormControl() + }); + projectAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = { + filterFn: this.filterProject.bind(this), + initialItems: (excludedItems: any[]) => this.filterProject('').map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1)), + displayFn: (item) => item['label'], + titleFn: (item) => item['label'], + //mapFn: (item) => new JsonSerializer().fromJSONArray(item, ProjectReference).map(item => item.toDropdownList()), + loadDataOnStart: true + }; + + constructor( + public language: TranslateService, + public projectService: ProjectService, + public formBuilder: FormBuilder + ) { + super(new ValidationErrorModel()); + } + + ngOnInit() { + super.ngOnInit(); + + this.formGroup.get('projects').valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => this.controlModified()); + this.formGroup.get('like').valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => this.controlModified()); + //if (this.criteria == null) { this.criteria = new DataManagementPlanCriteria(); } + } + + setCriteria(criteria: DmpCriteria): void { + this.formGroup.get('like').patchValue(criteria.like); + this.formGroup.get('projects').patchValue(criteria.projects); + } + + onCallbackError(error: any) { + this.setErrorModel(error.error); + } + + controlModified(): void { + this.clearErrorModel(); + if (this.refreshCallback != null && + (this.formGroup.get('like').value == null || this.formGroup.get('like').value.length === 0 || this.formGroup.get('like').value.length > 2) + ) { + this.refreshCallback(); + } + } + + filterProject(query: string) { + const projectRequestItem: RequestItem = new RequestItem(); + projectRequestItem.criteria = new ProjectCriteria(); + projectRequestItem.criteria.like = query; + return this.projectService.get(projectRequestItem); + } +} diff --git a/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.html b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.html new file mode 100644 index 000000000..68de193bc --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.html @@ -0,0 +1,88 @@ +
+

{{'DMP-LISTING.TITLE' | translate}} {{titlePrefix}}

+ + + + + + + + + {{'DMP-LISTING.COLUMNS.NAME' | translate}} + {{row.label}} + + + + + {{'DMP-LISTING.COLUMNS.PROJECT' | + translate}} + {{row.project}} + + + + + {{'DMP-LISTING.COLUMNS.STATUS' | translate}} + {{enumUtils.toDmpStatusString(row.status)}} + + + + + {{'DMP-LISTING.COLUMNS.CREATION-TIME' | translate}} + {{row.creationTime | date:'shortDate'}} + + + + + {{'DMP-LISTING.COLUMNS.ORGANISATIONS' | translate}} + {{row.organisations}} + + + + + {{'DMP-LISTING.COLUMNS.LATEST_VERSION' | translate}} + {{row.version}} + + + + + {{'DMP-LISTING.COLUMNS.DATASETS' | translate}} + + + + + + + {{'DMP-LISTING.COLUMNS.ACTIONS' | translate}} + + + + + + + + + + + + + + + + + + + + +
diff --git a/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.scss b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.scss new file mode 100644 index 000000000..a2ac7d5ea --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.scss @@ -0,0 +1,26 @@ +.dmp-listing { + + .mat-card { + margin: 1em 0; + } + + .mat-row { + cursor: pointer; + } + + mat-row:hover { + background-color: lightgray; + } + + mat-row:nth-child(odd) { + background-color: #eef0fb; + } + + .mat-fab-bottom-right { + top: auto !important; + right: 20px !important; + bottom: 10px !important; + left: auto !important; + position: fixed !important; + } +} diff --git a/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts new file mode 100644 index 000000000..578c392ca --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts @@ -0,0 +1,192 @@ +import { DataSource } from '@angular/cdk/table'; +import { Component, OnInit, ViewChild } from '@angular/core'; +import { MatDialog, MatPaginator, MatSort } from '@angular/material'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../core/common/base/base.component'; +import { DmpListingModel } from '../../../core/model/dmp/dmp-listing'; +import { DmpCriteria } from '../../../core/query/dmp/dmp-criteria'; +import { DmpService } from '../../../core/services/dmp/dmp.service'; +import { EnumUtils } from '../../../core/services/utilities/enum-utils.service'; +import { DataTableRequest } from '../../../core/model/data-table/data-table-request'; +import { BreadcrumbItem } from '../../misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '../../misc/breadcrumb/definition/IBreadCrumbComponent'; +import { DmpInvitationDialogComponent } from '../invitation/dmp-invitation.component'; +import { DmpCriteriaComponent } from './criteria/dmp-criteria.component'; +import { ProjectModel } from '../../../core/model/project/project'; + +@Component({ + selector: 'app-dmp-listing-component', + templateUrl: 'dmp-listing.component.html', + styleUrls: ['./dmp-listing.component.scss'], +}) +export class DmpListingComponent extends BaseComponent implements OnInit, IBreadCrumbComponent { + + @ViewChild(MatPaginator) _paginator: MatPaginator; + @ViewChild(MatSort) sort: MatSort; + @ViewChild(DmpCriteriaComponent) criteria: DmpCriteriaComponent; + + breadCrumbs: Observable = Observable.of([]); + dataSource: DmpDataSource | null; + displayedColumns: String[] = ['name', 'project', 'status', 'creationTime', 'organisations', 'version', 'datasets', 'actions']; + itemId: string; + projectId: string; + showProject: boolean; + titlePrefix: string; + constructor( + private dmpService: DmpService, + private router: Router, + private route: ActivatedRoute, + private dialog: MatDialog, + public enumUtils: EnumUtils + ) { + super(); + } + + ngOnInit() { + this.route.params + .pipe(takeUntil(this._destroyed)) + .subscribe(async params => { + let projectLabel; + if (params['projectId']) { + this.projectId = params['projectId']; + this.showProject = false; + const project: ProjectModel = { + id: this.projectId + } + this.criteria.setCriteria({ like: null, projects: [project], groupIds: null, allVersions: false }); + this.refresh(); + projectLabel = this.route.snapshot.queryParams.projectLabel; + this.breadCrumbs = Observable.of([{ parentComponentName: 'ProjectEditorComponent', label: projectLabel, url: '/projects/edit/' + this.projectId }]); + this.criteria.setRefreshCallback(() => this.refresh()); + } else { + this.itemId = params['groupId']; + this.showProject = true; + const breadCrumbs = []; + + if (this.itemId) { + const dmplabel = this.route.snapshot.queryParams.groupLabel; + breadCrumbs.push( + { parentComponentName: null, label: 'DMPs', url: '/plans' }, + ); + } + //else breadCrumbs.push({ parentComponentName: null, label: 'DMPs', url: "/plans" }) + this.breadCrumbs = Observable.of(breadCrumbs); + + this.criteria.setCriteria(this.getDefaultCriteria()); + this.refresh(); + this.criteria.setRefreshCallback(() => this.refresh()); + } + + if (this.projectId != null) { + if (projectLabel !== undefined) { + this.titlePrefix = 'for ' + projectLabel; + } + } + }); + + } + + refresh() { + this.dataSource = new DmpDataSource(this.dmpService, this._paginator, this.sort, this.criteria, this.itemId); + } + + rowClick(rowId: String) { + this.router.navigate(['/plans/edit/' + rowId]); + } + + addDataset(rowId: String) { + this.router.navigate(['/datasets/new/' + rowId]); + } + + showDatasets(rowId: String, rowLabel: String) { + this.router.navigate(['/datasets/dmp/' + rowId, { dmpLabel: rowLabel }]); + } + + viewVersions(rowId: String, rowLabel: String) { + this.router.navigate(['/plans/versions/' + rowId], { queryParams: { groupLabel: rowLabel } }); + } + + getDefaultCriteria(): DmpCriteria { + const defaultCriteria = new DmpCriteria(); + return defaultCriteria; + } + + openShareDialog(rowId: any, rowName: any) { + const dialogRef = this.dialog.open(DmpInvitationDialogComponent, { + // height: '250px', + // width: '700px', + data: { + dmpId: rowId, + dmpName: rowName + } + }); + } +} + +export class DmpDataSource extends DataSource { + + totalCount = 0; + + constructor( + private _service: DmpService, + private _paginator: MatPaginator, + private _sort: MatSort, + private _criteria: DmpCriteriaComponent, + private itemId + ) { + super(); + } + + connect(): Observable { + const displayDataChanges = [ + this._paginator.page + ]; + + return Observable.merge(...displayDataChanges) + .startWith(null) + .switchMap(() => { + const startIndex = this._paginator.pageIndex * this._paginator.pageSize; + let fields: Array = new Array(); + if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; } + const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); + request.criteria = this._criteria.formGroup.value; + if (this.itemId) { + request.criteria.groupIds = [this.itemId]; + request.criteria.allVersions = true; + } + return this._service.getPaged(request); + }) + /*.catch((error: any) => { + this._snackBar.openFromComponent(SnackBarNotificationComponent, { + data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService }, + duration: 3000, + extraClasses: ['snackbar-warning'] + }); + return Observable.of(null); + })*/ + .map(result => { + result.data = result.data; + return result; + }) + .map(result => { + return result; + }) + .map(result => { + if (!result) { return []; } + if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; } + return result.data.map(item => { + item['datasets'].map(dmp => { + dmp.url = 'datasets/edit/' + dmp.url; + dmp.all = 'datasets/dmp/' + item.id; + return dmp; + }); + return item; + }); + }); + } + + disconnect() { + } +} diff --git a/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard-editor.model.ts b/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard-editor.model.ts new file mode 100644 index 000000000..b182211a5 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard-editor.model.ts @@ -0,0 +1,149 @@ +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; +import { BackendErrorValidator } from "../../../common/forms/validation/custom-validator"; +import { ValidationErrorModel } from "../../../common/forms/validation/error-model/validation-error-model"; +import { ValidationContext } from "../../../common/forms/validation/validation-context"; +import { Status } from "../../../core/common/enum/Status"; +import { DmpProfile, DmpProfileDefinition } from "../../../core/model/dmp-profile/dmp-profile"; +import { DmpModel } from "../../../core/model/dmp/dmp"; +import { DmpDynamicField } from "../../../core/model/dmp/dmp-dynamic-field"; +import { DmpDynamicFieldDependency } from "../../../core/model/dmp/dmp-dynamic-field-dependency"; +import { OrganizationModel } from "../../../core/model/organisation/organization"; +import { ProjectModel } from "../../../core/model/project/project"; +import { ResearcherModel } from "../../../core/model/researcher/researcher"; +import { UserModel } from "../../../core/model/user/user"; +import { ValidJsonValidator } from "../../../library/auto-complete/auto-complete-custom-validator"; + +export class DmpWizardEditorModel { + public id: string; + public label: string; + public groupId: String; + public profile: String; + public version: number; + public lockable: boolean; + public creator: UserModel; + public status: Status = Status.Active; + public description: String; + public project: ProjectModel; + public organisations: OrganizationModel[] = []; + public researchers: ResearcherModel[] = []; + public profiles: DmpProfile[] = []; + public associatedUsers: UserModel[] = []; + public definition: DmpProfileDefinition; + public dynamicFields: Array = []; + public errorModel: ValidationErrorModel = new ValidationErrorModel(); + + fromModel(item: DmpModel): DmpWizardEditorModel { + this.id = item.id; + this.profile = item.profile; + this.label = item.label; + this.groupId = item.groupId; + this.version = item.version; + this.status = item.status; + this.lockable = item.lockable; + this.description = item.description; + this.project = item.project; + this.organisations = item.organisations; + this.researchers = item.researchers; + this.profiles = item.profiles; + this.associatedUsers = item.associatedUsers; + if (item.definition) { this.definition = item.definition; } + if (item.dynamicFields) { item.dynamicFields.map(x => this.dynamicFields.push(new DmpDynamicFieldEditorModel().fromModel(x))); } + this.creator = item.creator; + return this; + } + + buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { + if (context == null) { context = this.createValidationContext(); } + + const formGroup = new FormBuilder().group({ + id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators], + profile: [{ value: this.profile, disabled: disabled }, context.getValidation('profile').validators], + label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators], + groupId: [{ value: this.groupId, disabled: disabled }, context.getValidation('groupId').validators], + version: [{ value: this.version, disabled: disabled }, context.getValidation('version').validators], + status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators], + description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators], + project: [{ value: this.project, disabled: disabled }, context.getValidation('project').validators], + organisations: [{ value: this.organisations, disabled: disabled }, context.getValidation('organisations').validators], + researchers: [{ value: this.researchers, disabled: disabled }, context.getValidation('researchers').validators], + profiles: [{ value: this.profiles, disabled: disabled }, context.getValidation('profiles').validators], + associatedUsers: [{ value: this.associatedUsers, disabled: disabled }, context.getValidation('associatedUsers').validators], + }); + + const dynamicFields = new Array(); + if (this.dynamicFields) { this.dynamicFields.forEach(item => dynamicFields.push(item.buildForm())); } + + formGroup.addControl('dynamicFields', new FormBuilder().array(dynamicFields)); + + return formGroup; + } + + createValidationContext(): ValidationContext { + const baseContext: ValidationContext = new ValidationContext(); + baseContext.validation.push({ key: 'id', validators: [BackendErrorValidator(this.errorModel, 'id')] }); + baseContext.validation.push({ key: 'profile', validators: [BackendErrorValidator(this.errorModel, 'profile')] }); + baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'label')] }); + baseContext.validation.push({ key: 'groupId', validators: [BackendErrorValidator(this.errorModel, 'groupId')] }); + baseContext.validation.push({ key: 'version', validators: [BackendErrorValidator(this.errorModel, 'version')] }); + baseContext.validation.push({ key: 'status', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'status')] }); + baseContext.validation.push({ key: 'description', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'description')] }); + baseContext.validation.push({ key: 'project', validators: [Validators.required, ValidJsonValidator, BackendErrorValidator(this.errorModel, 'project')] }); + baseContext.validation.push({ key: 'organisations', validators: [BackendErrorValidator(this.errorModel, 'organisations')] }); + baseContext.validation.push({ key: 'researchers', validators: [BackendErrorValidator(this.errorModel, 'researchers')] }); + baseContext.validation.push({ key: 'profiles', validators: [Validators.required, ValidJsonValidator, BackendErrorValidator(this.errorModel, 'profiles')] }); + baseContext.validation.push({ key: 'associatedUsers', validators: [BackendErrorValidator(this.errorModel, 'associatedUsers')] }); + + return baseContext; + } +} + +export class DmpDynamicFieldEditorModel { + + public id: string; + public name: string; + public required: boolean; + public queryProperty; + public value: string; + public dependencies: Array = []; + + fromModel(item: DmpDynamicField): DmpDynamicFieldEditorModel { + this.id = item.id; + this.name = item.name; + this.required = item.required; + this.value = item.value; + this.queryProperty = item.queryProperty; + if (item.dependencies) { item.dependencies.map(x => this.dependencies.push(new DmpDynamicFieldDependencyEditorModel().fromModel(x))); } + return this; + } + + buildForm(): FormGroup { + const builder = new FormBuilder(); + const formGroup = builder.group({ + id: [this.id], + name: [this.name], + required: [this.required], + value: [this.value], + queryProperty: [this.queryProperty], + dependencies: [this.dependencies] + }); + return formGroup; + } +} + +export class DmpDynamicFieldDependencyEditorModel { + public id: string; + public queryProperty: string; + + fromModel(item: DmpDynamicFieldDependency): DmpDynamicFieldDependencyEditorModel { + this.id = item.id; + this.queryProperty = item.queryProperty; + return this; + } + + buildForm(): FormGroup { + return new FormBuilder().group({ + id: [this.id], + queryProperty: [this.queryProperty] + }); + } +} \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard.component.html b/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard.component.html new file mode 100644 index 000000000..50f20a3f0 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard.component.html @@ -0,0 +1,19 @@ +
+ + + {{'DMP-WIZARD.FIRST-STEP.DMP' | translate}} + + + + + {{'DMP-WIZARD.FIRST-STEP.DATASETS' | translate}} + + + + +
diff --git a/dmp-frontend/src/app/dmps/wizard/dmp-wizard.component.scss b/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard.component.scss similarity index 100% rename from dmp-frontend/src/app/dmps/wizard/dmp-wizard.component.scss rename to dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard.component.scss diff --git a/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard.component.ts b/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard.component.ts new file mode 100644 index 000000000..dab01bf0e --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard.component.ts @@ -0,0 +1,93 @@ +import { Component, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { MatSnackBar } from '@angular/material'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../core/common/base/base.component'; +import { DmpModel } from '../../../core/model/dmp/dmp'; +import { DmpService } from '../../../core/services/dmp/dmp.service'; +import { SnackBarNotificationComponent } from '../../../library/notification/snack-bar/snack-bar-notification.component'; +import { BreadcrumbItem } from '../../misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '../../misc/breadcrumb/definition/IBreadCrumbComponent'; +import { DmpWizardEditorModel } from './dmp-wizard-editor.model'; + +@Component({ + selector: 'app-dmp-wizard-component', + templateUrl: 'dmp-wizard.component.html', + styleUrls: ['./dmp-wizard.component.scss'], +}) +export class DmpWizardComponent extends BaseComponent implements OnInit, IBreadCrumbComponent { + + breadCrumbs: Observable; + itemId: string; + dmp: DmpWizardEditorModel; + formGroup: FormGroup; + isClone: boolean; + + constructor( + private dmpService: DmpService, + private language: TranslateService, + private snackBar: MatSnackBar, + private route: ActivatedRoute, + private router: Router + ) { super(); } + + ngOnInit(): void { + + this.route.params + .pipe(takeUntil(this._destroyed)) + .subscribe((params: Params) => { + this.itemId = params['id']; + this.dmpService.getSingle(this.itemId).map(data => data as DmpModel) + .pipe(takeUntil(this._destroyed)) + .subscribe(data => { + this.dmp = new DmpWizardEditorModel().fromModel(data); + this.isClone = this.route.snapshot.data.clone; + if (this.isClone === false) { this.dmp.version = this.dmp.version + 1; } + this.formGroup = this.dmp.buildForm(); + }); + }); + } + + + submit() { + if (this.isClone) { + this.dmpService.clone(this.formGroup.getRawValue(), this.itemId) + .pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) + ); + } else { + this.dmpService.newVersion(this.formGroup.getRawValue(), this.itemId) + .pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) + ); + } + } + + onCallbackSuccess(): void { + this.snackBar.openFromComponent(SnackBarNotificationComponent, { + data: { message: 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, + duration: 3000, + }); + this.router.navigate(['/plans']); + } + + onCallbackError(error: any) { + this.setErrorModel(error.error); + //this.validateAllFormFields(this.formGroup); + } + + public setErrorModel(errorModel: any) { + Object.keys(errorModel).forEach(item => { + // (this.dmp.errorModel)[item] = (errorModel)[item]; + }); + } + + +} diff --git a/dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.html b/dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.html new file mode 100644 index 000000000..f90ba27ad --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.html @@ -0,0 +1,63 @@ +
+
+ + +
+ + + {{baseErrorModel.label}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + {{baseErrorModel.project}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + {{errorModel.description}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + {{baseErrorModel.project}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + + {{baseErrorModel.organisations}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + {{baseErrorModel.project}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + + + + +

Associated Users

+ + person +
{{user.name}}
+
+
+
+
+
+
+
diff --git a/dmp-frontend/src/app/dmps/wizard/editor/dmp-wizard-editor.component.scss b/dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.scss similarity index 100% rename from dmp-frontend/src/app/dmps/wizard/editor/dmp-wizard-editor.component.scss rename to dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.scss diff --git a/dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.ts b/dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.ts new file mode 100644 index 000000000..33c692c52 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.ts @@ -0,0 +1,190 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { MatSnackBar } from '@angular/material'; +import { ActivatedRoute, Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../core/common/base/base.component'; +import { DatasetProfileModel } from '../../../../core/model/dataset/dataset-profile'; +import { ExternalSourceItemModel } from '../../../../core/model/external-sources/external-source-item'; +import { UserModel } from '../../../../core/model/user/user'; +import { BaseCriteria } from '../../../../core/query/base-criteria'; +import { DatasetProfileCriteria } from '../../../../core/query/dataset-profile/dataset-profile-criteria'; +import { ProjectCriteria } from '../../../../core/query/project/project-criteria'; +import { RequestItem } from '../../../../core/query/request-item'; +import { DmpService } from '../../../../core/services/dmp/dmp.service'; +import { ExternalSourcesService } from '../../../../core/services/external-sources/external-sources.service'; +import { ProjectService } from '../../../../core/services/project/project.service'; +import { MultipleAutoCompleteConfiguration } from '../../../../library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { SingleAutoCompleteConfiguration } from '../../../../library/auto-complete/single/single-auto-complete-configuration'; +import { SnackBarNotificationComponent } from '../../../../library/notification/snack-bar/snack-bar-notification.component'; +import { LanguageResolverService } from '../../../../services/language-resolver/language-resolver.service'; + +@Component({ + selector: 'app-dmp-wizard-editor-component', + templateUrl: 'dmp-wizard-editor.component.html', + styleUrls: ['./dmp-wizard-editor.component.scss'] +}) +export class DmpWizardEditorComponent extends BaseComponent implements OnInit { + + isNew = true; + @Input() formGroup: FormGroup = null; + + filteringOrganisationsAsync = false; + filteringResearchersAsync = false; + filteredProfilesAsync = false; + filteredOrganisations: ExternalSourceItemModel[]; + filteredResearchers: ExternalSourceItemModel[]; + filteredProfiles: DatasetProfileModel[]; + + projectAutoCompleteConfiguration: SingleAutoCompleteConfiguration; + profilesAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; + organisationsAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; + researchersAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; + createNewVersion; + associatedUsers: Array; + labelDisabled = false; + + constructor( + private dataManagementPlanService: DmpService, + private projectService: ProjectService, + private externalSourcesService: ExternalSourcesService, + private route: ActivatedRoute, + public snackBar: MatSnackBar, + public router: Router, + public language: TranslateService, + private _service: DmpService, + private languageResolverService: LanguageResolverService + ) { + super(); + } + + ngOnInit() { + + const projectRequestItem: RequestItem = new RequestItem(); + projectRequestItem.criteria = new ProjectCriteria(); + this.projectAutoCompleteConfiguration = { + filterFn: this.searchProject.bind(this.projectService), + initialItems: () => this.searchProject(''), + displayFn: (item) => item['label'], + titleFn: (item) => item['label'], + loadDataOnStart: true + }; + + this.profilesAutoCompleteConfiguration = { + filterFn: this.filterProfiles.bind(this), + initialItems: (excludedItems: any[]) => this.filterProfiles('').map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1)), + displayFn: (item) => item['label'], + titleFn: (item) => item['label'], + //mapFn: (item) => new JsonSerializer().fromJSONArray(item, ProjectReference).map(item => item.toDropdownList()), + loadDataOnStart: true + }; + + this.organisationsAutoCompleteConfiguration = { + filterFn: this.filterOrganisations.bind(this), + initialItems: (excludedItems: any[]) => this.filterOrganisations('').map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1)), + displayFn: (item) => item['name'], + titleFn: (item) => item['name'], + loadDataOnStart: true + }; + + this.researchersAutoCompleteConfiguration = { + filterFn: this.filterResearchers.bind(this), + initialItems: (excludedItems: any[]) => this.filterResearchers('').map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1)), + displayFn: (item) => item['name'], + titleFn: (item) => item['name'], + loadDataOnStart: true + }; + + const organisationRequestItem: RequestItem = new RequestItem(); + organisationRequestItem.criteria = new BaseCriteria(); + + this.route.data + .pipe(takeUntil(this._destroyed)) + .subscribe(value => { + if (value.clone === false && this.formGroup.get('label').value) { + this.labelDisabled = true; + } + this.formGroup.controls['version'].disable(); + }); + } + + searchProject(query: string) { + const projectRequestItem: RequestItem = new RequestItem(); + projectRequestItem.criteria = new ProjectCriteria(); + projectRequestItem.criteria.like = query; + return this.projectService.getWithExternal(projectRequestItem); + } + + formSubmit(): void { + //this.touchAllFormFields(this.formGroup); + if (!this.isFormValid()) { return; } + this.onSubmit(); + } + + public isFormValid() { + return this.formGroup.valid; + } + + onSubmit(): void { + this.dataManagementPlanService.createDmp(this.formGroup.getRawValue()) + .pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) + ); + } + + onCallbackSuccess(): void { + this.snackBar.openFromComponent(SnackBarNotificationComponent, { + data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, + duration: 3000, + }); + this.router.navigate(['/plans']); + } + + onCallbackError(error: any) { + this.setErrorModel(error.error); + //this.validateAllFormFields(this.formGroup); + } + + public setErrorModel(errorModel: BaseErrorModel) { + Object.keys(errorModel).forEach(item => { + // (this.dataManagementPlan.errorModel)[item] = (errorModel)[item]; + }); + } + + public cancel(): void { + this.router.navigate(['/plans']); + } + + filterOrganisations(value: string): Observable { + + this.filteredOrganisations = undefined; + this.filteringOrganisationsAsync = true; + + return this.externalSourcesService.searchDMPOrganizations(value); + } + + filterResearchers(value: string): Observable { + + this.filteredResearchers = undefined; + this.filteringResearchersAsync = true; + + return this.externalSourcesService.searchDMPResearchers({ criteria: { name: value, like: null } }); + } + + filterProfiles(value: string): Observable { + + this.filteredProfiles = undefined; + this.filteredProfilesAsync = true; + + const request = new RequestItem(); + const criteria = new DatasetProfileCriteria(); + criteria.like = value; + request.criteria = criteria; + return this._service.searchDMPProfiles(request); + } + +} diff --git a/dmp-frontend/src/app/dmps/wizard/listing/dataset-wizard-listing.component.html b/dmp-frontend/src/app/ui/dmp/wizard/listing/dmp-wizard-dataset-listing.component.html similarity index 100% rename from dmp-frontend/src/app/dmps/wizard/listing/dataset-wizard-listing.component.html rename to dmp-frontend/src/app/ui/dmp/wizard/listing/dmp-wizard-dataset-listing.component.html diff --git a/dmp-frontend/src/app/dmp-profiles/dmp-profile-listing/dmp-profile-listing.component.scss b/dmp-frontend/src/app/ui/dmp/wizard/listing/dmp-wizard-dataset-listing.component.scss similarity index 100% rename from dmp-frontend/src/app/dmp-profiles/dmp-profile-listing/dmp-profile-listing.component.scss rename to dmp-frontend/src/app/ui/dmp/wizard/listing/dmp-wizard-dataset-listing.component.scss diff --git a/dmp-frontend/src/app/ui/dmp/wizard/listing/dmp-wizard-dataset-listing.component.ts b/dmp-frontend/src/app/ui/dmp/wizard/listing/dmp-wizard-dataset-listing.component.ts new file mode 100644 index 000000000..4ba2478f5 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/wizard/listing/dmp-wizard-dataset-listing.component.ts @@ -0,0 +1,80 @@ +import { SelectionModel } from '@angular/cdk/collections'; +import { Component, Input, OnInit, ViewChild } from '@angular/core'; +import { FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms'; +import { MatPaginator, MatSnackBar, MatSort } from '@angular/material'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../core/common/base/base.component'; +import { DataTableRequest } from '../../../../core/model/data-table/data-table-request'; +import { DatasetListingModel } from '../../../../core/model/dataset/dataset-listing'; +import { DatasetCriteria } from '../../../../core/query/dataset/dataset-criteria'; +import { DatasetService } from '../../../../core/services/dataset/dataset.service'; +import { DmpService } from '../../../../core/services/dmp/dmp.service'; +import { DatasetCriteriaComponent } from '../../../dataset/listing/criteria/dataset-criteria.component'; + +@Component({ + selector: 'app-dmp-wizard-dataset-listing-component', + templateUrl: 'dmp-wizard-dataset-listing.component.html', + styleUrls: ['./dmp-wizard-dataset-listing.component.scss'], +}) +export class DmpWizardDatasetListingComponent extends BaseComponent implements OnInit { + + @ViewChild(MatPaginator) _paginator: MatPaginator; + @ViewChild(MatSort) sort: MatSort; + @ViewChild(DatasetCriteriaComponent) criteria: DatasetCriteriaComponent; + + + titlePrefix: String; + datasets: DatasetListingModel[] = []; + + @Input() dmpId: String; + @Input() formGroup: FormGroup; + selection = new SelectionModel(true, []); + + statuses = [ + { value: '0', viewValue: 'Active' }, + { value: '1', viewValue: 'Inactive' } + ]; + + constructor( + private datasetService: DatasetService, + private router: Router, + private languageService: TranslateService, + public snackBar: MatSnackBar, + public route: ActivatedRoute, + public dmpService: DmpService + ) { + super(); + } + + + ngOnInit() { + this.route.params + .pipe(takeUntil(this._destroyed)) + .subscribe((params: Params) => { + if (this.dmpId != null) { + if (params['dmpLabel'] !== undefined) { + this.titlePrefix = 'for ' + params['dmpLabel']; + } + } + }); + const request: DataTableRequest = new DataTableRequest(null, null, null); + request.criteria = new DatasetCriteria(); + request.criteria.dmpIds = [this.dmpId]; + this.datasetService.getPaged(request) + .pipe(takeUntil(this._destroyed)) + .subscribe(items => { + this.datasets = items.data; + }); + this.formGroup.addControl('datasets', new FormBuilder().array(new Array())); + } + + selectionChanged(event, selectedItems) { + this.formGroup.removeControl('datasets'); + this.formGroup.addControl('datasets', new FormBuilder().array(new Array())); + selectedItems.selectedOptions.selected.forEach(element => { + (this.formGroup.get('datasets')).push(new FormBuilder().group({ id: element.value })); + }); + } +} diff --git a/dmp-frontend/src/app/ui/explore-dataset/explore-dataset-listing.component.html b/dmp-frontend/src/app/ui/explore-dataset/explore-dataset-listing.component.html new file mode 100644 index 000000000..126c85869 --- /dev/null +++ b/dmp-frontend/src/app/ui/explore-dataset/explore-dataset-listing.component.html @@ -0,0 +1,85 @@ +
+

{{'DATASET-PUBLIC-LISTING.TITLE' | translate}} {{titlePrefix}}

+
+
+ +
+
+
+ + + + + + {{'DATASET-LISTING.COLUMNS.NAME' | translate}} + {{row.label}} + + + + + {{'DATASET-LISTING.COLUMNS.PROJECT' | + translate}} + {{row.project}} + + + + + {{'DATASET-LISTING.COLUMNS.PROFILE' + | translate}} + {{row.profile}} + + + + + + + + + + + + + + + + + {{'DATASET-LISTING.COLUMNS.DESCRIPTION' | translate}} + {{row.description}} + + + + + {{'DATASET-LISTING.COLUMNS.CREATED' | + translate}} + {{row.created | date:'shortDate'}} + + + + + + + + + + + + + +
+ +
+
+
diff --git a/dmp-frontend/src/app/datasets/dataset-public/dataset-public-listing.component.scss b/dmp-frontend/src/app/ui/explore-dataset/explore-dataset-listing.component.scss similarity index 100% rename from dmp-frontend/src/app/datasets/dataset-public/dataset-public-listing.component.scss rename to dmp-frontend/src/app/ui/explore-dataset/explore-dataset-listing.component.scss diff --git a/dmp-frontend/src/app/ui/explore-dataset/explore-dataset-listing.component.ts b/dmp-frontend/src/app/ui/explore-dataset/explore-dataset-listing.component.ts new file mode 100644 index 000000000..e68027e8e --- /dev/null +++ b/dmp-frontend/src/app/ui/explore-dataset/explore-dataset-listing.component.ts @@ -0,0 +1,147 @@ +import { DataSource } from '@angular/cdk/table'; +import { Component, OnInit, ViewChild } from '@angular/core'; +import { MatPaginator, MatSnackBar, MatSort, PageEvent } from '@angular/material'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../core/common/base/base.component'; +import { DatasetListingModel } from '../../core/model/dataset/dataset-listing'; +import { DatasetCriteria } from '../../core/query/dataset/dataset-criteria'; +import { ExploreDatasetCriteriaModel } from '../../core/query/explore-dataset/explore-dataset-criteria'; +import { DatasetService } from '../../core/services/dataset/dataset.service'; +import { DmpService } from '../../core/services/dmp/dmp.service'; +import { DataTableRequest } from '../../core/model/data-table/data-table-request'; + + +@Component({ + selector: 'app-explore-dataset-listing-component', + templateUrl: 'explore-dataset-listing.component.html', + styleUrls: ['./explore-dataset-listing.component.scss'], +}) +export class ExploreDatasetListingComponent extends BaseComponent implements OnInit { + + @ViewChild(MatPaginator) _paginator: MatPaginator; + @ViewChild(MatSort) sort: MatSort; + criteria: ExploreDatasetCriteriaModel; + + dataSource: DatasetDataSource | null; + displayedColumns: String[] = ['label', 'project', 'profile', 'description', 'created']; + pageEvent: PageEvent; + titlePrefix: String; + dmpId: string; + + constructor( + private datasetService: DatasetService, + private router: Router, + private languageService: TranslateService, + public snackBar: MatSnackBar, + public route: ActivatedRoute, + public dmpService: DmpService + ) { + super(); + } + + ngOnInit() { + + this.route.params + .pipe(takeUntil(this._destroyed)) + .subscribe(async (params: Params) => { + this.dmpId = params['dmpId']; + this.refresh(); + if (this.dmpId != null) { + const dmp = await this.dmpService.getSingle(this.dmpId).toPromise(); + if (params['dmpLabel'] !== undefined) { + this.titlePrefix = 'for ' + params['dmpLabel']; + } + } + }); + } + + onCriteriaChange(event: ExploreDatasetCriteriaModel) { + //console.log(event) + this.criteria = event; + this.refresh(); + } + + refresh() { + this.dataSource = new DatasetDataSource(this.datasetService, this._paginator, this.sort, this.languageService, this.snackBar, this.criteria, this.dmpId); + } + + rowClick(rowId: String) { + this.router.navigate(['/datasets/publicEdit/' + rowId]); + } + + getDefaultCriteria(dmpId: String): DatasetCriteria { + const defaultCriteria = new DatasetCriteria(); + if (dmpId != null) { + defaultCriteria.dmpIds.push(dmpId); + } + return defaultCriteria; + } + + makeItPublic(id: String) { + this.datasetService.makeDatasetPublic(id) + .pipe(takeUntil(this._destroyed)) + .subscribe(); + } +} + +export class DatasetDataSource extends DataSource { + + totalCount = 0; + + constructor( + private _service: DatasetService, + private _paginator: MatPaginator, + private _sort: MatSort, + private _languageService: TranslateService, + private _snackBar: MatSnackBar, + private _criteria: ExploreDatasetCriteriaModel, + private dmpId: String + ) { + super(); + + } + + connect(): Observable { + const displayDataChanges = [ + this._paginator.page + //this._sort.matSortChange + ]; + + + return Observable.merge(...displayDataChanges) + .startWith(null) + .switchMap(() => { + const startIndex = this._paginator.pageIndex * this._paginator.pageSize; + let fields: Array = new Array(); + if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; } + const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); + request.criteria = this._criteria; + //if (this.dmpId) request.criteria.allVersions = true; + return this._service.getPublicPaged(request); + }) + /*.catch((error: any) => { + this._snackBar.openFromComponent(SnackBarNotificationComponent, { + data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService }, + duration: 3000, + extraClasses: ['snackbar-warning'] + }); + //this._criteria.criteria.onCallbackError(error); + return Observable.of(null); + })*/ + .map(result => { + return result; + }) + .map(result => { + if (!result) { return []; } + if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; } + return result.data; + }); + } + + disconnect() { + // No-op + } +} diff --git a/dmp-frontend/src/app/ui/explore-dataset/explore-dataset.module.ts b/dmp-frontend/src/app/ui/explore-dataset/explore-dataset.module.ts new file mode 100644 index 000000000..c170d20a8 --- /dev/null +++ b/dmp-frontend/src/app/ui/explore-dataset/explore-dataset.module.ts @@ -0,0 +1,23 @@ +import { NgModule } from '@angular/core'; +import { CommonFormsModule } from '../../common/forms/common-forms.module'; +import { CommonUiModule } from '../../common/ui/common-ui.module'; +import { AutoCompleteModule } from '../../library/auto-complete/auto-complete.module'; +import { ExploreDatasetListingComponent } from './explore-dataset-listing.component'; +import { ExploreDatasetRoutingModule } from './explore-dataset.routing'; +import { ExploreDatasetFilterItemComponent } from './filters/explore-dataset-filter-item/explore-dataset-filter-item.component'; +import { ExploreDatasetFiltersComponent } from './filters/explore-dataset-filters.component'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule, + AutoCompleteModule, + ExploreDatasetRoutingModule + ], + declarations: [ + ExploreDatasetListingComponent, + ExploreDatasetFiltersComponent, + ExploreDatasetFilterItemComponent + ] +}) +export class ExploreDatasetModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/explore-dataset/explore-dataset.routing.ts b/dmp-frontend/src/app/ui/explore-dataset/explore-dataset.routing.ts new file mode 100644 index 000000000..fd9f14154 --- /dev/null +++ b/dmp-frontend/src/app/ui/explore-dataset/explore-dataset.routing.ts @@ -0,0 +1,19 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { ExploreDatasetListingComponent } from './explore-dataset-listing.component'; + +const routes: Routes = [ + { + path: '', + component: ExploreDatasetListingComponent, + data: { + breadcrumb: true + }, + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class ExploreDatasetRoutingModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/shared/components/facets/facet-search-component/facet-search-section.component.html b/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filter-item/explore-dataset-filter-item.component.html similarity index 100% rename from dmp-frontend/src/app/shared/components/facets/facet-search-component/facet-search-section.component.html rename to dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filter-item/explore-dataset-filter-item.component.html diff --git a/dmp-frontend/src/app/shared/components/facets/facet-search-component/facet-search-section.component.scss b/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filter-item/explore-dataset-filter-item.component.scss similarity index 100% rename from dmp-frontend/src/app/shared/components/facets/facet-search-component/facet-search-section.component.scss rename to dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filter-item/explore-dataset-filter-item.component.scss diff --git a/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filter-item/explore-dataset-filter-item.component.ts b/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filter-item/explore-dataset-filter-item.component.ts new file mode 100644 index 000000000..3490914bb --- /dev/null +++ b/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filter-item/explore-dataset-filter-item.component.ts @@ -0,0 +1,92 @@ +import { SelectionModel } from '@angular/cdk/collections'; +import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; +import { FormControl } from '@angular/forms'; +import { MatListOption, MatSelectionList } from '@angular/material'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../core/common/base/base.component'; + +@Component({ + selector: 'app-explore-dataset-filter-item-component', + templateUrl: './explore-dataset-filter-item.component.html', + styleUrls: ['./explore-dataset-filter-item.component.scss'] +}) +export class ExploreDatasetFilterItemComponent extends BaseComponent implements OnInit { + + @Input() + searchEnabled = false; + + @Input() + requestDelay = 200; + + @Input() + multipleSelect = true; + + @Input() + filterOptions: (value) => Observable; + + @Input() + options: Observable = Observable.of([]); + + @Input() + displayTitleFunc: (value) => string; + + @Input() + displayValueFunc: (value) => string; + + @Output() + selectedChanged = new EventEmitter(); + + @Output() + optionRemoved = new EventEmitter(); + + optionSearchControl = new FormControl(''); + + private selectedOptions: any[] = []; + + @ViewChild('optionsList') selectionList: MatSelectionList; + + constructor() { super(); } + + ngOnInit(): void { + if (!this.multipleSelect) { this.selectionList.selectedOptions = new SelectionModel(this.multipleSelect); } + this.optionSearchControl.valueChanges.debounceTime(this.requestDelay) + .distinctUntilChanged() + .pipe(takeUntil(this._destroyed)) + .subscribe(x => { if (this.filterOptions) { this.options = this.filterOptions(x); } }); + } + + public selectionChanged(event: any) { + const eventValue = event.option.value; + if (event.option.selected) { this.selectedOptions.push(eventValue); } + if (!event.option.selected) { + const index = this.selectedOptions.map(x => this.displayValue(x)).indexOf(this.displayValue(eventValue)); + this.selectedOptions.splice(index, 1); + } + this.selectedChanged.emit(event); + } + + public removeOption(project) { + const list = this.selectionList.selectedOptions.selected.map(x => x.value); + const indexOfProject = list.indexOf(project); + if (this.selectionList.selectedOptions.selected[indexOfProject]) { + this.selectionList.selectedOptions.selected[indexOfProject].selected = false; + this.selectionList.selectedOptions.selected.splice(indexOfProject, 1); + } + this.selectedOptions.splice(this.selectedOptions.map(x => this.displayValue(x)).indexOf(this.displayValue(project)), 1); + this.optionRemoved.emit(project); + } + + public isOptionSelected(value) { + return this.selectedOptions.map(x => this.displayValue(x)).indexOf(this.displayValue(value)) !== -1; + } + + displayLabel(value) { + return this.displayTitleFunc ? this.displayTitleFunc(value) : value; + } + + displayValue(value) { + return this.displayValueFunc ? this.displayValueFunc(value) : value; + } + +} diff --git a/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.html b/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.html new file mode 100644 index 000000000..309ef33b4 --- /dev/null +++ b/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.html @@ -0,0 +1,59 @@ + + + + + {{ 'FACET-SEARCH.FILTER' | translate }} + + +
+ + + +
+
+ + + + +
+
+ + + + {{ 'FACET-SEARCH.PROJECT-STATUS.TITLE' | translate }} + + + + + + + + + + {{ 'FACET-SEARCH.PROJECT.TITLE' | translate }} + + + + + + + + + + {{ 'FACET-SEARCH.PROFILES.TITLE' | translate }} + + + + + + + + + {{ 'FACET-SEARCH.DMP-ORGANISATIONS.TITLE' | translate }} + + + + + + +
diff --git a/dmp-frontend/src/app/shared/components/facets/facet-search.component.scss b/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.scss similarity index 100% rename from dmp-frontend/src/app/shared/components/facets/facet-search.component.scss rename to dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.scss diff --git a/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.ts b/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.ts new file mode 100644 index 000000000..313f19a0b --- /dev/null +++ b/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.ts @@ -0,0 +1,182 @@ +import { AfterViewInit, Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; +import { MatAccordion } from '@angular/material'; +import { ActivatedRoute } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { BaseComponent } from '../../../core/common/base/base.component'; +import { ProjectStateType } from '../../../core/common/enum/project-state-type'; +import { DatasetProfileModel } from '../../../core/model/dataset/dataset-profile'; +import { ExternalSourceItemModel } from '../../../core/model/external-sources/external-source-item'; +import { ProjectModel } from '../../../core/model/project/project'; +import { ExploreDatasetCriteriaModel } from '../../../core/query/explore-dataset/explore-dataset-criteria'; +import { ProjectCriteria } from '../../../core/query/project/project-criteria'; +import { TagCriteria } from '../../../core/query/tag/tag-criteria'; +import { DatasetService } from '../../../core/services/dataset/dataset.service'; +import { ExternalSourcesService } from '../../../core/services/external-sources/external-sources.service'; +import { ProjectService } from '../../../core/services/project/project.service'; +import { RequestItem } from '../../../core/query/request-item'; + +@Component({ + selector: 'app-explore-dataset-filters-component', + templateUrl: './explore-dataset-filters.component.html', + styleUrls: ['./explore-dataset-filters.component.scss'] +}) +export class ExploreDatasetFiltersComponent extends BaseComponent implements OnInit, AfterViewInit { + + @Input() facetCriteria = new ExploreDatasetCriteriaModel(); + @Output() facetCriteriaChange = new EventEmitter(); + public filteringTagsAsync = false; + public filteredTags: ExternalSourceItemModel[]; + ProjectStateType = ProjectStateType; + projects: Observable; + profiles: Observable; + dmpOrganisations: Observable; + projectOptions: Observable; + projectStateOptions: Observable; + @ViewChild('facetAccordion') accordion: MatAccordion; + + displayProjectStateValue = (option) => option['value']; + displayProjectStateLabel = (option) => option['label']; + + displayProjectValue = (option) => option['id']; + displayProjectLabel = (option) => option['label']; + + displayProfileValue = (option) => option['id']; + displayProfileLabel = (option) => option['label']; + + displayDmpOrganisationsValue = (option) => option['id']; + displayDmpOrganisationsLabel = (option) => option['name']; + + tagsAutoCompleteConfiguration = { + filterFn: this.filterTags.bind(this), + initialItems: (excludedItems: any[]) => this.filterTags('').map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1)), + displayFn: (item) => item['name'], + titleFn: (item) => item['name'] + }; + + constructor( + public activatedRoute: ActivatedRoute, + public projectService: ProjectService, + public languageService: TranslateService, + public datasetProfileService: DatasetService, + public externalSourcesService: ExternalSourcesService + ) { super(); } + + ngOnInit() { + setTimeout(x => { + this.projectStateOptions = Observable.of( + [ + { label: this.languageService.instant('FACET-SEARCH.PROJECT-STATUS.OPTIONS.INACTIVE'), value: ProjectStateType.Finished }, + { label: this.languageService.instant('FACET-SEARCH.PROJECT-STATUS.OPTIONS.ACTIVE'), value: ProjectStateType.OnGoing }, + ]); + }); + this.profiles = this.datasetProfileService.getDatasetProfiles(); + this.dmpOrganisations = this.externalSourcesService.searchDMPOrganizations(''); + } + + ngAfterViewInit(): void { + this.accordion.openAll(); + } + + public projectStatusChanged(event) { + this.facetCriteria.projectStatus = event.option.value.value; + if (!event.option.selected) { + this.facetCriteria.projectStatus = null; + this.projects = Observable.of([]); + this.facetCriteria.projects = []; + } + if (event.option.selected) { + const projectCriteria = new ProjectCriteria(); + projectCriteria.projectStateType = this.facetCriteria.projectStatus; + projectCriteria['length'] = 10; + const dataTableRequest: RequestItem = { criteria: projectCriteria }; + this.projects = this.projectService.get(dataTableRequest); + this.facetCriteria.projects = []; + } + this.facetCriteriaChange.emit(this.facetCriteria); + } + + public projectChanged(event: any) { + const eventValue = event.option.value.id; + if (event.option.selected) { this.facetCriteria.projects.push(eventValue); } + if (!event.option.selected) { + const index = this.facetCriteria.projects.indexOf(eventValue); + this.facetCriteria.projects.splice(index, 1); + } + this.facetCriteriaChange.emit(this.facetCriteria); + } + + removeProject(project) { + this.facetCriteria.projects.splice(this.facetCriteria.projects.indexOf(project), 1); + this.facetCriteriaChange.emit(this.facetCriteria); + } + + public profileChanged(event: any) { + const eventValue = event.option.value.id; + if (event.option.selected) { + this.facetCriteria.datasetProfile.push(eventValue); + } + if (!event.option.selected) { + const index = this.facetCriteria.datasetProfile.indexOf(eventValue); + this.facetCriteria.datasetProfile.splice(index, 1); + } + this.facetCriteriaChange.emit(this.facetCriteria); + } + + removeProfile(profile) { + this.facetCriteria.datasetProfile.splice(this.facetCriteria.datasetProfile.indexOf(profile), 1); + this.facetCriteriaChange.emit(this.facetCriteria); + } + + public dmpOrganisationChanged(event: any) { + const eventValue = event.option.value.id; + if (event.option.selected) { this.facetCriteria.dmpOrganisations.push(eventValue); } + if (!event.option.selected) { + const index = this.facetCriteria.dmpOrganisations.indexOf(eventValue); + this.facetCriteria.dmpOrganisations.splice(index, 1); + } + this.facetCriteriaChange.emit(this.facetCriteria); + } + + public projectSearch(value: string): Observable { + const projectCriteria = new ProjectCriteria(); + projectCriteria.projectStateType = this.facetCriteria.projectStatus; + projectCriteria['length'] = 10; + projectCriteria.like = value; + const dataTableRequest: RequestItem = { criteria: projectCriteria }; + return this.projectService.get(dataTableRequest); + } + + public dmpOrganisationSearch(value: string): Observable { + return this.externalSourcesService.searchDMPOrganizations(value); + } + + removeOrganisation(organisation) { + this.facetCriteria.dmpOrganisations.splice(this.facetCriteria.dmpOrganisations.indexOf(organisation), 1); + this.facetCriteriaChange.emit(this.facetCriteria); + } + + public profileSearch(value: string) { + return this.datasetProfileService.getDatasetProfiles(); + } + + public controlModified() { + this.facetCriteriaChange.emit(this.facetCriteria); + } + + filterTags(value: string): Observable { + this.filteredTags = undefined; + this.filteringTagsAsync = true; + const requestItem: RequestItem = new RequestItem(); + const criteria: TagCriteria = new TagCriteria(); + criteria.like = value; + requestItem.criteria = criteria; + return this.externalSourcesService.searchDatasetTags(requestItem); + // .subscribe(items => { + // this.filteredTags = items; + // this.filteringTagsAsync = false; + // }); + + + } +} diff --git a/dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.component.html b/dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.component.html new file mode 100644 index 000000000..29340a7c2 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.component.html @@ -0,0 +1,10 @@ +
+
+
+ + {{ breadcrumb.label }} + + chevron_right +
+
+
diff --git a/dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.component.scss b/dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.component.scss new file mode 100644 index 000000000..a7bebfffa --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.component.scss @@ -0,0 +1,17 @@ +.app-breadcrumb { + padding: 0.75rem 0.1rem; + margin-bottom: 1rem; + background-color: #e9ecef; + border-radius: 0.25rem; + margin-top: 2em; + + .arrow { + padding-right: 0; + padding-left: 0; + font-size: 1.7em; + } + + .link { + font-size: 1.1em; + } +} diff --git a/dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.component.ts b/dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.component.ts new file mode 100644 index 000000000..30d85d34a --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.component.ts @@ -0,0 +1,39 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; +import { Observable } from 'rxjs'; +import { BreadcrumbItem } from './definition/breadcrumb-item'; +import { BreadCrumbResolverService } from './service/breadcrumb.service'; + +@Component({ + selector: 'app-breadcrumb', + templateUrl: './breadcrumb.component.html', + styleUrls: ['./breadcrumb.component.scss'] +}) +export class BreadcrumbComponent implements OnInit { + breadcrumbs$ = this.router.events + .filter(event => event instanceof NavigationEnd) + .distinctUntilChanged() + .flatMap(event => this.buildBreadCrumb(this.activatedRoute.root)); + + + constructor( + public activatedRoute: ActivatedRoute, + private router: Router, + private breadCrumbService: BreadCrumbResolverService + ) { + + } + + ngOnInit() { + + } + + buildBreadCrumb(route: ActivatedRoute): Observable { + if (this.breadCrumbService.resolve(route)) { return this.breadCrumbService.resolve(route).map(x => { x.unshift({ label: 'Dashboard', url: '/home' }); return x; }); } + return Observable.of([]); + } + + navigate(url, params) { + this.router.navigate([url, params]); + } +} diff --git a/dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.module.ts b/dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.module.ts new file mode 100644 index 000000000..380baae34 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.module.ts @@ -0,0 +1,20 @@ +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { CommonUiModule } from '../../../common/ui/common-ui.module'; +import { BreadcrumbComponent } from './breadcrumb.component'; +import { BreadCrumbResolverService } from './service/breadcrumb.service'; + +@NgModule({ + imports: [ + CommonUiModule, + RouterModule + ], + declarations: [ + BreadcrumbComponent + ], + providers: [ + BreadCrumbResolverService + ], + exports: [BreadcrumbComponent] +}) +export class BreadcrumbModule { } diff --git a/dmp-frontend/src/app/shared/components/breadcrumb/definition/IBreadCrumbComponent.ts b/dmp-frontend/src/app/ui/misc/breadcrumb/definition/IBreadCrumbComponent.ts similarity index 100% rename from dmp-frontend/src/app/shared/components/breadcrumb/definition/IBreadCrumbComponent.ts rename to dmp-frontend/src/app/ui/misc/breadcrumb/definition/IBreadCrumbComponent.ts diff --git a/dmp-frontend/src/app/ui/misc/breadcrumb/definition/breadcrumb-item.ts b/dmp-frontend/src/app/ui/misc/breadcrumb/definition/breadcrumb-item.ts new file mode 100644 index 000000000..b312262de --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/breadcrumb/definition/breadcrumb-item.ts @@ -0,0 +1,8 @@ + +export class BreadcrumbItem { + parentComponentName?: string; + label: string; + url: string; + params?: any = {}; + notFoundResolver?: any[]; +} diff --git a/dmp-frontend/src/app/ui/misc/breadcrumb/service/breadcrumb.service.ts b/dmp-frontend/src/app/ui/misc/breadcrumb/service/breadcrumb.service.ts new file mode 100644 index 000000000..ed6071b93 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/breadcrumb/service/breadcrumb.service.ts @@ -0,0 +1,85 @@ +import { Injectable, NgZone } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { BaseService } from '../../../../core/common/base/base.service'; +import { BreadcrumbItem } from '../definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '../definition/IBreadCrumbComponent'; + +@Injectable() +export class BreadCrumbResolverService extends BaseService { + + private activeComponents = []; + private parentComponents = []; + private breadCrumbs: Observable = Observable.of([]); + constructor( + private router: Router, + private zone: NgZone + ) { super(); } + + public push(component: any) { + const existingComponentIndex = this.activeComponents.map(x => x.constructor.name).indexOf(component.constructor.name); + if (existingComponentIndex !== -1) { this.activeComponents.splice(existingComponentIndex, 1); } + this.activeComponents.push(component); + } + + public clear() { + this.activeComponents.length = 0; + this.breadCrumbs = Observable.of([]); + } + + public resolve(activatedRoute: ActivatedRoute): Observable { + this.breadCrumbs = null; + const routeComponents = this.getComponentsFromRoute(activatedRoute, []); + this.activeComponents.filter(x => routeComponents.indexOf(x.constructor.name) !== -1).forEach(x => { + if (x.hasOwnProperty('breadCrumbs')) { + const componentItems = this.resolveDependentComponents((x).breadCrumbs, []); + this.breadCrumbs = Observable.of(componentItems); + } + }); + return this.breadCrumbs; + } + + private getComponentsFromRoute(activatedRoute: ActivatedRoute, routeComponents: any[]): any[] { + activatedRoute.children.forEach(x => { + if (x.children.length > 0) { this.getComponentsFromRoute(x.children[0], routeComponents); } + if (x.component) { routeComponents.push(x.component['name']); } + }); + if (activatedRoute.component) { routeComponents.push(activatedRoute.component['name']); } + + return routeComponents; + } + + resolveDependentComponents(items: Observable, components: any[]): any[] { + items + .pipe(takeUntil(this._destroyed)) + .subscribe(breadCrumbs => { + breadCrumbs.forEach(async item => { + const parentComponent = item.parentComponentName ? this.findComponent(item.parentComponentName) : null; + if (parentComponent && parentComponent.hasOwnProperty('breadCrumbs')) { + components = this.pushToStart(components, this.resolveDependentComponents((parentComponent).breadCrumbs, components)); + } else if (item.notFoundResolver) { + components = this.pushToStart(components, item.notFoundResolver); + //components = this.pushToStart(components, [unresolvedComponentItems]) + } + }); + components = this.pushToEnd(components, breadCrumbs); + }); + return components; + } + + private findComponent(componentName: string): any { + for (let i = 0; i < this.activeComponents.length; i++) { + if (this.activeComponents[i].constructor.name === componentName) { return this.activeComponents[i]; } + } + return null; + } + + pushToStart(first: any[], second: any[]) { + return [].concat(second.filter(x => first.map(firstX => firstX.label).indexOf(x.label) === -1), first); + } + + pushToEnd(first: any[], second: any[]) { + return [].concat(first, second.filter(x => first.map(firstX => firstX.label).indexOf(x.label) === -1)); + } +} diff --git a/dmp-frontend/src/app/ui/misc/criteria/base-criteria.component.ts b/dmp-frontend/src/app/ui/misc/criteria/base-criteria.component.ts new file mode 100644 index 000000000..476a3b270 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/criteria/base-criteria.component.ts @@ -0,0 +1,99 @@ +import { Component, OnInit } from '@angular/core'; +import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; +import { ValidationErrorModel } from '../../../common/forms/validation/error-model/validation-error-model'; +import { BaseComponent } from '../../../core/common/base/base.component'; + +@Component({ + selector: 'app-base-criteria-component', + template: '', +}) +export class BaseCriteriaComponent extends BaseComponent implements OnInit { + + public refreshCallback: Function = null; + public formGroup: FormGroup = null; + + constructor( + public baseErrorModel?: ValidationErrorModel, + ) { + super(); + } + + ngOnInit() { + if (this.baseErrorModel == null) { this.baseErrorModel = new ValidationErrorModel(); } + } + + controlModified(): void { + this.clearErrorModel(); + if (!this.isFormValid()) { return; } + if (this.refreshCallback != null) { this.refreshCallback(); } + } + + public isFormValid(): boolean { + this.touchAllFormFields(this.formGroup); + this.validateAllFormFields(this.formGroup); + return this.formGroup.valid; + } + + public getFormData(): any { + return this.formGroup.value; + } + + public getFormControl(controlName: string): AbstractControl { + return this.formGroup.get(controlName); + } + + public disableFormFields(formControl: AbstractControl) { + formControl.disable(); + } + + public validateAllFormFields(formControl: AbstractControl) { + if (formControl instanceof FormControl) { + formControl.updateValueAndValidity({ emitEvent: false }); + } else if (formControl instanceof FormGroup) { + Object.keys(formControl.controls).forEach(item => { + const control = formControl.get(item); + this.validateAllFormFields(control); + }); + } else if (formControl instanceof FormArray) { + formControl.controls.forEach(item => { + this.validateAllFormFields(item); + }); + } + } + + public touchAllFormFields(formControl: AbstractControl) { + if (formControl instanceof FormControl) { + formControl.markAsTouched(); + } else if (formControl instanceof FormGroup) { + Object.keys(formControl.controls).forEach(item => { + const control = formControl.get(item); + this.touchAllFormFields(control); + }); + } else if (formControl instanceof FormArray) { + formControl.controls.forEach(item => { + this.touchAllFormFields(item); + }); + } + } + + setRefreshCallback(callback: Function): void { + this.refreshCallback = callback; + } + + onCallbackError(error: any) { + this.setErrorModel(error.error); + this.validateAllFormFields(this.formGroup); + } + + public setErrorModel(errorModel: any) { + Object.keys(errorModel).forEach(item => { + (this.baseErrorModel)[item] = (errorModel)[item]; + }); + } + + public clearErrorModel() { + Object.keys(this.baseErrorModel).forEach(item => { + (this.baseErrorModel)[item] = ''; + }); + } +} diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-composite-field/form-composite-field.component.html b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-composite-field/form-composite-field.component.html new file mode 100644 index 000000000..2db924526 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-composite-field/form-composite-field.component.html @@ -0,0 +1,45 @@ +
+ +
+
+
{{compositeField.numbering}} + {{compositeField.title}} + +
+
{{compositeField.description}}
+
+ {{compositeField.extendedDescription}} +
+ +
+
+
+
+
{{compositeField.numbering}}{{compositeField.title}}
+
{{compositeField.description}}
+
+ {{compositeField.extendedDescription}} +
+
+ + +
+ +
+
+ +
+
+
+
+
+
+
diff --git a/dmp-frontend/src/app/form/dynamic-form-composite-field/dynamic-form-composite-field.css b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-composite-field/form-composite-field.component.scss similarity index 100% rename from dmp-frontend/src/app/form/dynamic-form-composite-field/dynamic-form-composite-field.css rename to dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-composite-field/form-composite-field.component.scss diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-composite-field/form-composite-field.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-composite-field/form-composite-field.component.ts new file mode 100644 index 000000000..92490b056 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-composite-field/form-composite-field.component.ts @@ -0,0 +1,39 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormArray, FormGroup } from '@angular/forms'; +import { CompositeField } from '../../../../../core/model/dataset-profile-definition/composite-field'; +import { Field } from '../../../../../core/model/dataset-profile-definition/field'; +import { VisibilityRulesService } from '../../visibility-rules/visibility-rules.service'; + +@Component({ + selector: 'app-form-composite-field', + templateUrl: './form-composite-field.component.html', + styleUrls: ['./form-composite-field.component.scss'] +}) +export class FormCompositeFieldComponent implements OnInit { + + @Input() compositeField: CompositeField; + form: FormGroup; + trackByFn = (index, item) => item ? item['id'] : null; + + constructor( + private visibilityRulesService: VisibilityRulesService, + //private markForConsiderationService: MarkForConsiderationService, + ) { + } + + ngOnInit() { + if (this.compositeField) { + this.form = this.visibilityRulesService.getFormGroup(this.compositeField.id); + } + } + + addMultipleField(fieldIndex: number) { + const field: Field = this.compositeField.fields[fieldIndex].cloneForMultiplicity(fieldIndex, ''); + this.compositeField.fields[fieldIndex].multiplicityItems.push(field); + ((this.form.get('fields').get('' + fieldIndex).get('multiplicityItems'))).push(field.buildForm()); + } + + // markForConsideration() { + // this.markForConsiderationService.markForConsideration(this.compositeField); + // } +} diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.html b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.html new file mode 100644 index 000000000..d123b2981 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.html @@ -0,0 +1,55 @@ +
+ + + + +
{{field.description}}
+
{{field.extendedDescription}}
+ + + + {{'GENERAL.VALIDATION.REQUIRED' + | translate}} + + +
+ + + + + + {{opt.label}} + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+ +
+ {{field.data.label}} +
+ + + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + +
+ + Yes + + No + +
+ +
+ + {{option.label}} + +
+ +
+
diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.scss b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.scss new file mode 100644 index 000000000..bdf89f6c1 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.scss @@ -0,0 +1,9 @@ +.dynamic-form-field { + .radio-button-item { + margin-right: 1em; + } + + .full-width { + width: 100% + } +} diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.ts new file mode 100644 index 000000000..ba6cd97ae --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.ts @@ -0,0 +1,40 @@ +import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { Subscription } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../../core/common/base/base.component'; +import { Field } from '../../../../../core/model/dataset-profile-definition/field'; +import { VisibilityRulesService } from '../../visibility-rules/visibility-rules.service'; + +@Component({ + selector: 'app-form-field', + templateUrl: './form-field.component.html', + styleUrls: ['./form-field.component.scss'] +}) +export class FormFieldComponent extends BaseComponent implements OnInit { + @Input() field: Field; + form: FormGroup; + + change: Subscription; + trackByFn = (index, item) => item ? item['id'] : null; + + constructor( + public visibilityRulesService: VisibilityRulesService + ) { super(); } + + ngOnInit() { + if (this.field) { + this.form = this.visibilityRulesService.getFormGroup(this.field.id); + this.change = this.form.get('value').valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(item => { + this.visibilityRulesService.updateValueAndVisibility(this.field.id); + }); + } + } + + assignDropdownItem(item: any) { + if (!item) { return null; } + return (typeof item === 'string') ? JSON.parse(item) : JSON.stringify(item); + } +} diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.html b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.html new file mode 100644 index 000000000..d25935d91 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.ts new file mode 100644 index 000000000..d2595f4fb --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.ts @@ -0,0 +1,67 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormArray, FormGroup } from '@angular/forms'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../../core/common/base/base.component'; +import { VisibilityRulesService } from '../../visibility-rules/visibility-rules.service'; + +@Component({ + selector: 'app-form-progress-indication', + templateUrl: './form-progress-indication.component.html' +}) +export class FormProgressIndicationComponent extends BaseComponent implements OnInit { + @Input() formGroup: FormGroup; + @Input() public progressValueAccuracy = 1; + determinateProgressValue: number; + + constructor(private visibilityRulesService: VisibilityRulesService) { super(); } + + public value = 0; + ngOnInit() { + this.calculateValueForProgressbar(); + this.formGroup + .valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(control => { + this.calculateValueForProgressbar(); + }); + } + + calculateValueForProgressbar() { + const progressSoFar = this.countFormControlsWithValue(this.formGroup); + const total = this.getFormControlDepthLength(this.formGroup); + const perc = (progressSoFar / total) * 100; + this.value = Number.parseFloat(perc.toPrecision(this.progressValueAccuracy)); + } + + countFormControlsWithValue(form: FormGroup): number { + let value = 0; + Object.keys(form.controls).forEach(key => { + const control = form.controls[key]; + if (control instanceof FormGroup) { value += this.countFormControlsWithValue(control); } else if (control instanceof FormArray) { + const formArray = (control); + for (let i = 0; i < formArray.length; i++) { + value += this.countFormControlsWithValue(formArray.get('' + i)); + } + } else if (key === 'value' && control.value != null && control.value !== '') { value++; } + }); + return value; + } + + getFormControlDepthLength(form: FormGroup): number { + let value = 0; + Object.keys(form.controls).forEach(key => { + const control = form.controls[key]; + if (control instanceof FormGroup) { value += this.getFormControlDepthLength(control); } else if (control instanceof FormArray) { + const formArray = (control); + for (let i = 0; i < formArray.length; i++) { + if (formArray.get('' + i).value && this.visibilityRulesService.checkElementVisibility(formArray.get('' + i).value.id)) { + value += this.getFormControlDepthLength(formArray.get('' + i)); + } + } + } else if (key === 'value' && this.visibilityRulesService.checkElementVisibility(form.controls['id'].value)) { + value++; + } + }); + return value; + } +} diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section.component.html b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section.component.html new file mode 100644 index 000000000..65f26c7e2 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section.component.html @@ -0,0 +1,43 @@ +
+ + + + +
{{section.numbering}} {{section.title}}
+
+ +

{{section.description}}

+ +
+
+ +
+
+
+ +
+ +
+
+ + + + +
+ +
+
+
+
+
+
+ +
+
+
+
+
diff --git a/dmp-frontend/src/app/form/dynamic-form-section/dynamic-form-section.scss b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section.component.scss similarity index 100% rename from dmp-frontend/src/app/form/dynamic-form-section/dynamic-form-section.scss rename to dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section.component.scss diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section.component.ts new file mode 100644 index 000000000..ed47e0c60 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section.component.ts @@ -0,0 +1,54 @@ +import { AfterViewInit, Component, Input, OnInit } from '@angular/core'; +import { FormArray, FormGroup } from '@angular/forms'; +import { CompositeField } from '../../../../../core/model/dataset-profile-definition/composite-field'; +import { Section } from '../../../../../core/model/dataset-profile-definition/section'; +import { FormFocusService } from '../../form-focus/form-focus.service'; +import { VisibilityRulesService } from '../../visibility-rules/visibility-rules.service'; + +@Component({ + selector: 'app-form-section', + templateUrl: './form-section.component.html', + styleUrls: ['./form-section.component.scss'] +}) +export class FormSectionComponent implements OnInit, AfterViewInit { + + @Input() section: Section; + form: FormGroup; + @Input() pathName: string; + @Input() path: string; + trackByFn = (index, item) => item ? item['id'] : null; + constructor( + private visibilityRulesService: VisibilityRulesService, + private formFocusService: FormFocusService + ) { } + + ngOnInit() { + if (this.section) { + this.form = this.visibilityRulesService.getFormGroup(this.section.id); + } + } + + ngAfterViewInit() { + this.visibilityRulesService.triggerVisibilityEvaluation(); + } + + addMultipleField(fieldsetIndex: number) { + const compositeField: CompositeField = this.section.compositeFields[fieldsetIndex].cloneForMultiplicity(fieldsetIndex); + this.section.compositeFields[fieldsetIndex].multiplicityItems.push(compositeField); + ((this.form.get('compositeFields').get('' + fieldsetIndex).get('multiplicityItems'))).push(compositeField.buildForm()); + } + + isElementVisible(fieldSet: CompositeField): boolean { + if (!fieldSet) { return false; } + for (let i = 0; i < fieldSet.fields.length; i++) { + if (fieldSet.fields[i]) { + return true; + } + } + return false; + } + + next(compositeField: CompositeField) { + this.formFocusService.focusNext(compositeField); + } +} diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.html b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.html new file mode 100644 index 000000000..ec6c4e87d --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.html @@ -0,0 +1,20 @@ +
+
+ + +
+ +
+
+ + {{page.title}} +
+ +
+
+
+
+
+
+
+
diff --git a/dmp-frontend/src/app/form/dynamic-form/dynamic-form.component.scss b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.scss similarity index 100% rename from dmp-frontend/src/app/form/dynamic-form/dynamic-form.component.scss rename to dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.scss diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.ts new file mode 100644 index 000000000..e062af7a5 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.ts @@ -0,0 +1,125 @@ +import { AfterViewInit, Component, Input, OnInit, ViewChild } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { MatStepper } from '@angular/material'; +import { ActivatedRoute, Router } from '@angular/router'; +import 'rxjs/add/operator/switchMap'; +import { takeUntil } from 'rxjs/operators'; +import { Pair } from '../../../common/types/pair'; +import { BaseComponent } from '../../../core/common/base/base.component'; +import { CompositeField } from '../../../core/model/dataset-profile-definition/composite-field'; +import { DatasetProfileDefinitionModel } from '../../../core/model/dataset-profile-definition/dataset-profile-definition'; +import { Rule } from '../../../core/model/dataset-profile-definition/rule'; +import { Section } from '../../../core/model/dataset-profile-definition/section'; +import { DatasetDescriptionFormEditorModel } from './dataset-description-form.model'; +import { FormFocusService } from './form-focus/form-focus.service'; +import { VisibilityRulesService } from './visibility-rules/visibility-rules.service'; + +@Component({ + selector: 'app-dataset-description-form', + templateUrl: './dataset-description-form.component.html', + styleUrls: ['./dataset-description-form.component.scss'] +}) +export class DatasetDescriptionFormComponent extends BaseComponent implements OnInit, AfterViewInit { + + pathName: string; + pages: Array; + activeStepperIndex = 1; + visibleSidebar = false; + datasetProfileDefinitionModel: DatasetDescriptionFormEditorModel; + private currentPageIndex = 0; + @ViewChild('stepper') stepper: MatStepper; + + @Input() dataModel: DatasetProfileDefinitionModel; + @Input() path: string; + @Input() form: FormGroup; + id: string; + trackByFn = (index, item) => item ? item['id'] : null; + pageTrackByFn = (index, item) => item['id']; + + // @Input() datasetId: string; + + constructor( + private router: Router, + private route: ActivatedRoute, + private visibilityRulesService: VisibilityRulesService, + private formFocusService: FormFocusService + ) { + super(); + //this.datasetId = route.snapshot.params['id']; + } + + getSubForm(subformName) { + return this.form.controls[subformName]; + } + + ngOnInit() { + + const rules: Rule[] = this.dataModel.rules; + this.visibilityRulesService.formGroup = this.form; + this.visibilityRulesService.buildVisibilityRules(rules); + this.datasetProfileDefinitionModel = new DatasetDescriptionFormEditorModel().fromModel(this.dataModel); + this.visibilityRulesService.setModel(this.datasetProfileDefinitionModel); + + this.createPagination(); + + const sections: Pair[] = this.datasetProfileDefinitionModel.pages.map(page => new Pair(page.sections, page.ordinal)).filter(x => x); + const compositeFields: Pair[] = sections.map(section => new Pair(section.left.flatMap(sec => sec.compositeFields), section.right)).filter(x => x); + const nestedSections: Pair[] = sections.map(section => new Pair(section.left.flatMap(x => x.sections), section.right)).filter(x => x); + const nestedCompositeFields: Pair[] = nestedSections.map(section => new Pair(section.left.flatMap(x => x.compositeFields), section.right)).filter(x => x); + const compositeFieldsUnion: Pair[] = compositeFields.concat(nestedCompositeFields); + + //const fields = compositeFieldsUnion.flatJoinOn(x => x.right); + this.formFocusService.setFields(compositeFieldsUnion); + this.route.fragment + .pipe(takeUntil(this._destroyed)) + .subscribe((fragment: string) => { + const self = this; + setTimeout(function () { self.scrollTo(fragment); }); + }); + } + + ngAfterViewInit() { + this.visibilityRulesService.triggerVisibilityEvaluation(); + this.route.queryParams + .pipe(takeUntil(this._destroyed)) + .subscribe((params) => { + if (params && 'page' in params) { + this.changeCurrentPage(params['page']); + } + }); + } + + + toggleSidebar() { + this.visibleSidebar = !this.visibleSidebar; + } + + shouldDisplaySection(section: Section): Boolean { + return (section.page) === this.currentPageIndex; + } + + createPagination() { + + } + + changePageIndex(index: any) { + this.router.navigate([this.route.snapshot.url[0] + '/' + this.route.snapshot.url[1]], { queryParams: { page: this.pages[index - 1] } }); + } + + scrollTo(sectionID: string) { + if (!sectionID) { return; } + const element = document.querySelector('#' + sectionID); + if (!element) { return; } + element.scrollIntoView(); + this.visibleSidebar = true; + } + + changeCurrentPage(pageString: string) { + //if (!pageString) { return; } + const page = parseInt(pageString); + /*if (isNaN(page)) { return; } + const pageIndex = this.pages.indexOf(page); + if (pageIndex === -1) { return; }*/ + this.stepper.selectedIndex = page; + } +} diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.model.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.model.ts new file mode 100644 index 000000000..446d63a58 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.model.ts @@ -0,0 +1,295 @@ +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; +import { ValidationType } from "../../../core/common/enum/validation-type"; +import { CompositeField } from "../../../core/model/dataset-profile-definition/composite-field"; +import { DatasetProfileDefinitionModel } from "../../../core/model/dataset-profile-definition/dataset-profile-definition"; +import { DefaultValue } from "../../../core/model/dataset-profile-definition/default-value"; +import { Field } from "../../../core/model/dataset-profile-definition/field"; +import { Multiplicity } from "../../../core/model/dataset-profile-definition/multiplicity"; +import { Page } from "../../../core/model/dataset-profile-definition/page"; +import { Rule } from "../../../core/model/dataset-profile-definition/rule"; +import { Section } from "../../../core/model/dataset-profile-definition/section"; +import { ViewStyle } from "../../../core/model/dataset-profile-definition/view-style"; +import { BaseFormModel } from "../../../core/model/base-form-model"; + +export class DatasetDescriptionFormEditorModel extends BaseFormModel { + + public status: number; + public pages: Array = []; + public rules: Rule[] = []; + + fromModel(item: DatasetProfileDefinitionModel): DatasetDescriptionFormEditorModel { + this.status = item.status; + this.rules = item.rules; + if (item.pages) { item.pages.map(x => this.pages.push(new DatasetDescriptionPageEditorModel().fromModel(x))); } + return this; + } + + buildForm(): FormGroup { + const formGroup: FormGroup = new FormBuilder().group({}); + const pagesFormArray = new Array(); + + this.pages.forEach(item => { + const form: FormGroup = item.buildForm(); + pagesFormArray.push(form); + }); + formGroup.addControl('pages', this.formBuilder.array(pagesFormArray)); + return formGroup; + } +} + +export class DatasetDescriptionPageEditorModel extends BaseFormModel { + public ordinal: number; + public title: string; + public sections: DatasetDescriptionSectionEditorModel[] = []; + + fromModel(item: Page): DatasetDescriptionPageEditorModel { + this.ordinal = item.ordinal; + this.title = item.title; + if (item.sections) { item.sections.map(x => this.sections.push(new DatasetDescriptionSectionEditorModel().fromModel(x))); } + return this; + } + + buildForm(): FormGroup { + const formGroup: FormGroup = new FormBuilder().group({}); + const sectionsFormArray = new Array(); + this.sections.forEach(item => { + const form: FormGroup = item.buildForm(); + sectionsFormArray.push(form); + }); + formGroup.addControl('sections', this.formBuilder.array(sectionsFormArray)); + return formGroup; + } +} + +export class DatasetDescriptionSectionEditorModel extends BaseFormModel { + + sections: Array = new Array(); + defaultVisibility: boolean; + page: number; + numbering: string; + ordinal: number; + id: string; + title: string; + description: string; + compositeFields: Array = new Array(); + + fromModel(item: Section): DatasetDescriptionSectionEditorModel { + if (item.sections) { item.sections.map(x => this.sections.push(new DatasetDescriptionSectionEditorModel().fromModel(x))); } + this.page = item.page; + this.defaultVisibility = item.defaultVisibility; + this.numbering = item.numbering; + this.id = item.id; + this.title = item.title; + this.ordinal = item.ordinal; + this.description = item.description; + if (item.compositeFields) { item.compositeFields.map(x => this.compositeFields.push(new DatasetDescriptionCompositeFieldEditorModel().fromModel(x))); } + return this; + } + + buildForm(): FormGroup { + const formGroup: FormGroup = new FormBuilder().group({}); + const sectionsFormArray = new Array(); + if (this.sections) { + this.sections.forEach(item => { + const form: FormGroup = item.buildForm(); + sectionsFormArray.push(form); + }); + } + const compositeFieldsFormArray = new Array(); + if (this.compositeFields) { + this.compositeFields.forEach(item => { + const form: FormGroup = item.buildForm(); + compositeFieldsFormArray.push(form); + }); + } + formGroup.addControl('compositeFields', this.formBuilder.array(compositeFieldsFormArray)); + formGroup.addControl('sections', this.formBuilder.array(sectionsFormArray)); + return formGroup; + } +} + +export class DatasetDescriptionCompositeFieldEditorModel extends BaseFormModel { + + fields: Array = new Array(); + ordinal: number; + id: string; + numbering: string; + multiplicity: DatasetDescriptionMultiplicityEditorModel; + multiplicityItems: DatasetDescriptionCompositeFieldEditorModel[] = []; + title: string; + description: string; + extendedDescription: string; + hasCommentField: boolean; + commentFieldValue: string; + + fromModel(item: CompositeField): DatasetDescriptionCompositeFieldEditorModel { + + if (item.fields) { item.fields.map(x => this.fields.push(new DatasetDescriptionFieldEditorModel().fromModel(x))); } + this.ordinal = item.ordinal; + this.id = item.id; + this.title = item.title; + this.numbering = item.numbering; + this.description = item.description; + this.extendedDescription = item.extendedDescription; + this.hasCommentField = item.hasCommentField; + this.commentFieldValue = item.commentFieldValue; + if (item.multiplicity) this.multiplicity = new DatasetDescriptionMultiplicityEditorModel().fromModel(item.multiplicity); + if (item.multiplicityItems) { item.multiplicityItems.map(x => this.multiplicityItems.push(new DatasetDescriptionCompositeFieldEditorModel().fromModel(x))); } + return this; + } + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + id: this.id, + ordinal: this.ordinal, + title: this.title, + description: this.description, + extendedDescription: this.extendedDescription, + hasCommentField: this.hasCommentField, + commentFieldValue: this.commentFieldValue + }); + + const fieldsFormArray = new Array(); + this.fields.forEach(item => { + const form: FormGroup = item.buildForm(); + fieldsFormArray.push(form); + }); + formGroup.addControl('fields', this.formBuilder.array(fieldsFormArray)); + + const multiplicityItemsFormArray = new Array(); + this.multiplicityItems.forEach(item => { + const form: FormGroup = item.buildForm(); + multiplicityItemsFormArray.push(form); + }); + formGroup.addControl('multiplicityItems', this.formBuilder.array(multiplicityItemsFormArray)); + + return formGroup; + } + + cloneForMultiplicity(index: number): DatasetDescriptionCompositeFieldEditorModel { + const newItem: DatasetDescriptionCompositeFieldEditorModel = new DatasetDescriptionCompositeFieldEditorModel(); + newItem.id = 'multiple_' + this.id + '_' + index; + this.fields.forEach(field => { + newItem.fields.push(field.cloneForMultiplicity(this.fields.indexOf(field), newItem.id + '_')); + }); + newItem.ordinal = this.ordinal; + + return newItem; + } +} + +export class DatasetDescriptionFieldEditorModel extends BaseFormModel { + + public id: string; + public title: string; + public value: any; + public defaultValue: DefaultValue; + public description: string; + public numbering: string; + public extendedDescription: string; + public viewStyle: ViewStyle; + public defaultVisibility: boolean; + public page: number; + public multiplicity: DatasetDescriptionMultiplicityEditorModel; + public multiplicityItems: Array = new Array(); + public data: any; + public validations: Array; + public validationRequired = false; + + fromModel(item: Field): DatasetDescriptionFieldEditorModel { + this.id = item.id; + this.title = item.title; + this.numbering = item.numbering; + this.description = item.description; + this.extendedDescription = item.extendedDescription; + this.viewStyle = item.viewStyle; + this.defaultVisibility = item.defaultVisibility; + this.page = item.page; + this.validations = item.validations; + if (item.multiplicity) this.multiplicity = new DatasetDescriptionMultiplicityEditorModel().fromModel(item.multiplicity); + if (item.defaultValue) this.defaultValue = new DatasetDescriptionDefaultValueEditorModel().fromModel(item.defaultValue); + this.value = this.defaultValue.value && !item.value ? this.defaultValue.value : item.value; + if (this.viewStyle.renderStyle === 'checkBox') { this.value = this.value === 'true'; } + if (item.multiplicityItems) { item.multiplicityItems.map(x => this.multiplicityItems.push(new DatasetDescriptionFieldEditorModel().fromModel(x))); } + this.data = item.data; + return this; + } + + buildForm(): FormGroup { + if (this.validations) { + this.validations.forEach(validation => { + if (validation === ValidationType.Required) { this.validationRequired = true; } + }); + } + + const formGroup = this.formBuilder.group({ + id: [this.id], + data: [this.data], + value: [this.value, this.validationRequired === true ? Validators.required : null] + }); + + const multiplicityItemsFormArray = new Array(); + this.multiplicityItems.forEach(item => { + const form: FormGroup = item.buildForm(); + multiplicityItemsFormArray.push(form); + }); + formGroup.addControl('multiplicityItems', this.formBuilder.array(multiplicityItemsFormArray)); + + return formGroup; + } + + cloneForMultiplicity(index: number, idPath: string): DatasetDescriptionFieldEditorModel { + const newItem: DatasetDescriptionFieldEditorModel = new DatasetDescriptionFieldEditorModel(); + + newItem.id = idPath ? idPath + index : 'multiple_' + this.id + '_' + index; + newItem.title = this.title; + newItem.description = this.description; + newItem.extendedDescription = this.extendedDescription; + newItem.viewStyle = this.viewStyle; + newItem.defaultVisibility = this.defaultVisibility; + newItem.page = this.page; + newItem.multiplicity = null; + newItem.data = this.data; + + return newItem; + } +} + + +export class DatasetDescriptionMultiplicityEditorModel extends BaseFormModel { + public min: number; + public max: number; + + fromModel(item: Multiplicity): DatasetDescriptionMultiplicityEditorModel { + this.min = item.min; + this.max = item.max; + return this; + } + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + min: [this.min], + max: [this.max] + }); + return formGroup; + } +} + +export class DatasetDescriptionDefaultValueEditorModel extends BaseFormModel { + public type: string; + public value: string; + + fromModel(item: DefaultValue): DatasetDescriptionDefaultValueEditorModel { + this.type = item.type; + this.value = item.value; + return this; + } + + buildForm(): FormGroup { + const formGroup = this.formBuilder.group({ + type: [this.type], + value: [this.value] + }); + return formGroup; + } +} \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.module.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.module.ts new file mode 100644 index 000000000..bea3e585b --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.module.ts @@ -0,0 +1,33 @@ +import { NgModule } from '@angular/core'; +import { CommonFormsModule } from '../../../common/forms/common-forms.module'; +import { CommonUiModule } from '../../../common/ui/common-ui.module'; +import { FormCompositeFieldComponent } from './components/form-composite-field/form-composite-field.component'; +import { FormFieldComponent } from './components/form-field/form-field.component'; +import { FormProgressIndicationComponent } from './components/form-progress-indication/form-progress-indication.component'; +import { FormSectionComponent } from './components/form-section/form-section.component'; +import { DatasetDescriptionFormComponent } from './dataset-description-form.component'; +import { FormFocusService } from './form-focus/form-focus.service'; +import { VisibilityRulesService } from './visibility-rules/visibility-rules.service'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule + ], + declarations: [ + DatasetDescriptionFormComponent, + FormProgressIndicationComponent, + FormSectionComponent, + FormCompositeFieldComponent, + FormFieldComponent + ], + exports: [ + DatasetDescriptionFormComponent + ], + providers: [ + VisibilityRulesService, + FormFocusService + ] +}) +export class DatasetDescriptionFormModule { } + diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.css b/dmp-frontend/src/app/ui/misc/dataset-description-form/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.css similarity index 100% rename from dmp-frontend/src/app/form/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.css rename to dmp-frontend/src/app/ui/misc/dataset-description-form/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.css diff --git a/dmp-frontend/src/app/form/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.html b/dmp-frontend/src/app/ui/misc/dataset-description-form/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.html similarity index 100% rename from dmp-frontend/src/app/form/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.html rename to dmp-frontend/src/app/ui/misc/dataset-description-form/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.html diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.ts new file mode 100644 index 000000000..c4dbab56d --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/dynamic-fields/dynamic-field-autocomplete/autocomplete-remote.component.ts @@ -0,0 +1,53 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { ActivatedRoute } from '@angular/router'; + + +@Component({ + selector: 'app-form-autocomplete', + templateUrl: './autocomplete-remote.component.html', + styleUrls: ['./autocomplete-remote.component.css'] +}) +export class AutocompleteRemoteComponent implements OnInit/* , ControlValueAccessor */ { + + + @Input() field: Field; + @Input() disabled = false; + @Input() form: FormGroup; + + public autoCompleteConfiguration: AutoCompleteConfiguration; + public loading: boolean; + public datasetId; + public values: any[] = new Array(); + public typeaheadMS = 1400; + + constructor(private datasetProfileService: DatasetProfileService, route: ActivatedRoute) { + this.datasetId = route.snapshot.params['id']; + } + + + ngOnInit() { + const autocompleteRequestItem: RequestItem = new RequestItem(); + autocompleteRequestItem.criteria = new AutocompleteLookupItem(); + autocompleteRequestItem.criteria.fieldID = this.field.id; + autocompleteRequestItem.criteria.profileID = this.datasetId; + this.autoCompleteConfiguration = new AutoCompleteConfiguration(this.datasetProfileService.queryAutocomplete.bind(this.datasetProfileService), autocompleteRequestItem); + + } + + displayWith(item: any) { + if (!item) { return null; } + if (typeof item === 'string') { item = this.transform(item); } + return item['label']; + } + + assign(item: any) { + if (!item) { return null; } + return this.transform(item); + } + + transform(item: any) { + if (typeof item === 'string') { return JSON.parse(item); } else { return JSON.stringify(item); } + } +} + diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/form-focus/form-focus.service.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/form-focus/form-focus.service.ts new file mode 100644 index 000000000..5a077dfa5 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/form-focus/form-focus.service.ts @@ -0,0 +1,35 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Pair } from '../../../../common/types/pair'; +import { CompositeField } from '../../../../core/model/dataset-profile-definition/composite-field'; +import { VisibilityRulesService } from '../visibility-rules/visibility-rules.service'; + +@Injectable() +export class FormFocusService { + + private compositeFields: Pair[] = []; + + constructor( + private router: Router, + private route: ActivatedRoute, + private visibilityService: VisibilityRulesService + ) { + + } + + setFields(compositeFields: Pair[]) { + this.compositeFields = compositeFields; + } + + focusNext(field: CompositeField) { + const flattenedCompositeFields = this.compositeFields.groupBy(x => x.right) + .map(x => x.reduce((first: Pair, second: Pair) => + (new Pair(first.left.concat(second.left), first.right)))); + const page = flattenedCompositeFields.filter(x => x['left'].map(y => y.id).indexOf(field.id) !== -1)[0]; + let pageIndex = page['right']; + const currentFields = page['left'].filter(x => this.visibilityService.checkElementVisibility(x.id)).map(x => x.id); + const fieldIndex = currentFields.indexOf(field.id); + if (fieldIndex === currentFields.length - 1) { pageIndex = pageIndex + 1; } + this.router.navigate(['datasets/' + this.route.snapshot.url[0] + '/' + this.route.snapshot.url[1]], { fragment: page['left'].filter(x => this.visibilityService.checkElementVisibility(x.id))[fieldIndex].id, queryParams: { page: pageIndex } }); + } +} diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.html b/dmp-frontend/src/app/ui/misc/dataset-description-form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.html new file mode 100644 index 000000000..8f25dd2bf --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.html @@ -0,0 +1,4 @@ +
+ + +
diff --git a/dmp-frontend/src/app/form/tableOfContents/table-of-content-group/table-of-content-group.component.html b/dmp-frontend/src/app/ui/misc/dataset-description-form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.scss similarity index 100% rename from dmp-frontend/src/app/form/tableOfContents/table-of-content-group/table-of-content-group.component.html rename to dmp-frontend/src/app/ui/misc/dataset-description-form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.scss diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.ts new file mode 100644 index 000000000..f64d3c45f --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component.ts @@ -0,0 +1,45 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { CompositeField } from '../../../../../core/model/dataset-profile-definition/composite-field'; +import { DatasetProfileDefinitionModel } from '../../../../../core/model/dataset-profile-definition/dataset-profile-definition'; +import { Rule } from '../../../../../core/model/dataset-profile-definition/rule'; +import { Section } from '../../../../../core/model/dataset-profile-definition/section'; +import { DatasetWizardModel } from '../../../../../core/model/dataset/dataset-wizard'; +import { MarkForConsiderationService } from '../../mark-for-consideration/mark-for-consideration.service'; +import { VisibilityRulesService } from '../../visibility-rules/visibility-rules.service'; + +@Component({ + selector: 'app-dynamic-form-pending-questions-display', + templateUrl: './dynamic-form-pending-questions-display.component.html', + styleUrls: ['./dynamic-form-pending-questions-display.component.scss'] +}) +export class DynamicFormPendingQuestionsDisplayComponent implements OnInit { + + constructor( + private visibilityRulesService: VisibilityRulesService, + public markForConsideration: MarkForConsiderationService) { + } + + datasetProfileDefinitionModel: DatasetProfileDefinitionModel; + + @Input() + form: FormGroup; + + @Input() dataModel: DatasetWizardModel; + + fields: CompositeField[]; + + ngOnInit(): void { + const rules: Rule[] = this.dataModel.datasetProfileDefinition.rules; + this.datasetProfileDefinitionModel = this.dataModel.datasetProfileDefinition; + const sections: Section[] = this.datasetProfileDefinitionModel.pages.flatMap(page => page.sections).filter(x => x); + const compositeFields: CompositeField[] = sections.flatMap(section => section.compositeFields).filter(x => x); + const nestedSections: Section[] = sections.flatMap(section => section.sections).filter(x => x); + const nestedCompositeFiels: CompositeField[] = nestedSections.flatMap(section => section.compositeFields).filter(x => x); + const compositeFieldsUnion = compositeFields.concat(nestedCompositeFiels); + //const fields: Field[] = compositeFields.flatMap(composite => composite.fields).concat(nestedCompositeFiels.flatMap(composite => composite.fields)); + const fields = compositeFieldsUnion.filter(compositeField => this.visibilityRulesService.checkElementVisibility(compositeField.id)) + .filter(compositeField => compositeField.fields.filter(x => x && x.validationRequired && this.visibilityRulesService.getFormGroup(x.id).value == null).length > 0); + fields.forEach(x => this.markForConsideration.markForConsideration(x)); + } +} diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/mark-for-consideration/mark-for-consideration.service.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/mark-for-consideration/mark-for-consideration.service.ts new file mode 100644 index 000000000..30673abeb --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/mark-for-consideration/mark-for-consideration.service.ts @@ -0,0 +1,22 @@ +import { Injectable } from '@angular/core'; +import { CompositeField } from '../../../../core/model/dataset-profile-definition/composite-field'; + +@Injectable() +export class MarkForConsiderationService { + + private compositeFields: CompositeField[] = []; + + markForConsideration(field: CompositeField) { + if (this.exists(field)) { + this.compositeFields.push(field); + } + } + + getFields() { + return this.compositeFields; + } + + exists(field: CompositeField) { + return this.compositeFields.map(x => x.id).indexOf(field.id) === -1; + } +} diff --git a/dmp-frontend/src/app/form/tableOfContents/base-table-of-content.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/base-table-of-content.component.ts similarity index 100% rename from dmp-frontend/src/app/form/tableOfContents/base-table-of-content.component.ts rename to dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/base-table-of-content.component.ts diff --git a/dmp-frontend/src/app/form/tableOfContents/table-of-content-field/table-of-content-field.component.html b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-field/table-of-content-field.component.html similarity index 100% rename from dmp-frontend/src/app/form/tableOfContents/table-of-content-field/table-of-content-field.component.html rename to dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-field/table-of-content-field.component.html diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-field/table-of-content-field.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-field/table-of-content-field.component.ts new file mode 100644 index 000000000..83f276eef --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-field/table-of-content-field.component.ts @@ -0,0 +1,19 @@ +import { Component, Input } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Field } from '../../../../../core/model/dataset-profile-definition/field'; +import { BaseTableOfContent } from '../base-table-of-content.component'; + + +@Component({ + selector: 'app-table-of-contents-field', + templateUrl: './table-of-content-field.component.html' +}) +export class TableOfContentsFieldComponent extends BaseTableOfContent { + @Input() model: Field; + @Input() index: number; + @Input() public path: string; + @Input() public page: number; + constructor(public router: Router, public route: ActivatedRoute, ) { + super(router, route); + } +} diff --git a/dmp-frontend/src/app/form/tableOfContents/table-of-content-fieldset/table-of-content-fieldset.component.html b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-fieldset/table-of-content-fieldset.component.html similarity index 100% rename from dmp-frontend/src/app/form/tableOfContents/table-of-content-fieldset/table-of-content-fieldset.component.html rename to dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-fieldset/table-of-content-fieldset.component.html diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-fieldset/table-of-content-fieldset.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-fieldset/table-of-content-fieldset.component.ts new file mode 100644 index 000000000..3e6bb632d --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-fieldset/table-of-content-fieldset.component.ts @@ -0,0 +1,19 @@ +import { Component, Input } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { CompositeField } from '../../../../../core/model/dataset-profile-definition/composite-field'; +import { BaseTableOfContent } from '../base-table-of-content.component'; + +@Component({ + selector: 'app-table-of-contents-fieldset', + templateUrl: './table-of-content-fieldset.component.html' +}) +export class TableOfContentsFieldSetComponent extends BaseTableOfContent { + + @Input() model: CompositeField; + @Input() index: number; + @Input() public path: string; + @Input() public page: number; + constructor(public router: Router, public route: ActivatedRoute) { + super(router, route); + } +} diff --git a/dmp-frontend/src/app/shared/components/criteria/projects/projects-criteria.component.scss b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-group/table-of-content-group.component.html similarity index 100% rename from dmp-frontend/src/app/shared/components/criteria/projects/projects-criteria.component.scss rename to dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-group/table-of-content-group.component.html diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-group/table-of-content-group.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-group/table-of-content-group.component.ts new file mode 100644 index 000000000..6b1a5428c --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-group/table-of-content-group.component.ts @@ -0,0 +1,24 @@ +// import { Component, Input } from '@angular/core'; +// import { ActivatedRoute, Router } from '@angular/router'; +// import { BaseTableOfContent } from '../base-table-of-content.component'; + +// @Component({ +// selector: 'app-table-of-contents-group', +// templateUrl: './table-of-content-group.component.html' +// }) +// export class TableOfContentsGroupComponent extends BaseTableOfContent { + +// @Input() model: FieldGroup; +// @Input() index: number; +// @Input() public path: string; +// @Input() public page: number; +// /* @Output() +// setPage:EventEmitter = new EventEmitter(); + +// */ +// constructor(public router: Router, public route: ActivatedRoute) { +// super(router, route); +// } + + +// } diff --git a/dmp-frontend/src/app/form/tableOfContents/table-of-content-section/table-of-content-section.component.html b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-section/table-of-content-section.component.html similarity index 100% rename from dmp-frontend/src/app/form/tableOfContents/table-of-content-section/table-of-content-section.component.html rename to dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-section/table-of-content-section.component.html diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-section/table-of-content-section.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-section/table-of-content-section.component.ts new file mode 100644 index 000000000..be077c7be --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-content-section/table-of-content-section.component.ts @@ -0,0 +1,23 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Section } from '../../../../../core/model/dataset-profile-definition/section'; +import { BaseTableOfContent } from '../base-table-of-content.component'; + +@Component({ + selector: 'app-table-of-contents-section', + templateUrl: './table-of-content-section.component.html' +}) +export class TableOfContentsSectionComponent extends BaseTableOfContent implements OnInit { + + @Input() model: Section; + @Input() index: number; + @Input() public path: string; + @Input() public page: number; + constructor(public router: Router, public route: ActivatedRoute) { + super(router, route); + } + ngOnInit() { + + } + +} diff --git a/dmp-frontend/src/app/form/tableOfContents/table-of-contents.component.html b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-contents.component.html similarity index 100% rename from dmp-frontend/src/app/form/tableOfContents/table-of-contents.component.html rename to dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-contents.component.html diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-contents.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-contents.component.ts new file mode 100644 index 000000000..5d34c6be7 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/table-of-contents.component.ts @@ -0,0 +1,19 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { DatasetProfileDefinitionModel } from '../../../../core/model/dataset-profile-definition/dataset-profile-definition'; + +@Component({ + selector: 'app-table-of-content', + templateUrl: './table-of-contents.component.html', + styleUrls: ['./toc.component.css'] +}) +export class TableOfContentsComponent implements OnInit { + + @Input() + public model: DatasetProfileDefinitionModel; + public path = ''; + + ngOnInit() { + + } + +} diff --git a/dmp-frontend/src/app/form/tableOfContents/toc.component.css b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/toc.component.css similarity index 100% rename from dmp-frontend/src/app/form/tableOfContents/toc.component.css rename to dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContents/toc.component.css diff --git a/dmp-frontend/src/app/utilities/visibility-rules/models/VisibilityRuleSource.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/models/visibility-rule-source.ts similarity index 100% rename from dmp-frontend/src/app/utilities/visibility-rules/models/VisibilityRuleSource.ts rename to dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/models/visibility-rule-source.ts diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/models/visibility-rule.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/models/visibility-rule.ts new file mode 100644 index 000000000..b2fba603b --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/models/visibility-rule.ts @@ -0,0 +1,6 @@ +import { VisibilityRuleSource } from "./visibility-rule-source"; + +export class VisibilityRule { + public targetControlId: string; + public sourceVisibilityRules: Array; +} diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/models/visibility-rules-context.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/models/visibility-rules-context.ts new file mode 100644 index 000000000..3df90cf19 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/models/visibility-rules-context.ts @@ -0,0 +1,35 @@ +import { Rule } from "../../../../../core/model/dataset-profile-definition/rule"; +import { VisibilityRule } from "./visibility-rule"; + +export class VisibilityRulesContext { + + public rules: Array = new Array(); + + constructor() { } + + public getRulesFromKey(id: string): VisibilityRule { + + for (let i = 0; i < this.rules.length; i++) { + if (id === this.rules[i].targetControlId) { return this.rules[i]; } + } + return null; + } + + public buildVisibilityRuleContext(items: Array) { + items.forEach(item => { + this.addToVisibilityRulesContext(item); + }); + } + + private addToVisibilityRulesContext(item: Rule): void { + for (let i = 0; i < this.rules.length; i++) { + if (this.rules[i].targetControlId === item.targetField) { + this.rules[i].sourceVisibilityRules.push({ sourceControlId: item.sourceField, sourceControlValue: item.requiredValue }); + return; + } + } + const newVisibilityRuleArray = [({ sourceControlId: item.sourceField, sourceControlValue: item.requiredValue })]; + this.rules.push({ targetControlId: item.targetField, sourceVisibilityRules: newVisibilityRuleArray }); + return; + } +} diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/visibility-rules.service.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/visibility-rules.service.ts new file mode 100644 index 000000000..ed52b2f4f --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/visibility-rules.service.ts @@ -0,0 +1,152 @@ +import { ApplicationRef, Injectable, NgZone } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { DatasetProfileDefinitionModel } from '../../../../core/model/dataset-profile-definition/dataset-profile-definition'; +import { Rule } from '../../../../core/model/dataset-profile-definition/rule'; +import { VisibilityRule } from './models/visibility-rule'; +import { VisibilityRulesContext } from './models/visibility-rules-context'; + +@Injectable() +export class VisibilityRulesService { + + public formGroup: FormGroup; + private visibilityRuleContext: VisibilityRulesContext; + private fieldsPathMemory: any = {}; + private elementVisibilityMap = new Map(); + private initialModel: DatasetProfileDefinitionModel; + private currentModel: DatasetProfileDefinitionModel; + + constructor( + public applicationReference: ApplicationRef, + public ngZone: NgZone + ) { + + } + + public setModel(model: DatasetProfileDefinitionModel) { + this.initialModel = model; + this.currentModel = model; + //this.visibilityRuleContext.rules.forEach(item => this.evaluateVisibility(item)) + } + + public triggerVisibilityEvaluation() { + this.visibilityRuleContext.rules.forEach(item => this.evaluateVisibility(item)); + } + + public getFormGroup(id: string): FormGroup { + const pathKeyArray = this.search('pages', this.initialModel.pages, id).split('.'); + + pathKeyArray.pop(); + const pathKey = pathKeyArray.join('.'); + if (!this.fieldsPathMemory[id] && pathKey) { this.fieldsPathMemory[id] = pathKey; } + return (this.formGroup.get(pathKey)); + } + + public checkElementVisibility(id: string): boolean { + return true; + //return !this.elementVisibilityMap.has(id) || this.elementVisibilityMap.get(id); + } + + public buildVisibilityRules(item: Array) { + this.visibilityRuleContext = new VisibilityRulesContext(); + this.visibilityRuleContext.buildVisibilityRuleContext(item || []); + } + + public updateValueAndVisibility(id: string) { + const visibilityRules = this.visibilityRuleContext.rules.filter(item => item.sourceVisibilityRules.filter(source => source.sourceControlId === id).length > 0); + //visibilityRules.forEach(item => this.evaluateVisibility(item)); + } + + private evaluateVisibility(visibilityRule: VisibilityRule) { + for (let i = 0; i < visibilityRule.sourceVisibilityRules.length; i++) { + const pathKey = this.fieldsPathMemory[visibilityRule.sourceVisibilityRules[i].sourceControlId]; + if (this.formGroup.get(pathKey + '.value') && (this.parseValue(this.formGroup.get(pathKey + '.value').value) !== this.parseValue(visibilityRule.sourceVisibilityRules[i].sourceControlValue))) { + if (this.formGroup.get(pathKey).parent.get('id')) { + if (!this.checkElementVisibility(this.formGroup.get(pathKey).parent.get('id').value)) { + const targetPathKey = this.fieldsPathMemory[visibilityRule.targetControlId]; + this.getObject(this.currentModel, 'id', visibilityRule.targetControlId, this.currentModel, true); + this.elementVisibilityMap.set(visibilityRule.targetControlId, false); + this.clearValues(targetPathKey); + return; + } + } else { + const targetPathKey = this.fieldsPathMemory[visibilityRule.targetControlId]; + this.getObject(this.currentModel, 'id', visibilityRule.targetControlId, this.currentModel, true); + this.elementVisibilityMap.set(visibilityRule.targetControlId, false); + this.clearValues(targetPathKey); + return; + } + } + } + const obj = this.getObject(this.initialModel, 'id', visibilityRule.targetControlId, this.initialModel); + const targetObjPathKey = this.fieldsPathMemory[visibilityRule.targetControlId] ? this.fieldsPathMemory[visibilityRule.targetControlId] : this.search('pages', this.initialModel.pages, obj); + this.updateValue(this.currentModel, obj, targetObjPathKey); + this.elementVisibilityMap.set(visibilityRule.targetControlId, true); + } + + private clearValues(pathKey) { + if (pathKey && this.formGroup.get(pathKey + '.value')) { this.formGroup.get(pathKey + '.value').patchValue(null); } + if (pathKey && this.formGroup.get(pathKey)['controls'].fields) { + for (let i = 0; i < this.formGroup.get(pathKey)['controls'].fields.length; i++) { + this.clearValues(pathKey + '.fields.' + i); + } + } + } + + parseValue(value: any) { + if (typeof value === 'string') { + if (value === 'true') { return true; } else if (value === 'false') { return false; } else { return this.translate(value); } + } else { return value; } + } + + updateValue(obj, value, path) { + let i; + path = path.split('.'); + + for (i = 0; i < path.length - 1; i++) { + obj = obj[path[i]]; + } + + for (let propIndex = 0; propIndex < obj.length; propIndex++) { + if (obj[propIndex] && obj[propIndex]['id'] === value['id']) { return; } + } + obj[path[i]] = value; + } + + search(path, obj, target) { + for (const k in obj) { + if (obj.hasOwnProperty(k)) { + if (obj[k] === target) { + return path + '.' + k; + } else if (typeof obj[k] === 'object') { + const result = this.search(path + '.' + k, obj[k], target); + if (result) { + return result; + } + } + } + } + return false; + } + + private getObject(obj, key, val, parent, deleteObj = false) { + for (const i in obj) { + if (!obj.hasOwnProperty(i)) { continue; } + if (typeof obj[i] === 'object') { + const returnObj = this.getObject(obj[i], key, val, obj, deleteObj); + if (returnObj) { return returnObj; } + } else if (i === key && obj[key] === val) { + //console.log(obj[key]) + if (deleteObj) { parent[parent.indexOf(obj)] = null; } + return obj; + } + } + } + + private translate(item: any) { + try { + return JSON.parse(item).value; + } catch (error) { + return item; + } + } +} diff --git a/dmp-frontend/src/app/ui/misc/external-sources/external-sources.module.ts b/dmp-frontend/src/app/ui/misc/external-sources/external-sources.module.ts new file mode 100644 index 000000000..b7b837fd0 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/external-sources/external-sources.module.ts @@ -0,0 +1,20 @@ +import { NgModule } from '@angular/core'; +import { CommonFormsModule } from '../../../common/forms/common-forms.module'; +import { CommonUiModule } from '../../../common/ui/common-ui.module'; +import { AutoCompleteModule } from '../../../library/auto-complete/auto-complete.module'; +import { ExternalItemListingComponent } from './listing/external-item-listing.component'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule, + AutoCompleteModule + ], + declarations: [ + ExternalItemListingComponent, + ], + exports: [ + ExternalItemListingComponent + ] +}) +export class ExternalSourcesModule { } diff --git a/dmp-frontend/src/app/ui/misc/external-sources/listing/external-item-listing.component.html b/dmp-frontend/src/app/ui/misc/external-sources/listing/external-item-listing.component.html new file mode 100644 index 000000000..615617b8a --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/external-sources/listing/external-item-listing.component.html @@ -0,0 +1,19 @@ +
+ + + + {{ option.label }} + + + + + + + +
+
+ + +
+
+
diff --git a/dmp-frontend/src/app/shared/components/external-items/external-item-listing/external-item-listing.component.scss b/dmp-frontend/src/app/ui/misc/external-sources/listing/external-item-listing.component.scss similarity index 100% rename from dmp-frontend/src/app/shared/components/external-items/external-item-listing/external-item-listing.component.scss rename to dmp-frontend/src/app/ui/misc/external-sources/listing/external-item-listing.component.scss diff --git a/dmp-frontend/src/app/ui/misc/external-sources/listing/external-item-listing.component.ts b/dmp-frontend/src/app/ui/misc/external-sources/listing/external-item-listing.component.ts new file mode 100644 index 000000000..6f8a7f2e4 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/external-sources/listing/external-item-listing.component.ts @@ -0,0 +1,46 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { FormArray, FormControl } from '@angular/forms'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../../core/common/base/base.component'; +import { ExternalSourceUrlModel } from '../../../../core/model/external-sources/external-source-url'; +import { SingleAutoCompleteConfiguration } from '../../../../library/auto-complete/single/single-auto-complete-configuration'; + +@Component({ + selector: 'app-external-item-listing', + templateUrl: './external-item-listing.component.html', + styleUrls: ['./external-item-listing.component.scss'] +}) +export class ExternalItemListingComponent extends BaseComponent implements OnInit { + + @Input() public placeholder: string; + @Input() public autoCompleteConfiguration: SingleAutoCompleteConfiguration; + @Input() formArray: FormArray; + @Input() parentTemplate; + @Input() public options: Array; + @Output() public onItemChange = new EventEmitter(); + + public choice: string; + public formControl = new FormControl(); + + constructor() { super(); } + ngOnInit() { + this.formControl.disable(); + this.formControl.updateValueAndValidity(); + + this.formControl.valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => { + if (x) { this.onItemChange.emit(x); } + }); + } + + selectionChange(event) { + if (this.formControl.disabled) { this.formControl.enable(); this.formControl.updateValueAndValidity(); } + this.autoCompleteConfiguration.extraData = event.value; + } + + deleteItem(name: number) { + this.formArray.removeAt(name); + } +} + diff --git a/dmp-frontend/src/app/ui/misc/help-content/help-content.component.ts b/dmp-frontend/src/app/ui/misc/help-content/help-content.component.ts new file mode 100644 index 000000000..9b18572b2 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/help-content/help-content.component.ts @@ -0,0 +1,66 @@ +/** + * Created by stefania on 7/17/17. + */ +import { Component, Input, OnInit } from '@angular/core'; +import { ActivatedRoute, NavigationStart, Router } from '@angular/router'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../core/common/base/base.component'; +import { PageHelpContent } from '../../../core/model/help-content/page-help-content'; +import { HelpContentService } from '../../../core/services/help-content/help-content.service'; + +@Component({ + selector: 'app-help-content', + template: ` + + +
+
+
+ `, +}) +export class HelpContentComponent extends BaseComponent implements OnInit { + @Input() position: string; + contents: any[]; + errorMessage: string = null; + constructor(private _helpContentService: HelpContentService, private route: ActivatedRoute, private router: Router) { + super(); + } + + ngOnInit() { + this.errorMessage = null; + this.router.events + .pipe(takeUntil(this._destroyed)) + .subscribe(event => { + if (event instanceof NavigationStart) { + this._helpContentService.getActivePageContent(event['url']) + .pipe(takeUntil(this._destroyed)) + .subscribe( + pageContent => this.shiftThroughContent(pageContent), + error => this.handleError(error)); + } + }); + } + shiftThroughContent(pageContent: PageHelpContent) { + this.contents = pageContent.content[this.position]; + } + isPresent() { + return (this.contents && this.contents.length > 0); + } + handleError(error) { + this.contents = []; + this.errorMessage = 'System error retrieving page content (Server responded: ' + error + ')'; + } +} + +@Component({ + selector: 'app-aside-help-content', + template: ` + + +
+
+
+ `, +}) +export class AsideHelpContentComponent extends HelpContentComponent { +} diff --git a/dmp-frontend/src/app/ui/misc/help-content/help-content.module.ts b/dmp-frontend/src/app/ui/misc/help-content/help-content.module.ts new file mode 100644 index 000000000..ae67f9f8b --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/help-content/help-content.module.ts @@ -0,0 +1,14 @@ +import { NgModule } from '@angular/core'; +import { CommonUiModule } from '../../../common/ui/common-ui.module'; +import { HelpContentComponent } from './help-content.component'; + +@NgModule({ + imports: [ + CommonUiModule + ], + declarations: [ + HelpContentComponent + ], + exports: [HelpContentComponent] +}) +export class HelpContentModule { } diff --git a/dmp-frontend/src/app/ui/misc/navigation/navigation.component.html b/dmp-frontend/src/app/ui/misc/navigation/navigation.component.html new file mode 100644 index 000000000..18ad1ad85 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/navigation/navigation.component.html @@ -0,0 +1,55 @@ + + + + + + +
+
+ + + + + {{option.label}} +
+ {{transformType(option.type)}} +
+
+
+
+
+ +
+ +
+ +
+
+ +
+ + + + + +
+
+ +
diff --git a/dmp-frontend/src/app/ui/misc/navigation/navigation.component.scss b/dmp-frontend/src/app/ui/misc/navigation/navigation.component.scss new file mode 100644 index 000000000..e20917ac1 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/navigation/navigation.component.scss @@ -0,0 +1,33 @@ +@mixin navigation-component-theme($theme) { + $accent: map-get($theme, accent); + + .navigation-bar { + overflow: hidden; + position: fixed; + width: 100%; + top: 0; + left: 0; + z-index: 1000; + + .active { + color: mat-color($accent); + } + + .user-label { + font-size: 14px; + } + + .app-logo { + margin-right: 30px; + margin-left: 20px; + } + } + + .progress-bar { + top: 64px; + left: 0; + position: fixed; + width: 100%; + z-index: 1; + } +} diff --git a/dmp-frontend/src/app/ui/misc/navigation/navigation.component.ts b/dmp-frontend/src/app/ui/misc/navigation/navigation.component.ts new file mode 100644 index 000000000..2dd10b076 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/navigation/navigation.component.ts @@ -0,0 +1,130 @@ +import { Component, OnInit } from '@angular/core'; +import { FormControl } from '@angular/forms'; +import { MatDialog } from '@angular/material'; +import { Router } from '@angular/router'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../core/common/base/base.component'; +import { AppRole } from '../../../core/common/enum/app-role'; +import { SearchBarItem } from '../../../core/model/dashboard/search-bar-item'; +import { ProjectCriteria } from '../../../core/query/project/project-criteria'; +import { RequestItem } from '../../../core/query/request-item'; +import { AuthService } from '../../../core/services/auth/auth.service'; +import { ProgressIndicationService } from '../../../core/services/progress-indication/progress-indication-service'; +import { ProjectService } from '../../../core/services/project/project.service'; +import { SearchBarService } from '../../../core/services/search-bar/search-bar.service'; +import { SingleAutoCompleteConfiguration } from '../../../library/auto-complete/single/single-auto-complete-configuration'; +import { LanguageResolverService } from '../../../services/language-resolver/language-resolver.service'; +import { UserDialogComponent } from './user-dialog/user-dialog.component'; + +export enum SearchBarType { + Dataset = 0, + Dmp = 1, + Project = 2 +} + +@Component({ + selector: 'app-navigation', + templateUrl: 'navigation.component.html', + styleUrls: ['./navigation.component.scss'] +}) +export class NavigationComponent extends BaseComponent implements OnInit { + progressIndication = false; + public search = false; + projectAutoCompleteConfiguration: SingleAutoCompleteConfiguration; + public searchControl = new FormControl(); + filteredOptions: Observable; + + events: string[] = []; + opened: boolean; + constructor( + private authentication: AuthService, + private dialog: MatDialog, + private projectService: ProjectService, + private searchBarService: SearchBarService, + private router: Router, + private progressIndicationService: ProgressIndicationService, + public languageResolver: LanguageResolverService + ) { + super(); + } + + ngOnInit() { + this.progressIndicationService.getProgressIndicationObservable().pipe(takeUntil(this._destroyed)).subscribe(x => { + setTimeout(() => { this.progressIndication = x; }); + }); + + this.projectAutoCompleteConfiguration = { + filterFn: this.searchProject.bind(this), + initialItems: (extraData) => this.searchProject(''), + displayFn: (item) => item['label'], + titleFn: (item) => item['label'], + //mapFn: (item) => new JsonSerializer().fromJSONArray(item, ProjectReference).map(item => item.toDropdownList()), + loadDataOnStart: true + }; + + this.filteredOptions = this.searchControl.valueChanges.debounceTime(500).distinctUntilChanged().flatMap(x => { + return this.searchBarService.search(x); + }); + } + + searchProject(query: string) { + const projectRequestItem: RequestItem = new RequestItem(); + projectRequestItem.criteria = new ProjectCriteria(); + projectRequestItem.criteria.like = query; + return this.projectService.getWithExternal(projectRequestItem); + } + + public logout(): void { + this.authentication.logout(); + } + + public isAuthenticated(): boolean { + return !(!this.authentication.current()); + } + + public isAdmin(): boolean { + if (!this.authentication.current()) { return false; } + const principalRoles = this.authentication.current().authorities; + for (let i = 0; i < principalRoles.length; i++) { + if (principalRoles[i] === AppRole.Admin) { + return true; + } + } + return false; + } + + public principalHasAvatar(): boolean { + return this.authentication.current().avatarUrl != null; + } + + public getPrincipalAvatar(): string { + return this.authentication.current().avatarUrl; + } + + openProfile() { + const dialogRef = this.dialog.open(UserDialogComponent, { + hasBackdrop: true, + closeOnNavigation: true, + disableClose: false, + position: { top: '64px', left: '85%' } + }); + } + + onOptionSelected(event: any) { + this.search = false; + this.searchControl.patchValue(null); + const selectedSearchBarItem = event.option.value; + if (selectedSearchBarItem.type === SearchBarType.Dataset) { this.router.navigate(['datasets/edit/' + selectedSearchBarItem.id]); } + if (selectedSearchBarItem.type === SearchBarType.Project) { this.router.navigate(['projects/edit/' + selectedSearchBarItem.id]); } + if (selectedSearchBarItem.type === SearchBarType.Dmp) { this.router.navigate(['plans/edit/' + selectedSearchBarItem.id]); } + } + + transformType(type) { + switch (type) { + case SearchBarType.Dataset: return 'Dataset'; + case SearchBarType.Dmp: return 'DMP'; + case SearchBarType.Project: return 'Project'; + } + } +} diff --git a/dmp-frontend/src/app/ui/misc/navigation/navigation.module.ts b/dmp-frontend/src/app/ui/misc/navigation/navigation.module.ts new file mode 100644 index 000000000..796ee2ac9 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/navigation/navigation.module.ts @@ -0,0 +1,21 @@ +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { CommonFormsModule } from '../../../common/forms/common-forms.module'; +import { CommonUiModule } from '../../../common/ui/common-ui.module'; +import { NavigationComponent } from './navigation.component'; +import { UserDialogComponent } from './user-dialog/user-dialog.component'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule, + RouterModule + ], + declarations: [ + NavigationComponent, + UserDialogComponent + ], + entryComponents: [UserDialogComponent], + exports: [NavigationComponent] +}) +export class NavigationModule { } diff --git a/dmp-frontend/src/app/shared/components/user-dialog/user-dialog.component.html b/dmp-frontend/src/app/ui/misc/navigation/user-dialog/user-dialog.component.html similarity index 100% rename from dmp-frontend/src/app/shared/components/user-dialog/user-dialog.component.html rename to dmp-frontend/src/app/ui/misc/navigation/user-dialog/user-dialog.component.html diff --git a/dmp-frontend/src/app/ui/misc/navigation/user-dialog/user-dialog.component.ts b/dmp-frontend/src/app/ui/misc/navigation/user-dialog/user-dialog.component.ts new file mode 100644 index 000000000..5449e9ad2 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/navigation/user-dialog/user-dialog.component.ts @@ -0,0 +1,49 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { Router } from '@angular/router'; +import { Principal } from '../../../../core/model/auth/Principal'; +import { AuthService } from '../../../../core/services/auth/auth.service'; + +@Component({ + selector: 'app-user-dialog-component', + templateUrl: 'user-dialog.component.html', +}) +export class UserDialogComponent implements OnInit { + + public formGroup: FormGroup; + + constructor( + private authentication: AuthService, + private router: Router, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any + ) { } + + ngOnInit(): void { + } + + public logout(): void { + this.dialogRef.close(); + this.authentication.logout(); + } + + public getPrincipalName(): string { + const principal: Principal = this.authentication.current(); + if (principal) { return principal.name; } + return ''; + } + + public principalHasAvatar(): boolean { + return this.authentication.current() && this.authentication.current().avatarUrl != null; + } + + public getPrincipalAvatar(): string { + return this.authentication.current() && this.authentication.current().avatarUrl; + } + + public navigateToProfile() { + this.dialogRef.close(); + this.router.navigate(['/users/' + this.authentication.current().id]); + } +} diff --git a/dmp-frontend/src/app/unauthorized/unauthorized.component.html b/dmp-frontend/src/app/ui/misc/unauthorized/unauthorized.component.html similarity index 100% rename from dmp-frontend/src/app/unauthorized/unauthorized.component.html rename to dmp-frontend/src/app/ui/misc/unauthorized/unauthorized.component.html diff --git a/dmp-frontend/src/app/ui/misc/unauthorized/unauthorized.component.ts b/dmp-frontend/src/app/ui/misc/unauthorized/unauthorized.component.ts new file mode 100644 index 000000000..22233f4ef --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/unauthorized/unauthorized.component.ts @@ -0,0 +1,35 @@ +import { AfterViewInit, Component, Input } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { takeUntil } from 'rxjs/operators'; +import { BaseComponent } from '../../../core/common/base/base.component'; +import { AuthService } from '../../../core/services/auth/auth.service'; + +@Component({ + selector: 'app-unauthorized-component', + templateUrl: './unauthorized.component.html' +}) +export class UnauthorizedComponent extends BaseComponent implements AfterViewInit { + @Input() + public message: string; + constructor( + private authService: AuthService, + private route: ActivatedRoute, + private router: Router + ) { super(); } + + ngAfterViewInit() { + const returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/'; + const principal = this.authService.current(); + if (!principal) { + this.router.navigate(['/login'], { queryParams: { returnUrl: returnUrl } }); + } else { + this.authService.me() + .pipe(takeUntil(this._destroyed)) + .subscribe( + result => { + if (!result) { this.router.navigate(['/login'], { queryParams: { returnUrl: returnUrl } }); } else { this.router.navigate(['/']); } + }, + err => console.error('An error occurred', err)); + } + } +} diff --git a/dmp-frontend/src/app/ui/misc/unauthorized/unauthorized.module.ts b/dmp-frontend/src/app/ui/misc/unauthorized/unauthorized.module.ts new file mode 100644 index 000000000..c25f31acd --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/unauthorized/unauthorized.module.ts @@ -0,0 +1,15 @@ +import { NgModule } from "@angular/core"; +import { CommonUiModule } from "../../../common/ui/common-ui.module"; +import { UnauthorizedComponent } from "./unauthorized.component"; +import { UnauthorizedRoutingModule } from "./unauthorized.routes"; + +@NgModule({ + imports: [ + CommonUiModule, + UnauthorizedRoutingModule + ], + declarations: [ + UnauthorizedComponent, + ], +}) +export class UnauthorizedModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/misc/unauthorized/unauthorized.routes.ts b/dmp-frontend/src/app/ui/misc/unauthorized/unauthorized.routes.ts new file mode 100644 index 000000000..92ecc0fc0 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/unauthorized/unauthorized.routes.ts @@ -0,0 +1,16 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { UnauthorizedComponent } from './unauthorized.component'; + +const routes: Routes = [ + { + path: '', + component: UnauthorizedComponent + }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class UnauthorizedRoutingModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/project/editor/project-editor.component.html b/dmp-frontend/src/app/ui/project/editor/project-editor.component.html new file mode 100644 index 000000000..b23fc3d73 --- /dev/null +++ b/dmp-frontend/src/app/ui/project/editor/project-editor.component.html @@ -0,0 +1,104 @@ +
+ {{'PROJECT-EDITOR.TITLE.NEW' | translate}} + {{formGroup?.get('label')?.value}} +
+ + +
+ + + + + +
+ + + + +
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+ +
+ + + {{baseErrorModel.label}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + {{baseErrorModel.abbreviation}} + + + + + {{baseErrorModel.uri}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + + + {{this.project.errorModel.startDate}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + + + {{baseErrorModel.endDate}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + {{errorModel.description}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + +
+
+
+ +
+
+
+ +
+
+ +
+
+
+
+
+
+
+
diff --git a/dmp-frontend/src/app/ui/project/editor/project-editor.component.scss b/dmp-frontend/src/app/ui/project/editor/project-editor.component.scss new file mode 100644 index 000000000..9c5228133 --- /dev/null +++ b/dmp-frontend/src/app/ui/project/editor/project-editor.component.scss @@ -0,0 +1,20 @@ +.project-editor { + + .project-editor-header-actions { + display: flex; + align-items: center; + } + + .logo-table { + table-layout: fixed; + display: inline-block; + + td { + padding: 3px; + } + } + + .hidden { + display: none; + } +} diff --git a/dmp-frontend/src/app/ui/project/editor/project-editor.component.ts b/dmp-frontend/src/app/ui/project/editor/project-editor.component.ts new file mode 100644 index 000000000..d5127ce9c --- /dev/null +++ b/dmp-frontend/src/app/ui/project/editor/project-editor.component.ts @@ -0,0 +1,203 @@ +import { Component, OnInit } from '@angular/core'; +import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; +import { MatDialog, MatSnackBar } from '@angular/material'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { environment } from '../../../../environments/environment'; +import { BaseComponent } from '../../../core/common/base/base.component'; +import { ProjectType } from '../../../core/common/enum/project-type'; +import { ProjectModel } from '../../../core/model/project/project'; +import { ProjectFileUploadService } from '../../../core/services/project/project-file-upload.service'; +import { ProjectService } from '../../../core/services/project/project.service'; +import { ConfirmationDialogComponent } from '../../../library/confirmation-dialog/confirmation-dialog.component'; +import { SnackBarNotificationComponent } from '../../../library/notification/snack-bar/snack-bar-notification.component'; +import { BreadcrumbItem } from '../../misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '../../misc/breadcrumb/definition/IBreadCrumbComponent'; +import { ProjectEditorModel } from './project-editor.model'; + +@Component({ + selector: 'app-project-editor-component', + templateUrl: 'project-editor.component.html', + styleUrls: ['./project-editor.component.scss'] +}) +export class ProjectEditorComponent extends BaseComponent implements OnInit, IBreadCrumbComponent { + + breadCrumbs: Observable = Observable.of([]); + isNew = true; + project: ProjectEditorModel; + formGroup: FormGroup = null; + host = environment.Server; + editMode = false; + constructor( + private projectService: ProjectService, + private route: ActivatedRoute, + public snackBar: MatSnackBar, + public router: Router, + public language: TranslateService, + private dialog: MatDialog, + private projectFileUploadService: ProjectFileUploadService, + ) { + super(); + } + + ngOnInit() { + this.route.params + .pipe(takeUntil(this._destroyed)) + .subscribe((params: Params) => { + const itemId = params['id']; + + if (itemId != null) { + this.isNew = false; + this.projectService.getSingle(itemId).map(data => data as ProjectModel) + .pipe(takeUntil(this._destroyed)) + .subscribe(data => { + this.project = new ProjectEditorModel().fromModel(data); + this.formGroup = this.project.buildForm(null, this.project.type === ProjectType.External || !this.editMode); + this.breadCrumbs = Observable.of([ + { parentComponentName: 'ProjectListingComponent', label: 'Projects', url: '/projects' }, + ]); + }); + } else { + this.breadCrumbs = Observable.of([ + { parentComponentName: 'ProjectListingComponent', label: 'Projects', url: '/projects' }, + ]); + this.project = new ProjectEditorModel(); + setTimeout(() => { + this.formGroup = this.project.buildForm(); + }); + } + }); + } + + formSubmit(): void { + this.touchAllFormFields(this.formGroup); + if (!this.isFormValid()) { return; } + this.onSubmit(); + } + + public isFormValid() { + return this.formGroup.valid; + } + + onSubmit(): void { + this.projectService.createProject(this.formGroup.value) + .pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) + ); + } + + onCallbackSuccess(): void { + this.snackBar.openFromComponent(SnackBarNotificationComponent, { + data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, + duration: 3000, + }); + this.router.navigate(['/projects']); + } + + onCallbackError(errorResponse: any) { + this.setErrorModel(errorResponse.error.payload); + this.validateAllFormFields(this.formGroup); + } + + public setErrorModel(errorModel: BaseErrorModel) { + Object.keys(errorModel).forEach(item => { + (this.project.errorModel)[item] = (errorModel)[item]; + }); + } + + public cancel(): void { + this.router.navigate(['/projects']); + } + + public delete(): void { + const dialogRef = this.dialog.open(ConfirmationDialogComponent, { + maxWidth: '300px', + data: { + message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'), + confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'), + cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL') + } + }); + dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { + if (result) { + this.projectService.inactivate(this.project.id) + .pipe(takeUntil(this._destroyed)) + .subscribe( + complete => { this.onCallbackSuccess() }, + error => this.onCallbackError(error) + ); + } + }); + } + + public touchAllFormFields(formControl: AbstractControl) { + if (formControl instanceof FormControl) { + formControl.markAsTouched(); + } else if (formControl instanceof FormGroup) { + Object.keys(formControl.controls).forEach(item => { + const control = formControl.get(item); + this.touchAllFormFields(control); + }); + } else if (formControl instanceof FormArray) { + formControl.controls.forEach(item => { + this.touchAllFormFields(item); + }); + } + } + + public validateAllFormFields(formControl: AbstractControl) { + if (formControl instanceof FormControl) { + formControl.updateValueAndValidity({ emitEvent: false }); + } else if (formControl instanceof FormGroup) { + Object.keys(formControl.controls).forEach(item => { + const control = formControl.get(item); + this.validateAllFormFields(control); + }); + } else if (formControl instanceof FormArray) { + formControl.controls.forEach(item => { + this.validateAllFormFields(item); + }); + } + } + + public enableForm() { + if (!this.isExternalProject()) { + this.editMode = true; + this.formGroup.enable(); + } + } + + public disableForm() { + this.editMode = false; + this.formGroup.disable(); + } + + public goToProjectDmps() { + this.router.navigate(['plans/project/' + this.project.id], { queryParams: { projectLabel: this.project.label } }); + } + + public isExternalProject() { + return this.project.type === ProjectType.External; + } + + public previewImage(event): void { + const fileList: FileList | File = event.target.files; + + const formdata: FormData = new FormData(); + + if (fileList instanceof FileList) { + for (let i = 0; i < fileList.length; i++) { + formdata.append('file', fileList[i]); + } + } else { + formdata.append('file', fileList); + } + this.projectFileUploadService.uploadFile(formdata) + .pipe(takeUntil(this._destroyed)) + .subscribe(files => this.formGroup.get('files').patchValue(files)); + } +} diff --git a/dmp-frontend/src/app/ui/project/editor/project-editor.model.ts b/dmp-frontend/src/app/ui/project/editor/project-editor.model.ts new file mode 100644 index 000000000..071a373e0 --- /dev/null +++ b/dmp-frontend/src/app/ui/project/editor/project-editor.model.ts @@ -0,0 +1,74 @@ +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { BackendErrorValidator } from '../../../common/forms/validation/custom-validator'; +import { ValidationErrorModel } from '../../../common/forms/validation/error-model/validation-error-model'; +import { ValidationContext } from '../../../common/forms/validation/validation-context'; +import { ProjectType } from '../../../core/common/enum/project-type'; +import { Status } from '../../../core/common/enum/Status'; +import { ContentFile, ProjectModel } from '../../../core/model/project/project'; + +export class ProjectEditorModel { + public id: string; + public label: string; + public abbreviation: string; + public reference: string; + public type: ProjectType = ProjectType.Internal; + public uri: String; + public status: Status = Status.Active; + public startDate: Date; + public endDate: Date; + public description: String; + public contentUrl: string; + public files: ContentFile[]; + public errorModel: ValidationErrorModel = new ValidationErrorModel(); + + fromModel(item: ProjectModel): ProjectEditorModel { + this.id = item.id; + this.label = item.label; + this.type = item.type; + this.abbreviation = item.abbreviation; + this.reference = item.reference; + this.uri = item.uri; + this.status = item.status; + this.startDate = item.startDate ? new Date(item.startDate) : null; + this.endDate = item.endDate ? new Date(item.endDate) : null; + this.description = item.description; + this.contentUrl = item.contentUrl; + this.files = item.files; + return this; + } + + buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { + if (context == null) { context = this.createValidationContext(); } + + const formGroup = new FormBuilder().group({ + id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators], + label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators], + abbreviation: [{ value: this.abbreviation, disabled: disabled }, context.getValidation('abbreviation').validators], + uri: [{ value: this.uri, disabled: disabled }, context.getValidation('uri').validators], + status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators], + type: [{ value: this.type, disabled: disabled }, context.getValidation('type').validators], + description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators], + startDate: [{ value: this.startDate, disabled: disabled }, context.getValidation('startDate').validators], + endDate: [{ value: this.endDate, disabled: disabled }, context.getValidation('endDate').validators], + files: [{ value: this.files, disabled: disabled }, context.getValidation('files').validators] + }); + + return formGroup; + } + + createValidationContext(): ValidationContext { + const baseContext: ValidationContext = new ValidationContext(); + baseContext.validation.push({ key: 'id', validators: [] }); + baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'label')] }); + baseContext.validation.push({ key: 'abbreviation', validators: [BackendErrorValidator(this.errorModel, 'abbreviation')] }); + baseContext.validation.push({ key: 'uri', validators: [BackendErrorValidator(this.errorModel, 'uri')] }); + baseContext.validation.push({ key: 'type', validators: [BackendErrorValidator(this.errorModel, 'type')] }); + baseContext.validation.push({ key: 'status', validators: [] }); + baseContext.validation.push({ key: 'description', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'description')] }); + baseContext.validation.push({ key: 'startDate', validators: [BackendErrorValidator(this.errorModel, 'startDate')] }); + baseContext.validation.push({ key: 'endDate', validators: [BackendErrorValidator(this.errorModel, 'endDate')] }); + baseContext.validation.push({ key: 'files', validators: [BackendErrorValidator(this.errorModel, 'files')] }); + + return baseContext; + } +} diff --git a/dmp-frontend/src/app/ui/project/listing/criteria/project-criteria.component.html b/dmp-frontend/src/app/ui/project/listing/criteria/project-criteria.component.html new file mode 100644 index 000000000..6176fad9a --- /dev/null +++ b/dmp-frontend/src/app/ui/project/listing/criteria/project-criteria.component.html @@ -0,0 +1,33 @@ + +
+ + + + {{baseErrorModel['criteria.like']}} + + + + + + + {{baseErrorModel['criteria.periodStart']}} + + + + {{baseErrorModel['criteria.periodEnd']}} + + + + + + + + {{ 'CRITERIA.PROJECTS.TYPES.ON-GOING' | translate}} + + + {{ 'CRITERIA.PROJECTS.TYPES.FINISHED' | translate}} + + + +
+
diff --git a/dmp-frontend/src/app/shared/components/external-items/external-item/external-item.component.scss b/dmp-frontend/src/app/ui/project/listing/criteria/project-criteria.component.scss similarity index 100% rename from dmp-frontend/src/app/shared/components/external-items/external-item/external-item.component.scss rename to dmp-frontend/src/app/ui/project/listing/criteria/project-criteria.component.scss diff --git a/dmp-frontend/src/app/ui/project/listing/criteria/project-criteria.component.ts b/dmp-frontend/src/app/ui/project/listing/criteria/project-criteria.component.ts new file mode 100644 index 000000000..551c0d5c4 --- /dev/null +++ b/dmp-frontend/src/app/ui/project/listing/criteria/project-criteria.component.ts @@ -0,0 +1,49 @@ +import { Component, OnInit } from '@angular/core'; +import { FormBuilder } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { ValidationErrorModel } from '../../../../common/forms/validation/error-model/validation-error-model'; +import { ProjectStateType } from '../../../../core/common/enum/project-state-type'; +import { ProjectCriteria } from '../../../../core/query/project/project-criteria'; +import { LanguageResolverService } from '../../../../services/language-resolver/language-resolver.service'; +import { BaseCriteriaComponent } from '../../../misc/criteria/base-criteria.component'; + +@Component({ + selector: 'app-project-criteria-component', + templateUrl: './project-criteria.component.html', + styleUrls: ['./project-criteria.component.scss'] +}) +export class ProjectCriteriaComponent extends BaseCriteriaComponent implements OnInit { + + public ProjectStateType = ProjectStateType; + public criteria: ProjectCriteria = new ProjectCriteria(); + + constructor( + public language: TranslateService, + public formBuilder: FormBuilder, + public languageResolver: LanguageResolverService + ) { + super(new ValidationErrorModel()); + } + + ngOnInit() { + super.ngOnInit(); + if (this.criteria == null) { this.criteria = new ProjectCriteria(); } + } + + setCriteria(criteria: ProjectCriteria): void { + this.criteria = criteria; + } + + onCallbackError(error: any) { + this.setErrorModel(error.error); + } + + controlModified(): void { + this.clearErrorModel(); + if (this.refreshCallback != null && + (this.criteria.like == null || this.criteria.like.length === 0 || this.criteria.like.length > 2) + ) { + this.refreshCallback(); + } + } +} diff --git a/dmp-frontend/src/app/ui/project/listing/project-listing.component.html b/dmp-frontend/src/app/ui/project/listing/project-listing.component.html new file mode 100644 index 000000000..dc5140ef3 --- /dev/null +++ b/dmp-frontend/src/app/ui/project/listing/project-listing.component.html @@ -0,0 +1,68 @@ +
+

{{languageResolverService.getBy('listingTitle') | translate}}

+ + + +
+ + + + {{'PROJECT-LISTING.COLUMNS.AVATAR' | translate}} + + + + + + + {{'PROJECT-LISTING.COLUMNS.NAME' | translate}} + {{row.label}} + + + + + {{'PROJECT-LISTING.COLUMNS.ABBREVIATION' | + translate}} + {{row.abbreviation}} + + + + + {{'PROJECT-LISTING.COLUMNS.START' | translate}} + {{row.startDate | date:'shortDate'}} + + + + + {{'PROJECT-LISTING.COLUMNS.END' | translate}} + {{row.endDate | date:'shortDate'}} + + + + + {{'PROJECT-LISTING.COLUMNS.DMPS' | translate}} + + + + + + + + + + + + + + + +
+
+
+ + +
diff --git a/dmp-frontend/src/app/ui/project/listing/project-listing.component.scss b/dmp-frontend/src/app/ui/project/listing/project-listing.component.scss new file mode 100644 index 000000000..3056f0982 --- /dev/null +++ b/dmp-frontend/src/app/ui/project/listing/project-listing.component.scss @@ -0,0 +1,25 @@ + .project-listing { + .mat-card { + margin: 1em 0; + } + + .mat-row { + cursor: pointer; + } + + mat-row:hover { + background-color: lightgray; + } + + mat-row:nth-child(odd) { + background-color: #eef0fb; + } + + .mat-fab-bottom-right { + top: auto !important; + right: 20px !important; + bottom: 10px !important; + left: auto !important; + position: fixed !important; + } + } diff --git a/dmp-frontend/src/app/ui/project/listing/project-listing.component.ts b/dmp-frontend/src/app/ui/project/listing/project-listing.component.ts new file mode 100644 index 000000000..457ee4230 --- /dev/null +++ b/dmp-frontend/src/app/ui/project/listing/project-listing.component.ts @@ -0,0 +1,142 @@ +import { DataSource } from '@angular/cdk/table'; +import { Component, OnInit, ViewChild } from '@angular/core'; +import { MatPaginator, MatSnackBar, MatSort } from '@angular/material'; +import { Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { environment } from '../../../../environments/environment'; +import { ProjectStateType } from '../../../core/common/enum/project-state-type'; +import { ProjectListingModel } from '../../../core/model/project/project-listing'; +import { ProjectCriteria } from '../../../core/query/project/project-criteria'; +import { ProjectService } from '../../../core/services/project/project.service'; +import { DataTableRequest } from '../../../core/model/data-table/data-table-request'; +import { LanguageResolverService } from '../../../services/language-resolver/language-resolver.service'; +import { BreadcrumbItem } from '../../misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '../../misc/breadcrumb/definition/IBreadCrumbComponent'; +import { ProjectCriteriaComponent } from './criteria/project-criteria.component'; + +@Component({ + selector: 'app-project-listing-component', + templateUrl: 'project-listing.component.html', + styleUrls: ['./project-listing.component.scss'] +}) +export class ProjectListingComponent implements OnInit, IBreadCrumbComponent { + + public breadCrumbs: Observable = Observable.of([]); + + @ViewChild(MatPaginator) _paginator: MatPaginator; + @ViewChild(MatSort) sort: MatSort; + @ViewChild(ProjectCriteriaComponent) criteria: ProjectCriteriaComponent; + + host = environment.Server; + dataSource: ProjectDataSource | null; + displayedColumns: String[] = ['avatar', 'name', 'abbreviation', 'start', 'end', 'dmps']; + + constructor( + public projectService: ProjectService, + public router: Router, + public languageService: TranslateService, + public snackBar: MatSnackBar, + public languageResolverService: LanguageResolverService + ) { + + } + + ngOnInit() { + this.breadCrumbs = Observable.of([]); + + this.criteria.setCriteria(this.getDefaultCriteria()); + this.refresh(); + this.criteria.setRefreshCallback(() => this.refresh()); + } + + refresh() { + this.dataSource = new ProjectDataSource(this.projectService, this._paginator, this.sort, this.languageService, this.snackBar, this.criteria); + } + + rowClick(rowId: String) { + this.router.navigate(['/projects/edit/' + rowId]); + } + + getDefaultCriteria(): ProjectCriteria { + const defaultCriteria = new ProjectCriteria(); + defaultCriteria.projectStateType = ProjectStateType.OnGoing; + return defaultCriteria; + } +} + +export class ProjectDataSource extends DataSource { + + totalCount = 0; + + constructor( + private _service: ProjectService, + private _paginator: MatPaginator, + private _sort: MatSort, + private _languageService: TranslateService, + private _snackBar: MatSnackBar, + private _criteria: ProjectCriteriaComponent + ) { + super(); + + //this._paginator.page.pipe(takeUntil(this._destroyed)).subscribe((pageEvent: PageEvent) => { + // this.store.dispatch(new LoadPhotosRequestAction(pageEvent.pageIndex, pageEvent.pageSize)) + //}) + } + + connect(): Observable { + const displayDataChanges = [ + this._paginator.page + //this._sort.matSortChange + ]; + + // If the user changes the sort order, reset back to the first page. + //this._sort.matSortChange.pipe(takeUntil(this._destroyed)).subscribe(() => { + // this._paginator.pageIndex = 0; + //}) + + return Observable.merge(...displayDataChanges) + .startWith(null) + .switchMap(() => { + const startIndex = this._paginator.pageIndex * this._paginator.pageSize; + let fields: Array = new Array(); + if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; } + const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); + request.criteria = this._criteria.criteria; + return this._service.getPaged(request); + }) + /*.catch((error: any) => { + this._snackBar.openFromComponent(SnackBarNotificationComponent, { + data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService }, + duration: 3000, + extraClasses: ['snackbar-warning'] + }); + this._criteria.onCallbackError(error.error); + return Observable.of(null); + })*/ + .map(result => { + result.data = result.data; + return result; + }) + .map(result => { + return result; + }) + .map(result => { + if (!result) { return []; } + if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; } + return result.data.map(item => { + item.dmps.map(dmp => { + dmp.url = 'plans/edit/' + dmp.url; + dmp.all = 'plans/project/' + item.id; + return dmp; + }); + return item; + }); + }); + + } + + disconnect() { + // No-op + } +} diff --git a/dmp-frontend/src/app/ui/project/project.module.ts b/dmp-frontend/src/app/ui/project/project.module.ts new file mode 100644 index 000000000..2b31c5f29 --- /dev/null +++ b/dmp-frontend/src/app/ui/project/project.module.ts @@ -0,0 +1,25 @@ +import { NgModule } from '@angular/core'; +import { CommonFormsModule } from '../../common/forms/common-forms.module'; +import { CommonUiModule } from '../../common/ui/common-ui.module'; +import { ConfirmationDialogModule } from '../../library/confirmation-dialog/confirmation-dialog.module'; +import { UrlListingModule } from '../../library/url-listing/url-listing.module'; +import { ProjectEditorComponent } from './editor/project-editor.component'; +import { ProjectCriteriaComponent } from './listing/criteria/project-criteria.component'; +import { ProjectListingComponent } from './listing/project-listing.component'; +import { ProjectRoutingModule } from './project.routing'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule, + UrlListingModule, + ConfirmationDialogModule, + ProjectRoutingModule + ], + declarations: [ + ProjectListingComponent, + ProjectCriteriaComponent, + ProjectEditorComponent + ] +}) +export class ProjectModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/project/project.routing.ts b/dmp-frontend/src/app/ui/project/project.routing.ts new file mode 100644 index 000000000..54d255a6b --- /dev/null +++ b/dmp-frontend/src/app/ui/project/project.routing.ts @@ -0,0 +1,34 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { ProjectEditorComponent } from './editor/project-editor.component'; +import { ProjectListingComponent } from './listing/project-listing.component'; + +const routes: Routes = [ + { + path: '', + component: ProjectListingComponent, + data: { + breadcrumb: true + }, + }, + { + path: 'edit/:id', + component: ProjectEditorComponent, + data: { + breadcrumb: true + } + }, + { + path: 'new', + component: ProjectEditorComponent, + data: { + breadcrumb: true + }, + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class ProjectRoutingModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/user-profile/user-profile.component.html b/dmp-frontend/src/app/ui/user-profile/user-profile.component.html new file mode 100644 index 000000000..552851e2c --- /dev/null +++ b/dmp-frontend/src/app/ui/user-profile/user-profile.component.html @@ -0,0 +1,89 @@ +
+ + +
+
+ +
+ {{userProfile.name}} + {{userProfile.email}} +
+
+
+ + +
+
+

{{ 'USER-PROFILE.ASSOCIATED-DMPS' | translate}}

+
+
+ + +
+ {{ dmp.label }} +
+
+ + {{ getUserRole(dmp) }} + +
+
+
+ +
+
+
+
+ + + +

{{ 'USER-PROFILE.SETTINGS.TITLE' | translate}}

+ + +
+
+ +
+
+
+ + + + + {{ timezone | timezoneInfoDisplay }} + + + +
+
+ + + + + {{ culture.displayName }} - {{ culture.nativeName }} + + + +
+
+ + + + {{ language.label }} + + + +
+
+
+
+
+
+ + diff --git a/dmp-frontend/src/app/users/profile/user-profile.component.scss b/dmp-frontend/src/app/ui/user-profile/user-profile.component.scss similarity index 100% rename from dmp-frontend/src/app/users/profile/user-profile.component.scss rename to dmp-frontend/src/app/ui/user-profile/user-profile.component.scss diff --git a/dmp-frontend/src/app/ui/user-profile/user-profile.component.ts b/dmp-frontend/src/app/ui/user-profile/user-profile.component.ts new file mode 100644 index 000000000..481ac0190 --- /dev/null +++ b/dmp-frontend/src/app/ui/user-profile/user-profile.component.ts @@ -0,0 +1,135 @@ +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import * as moment from 'moment-timezone'; +import { takeUntil } from 'rxjs/operators'; +import { Observable } from 'rxjs/Rx'; +import { BaseComponent } from '../../core/common/base/base.component'; +import { CultureInfo } from '../../core/model/culture-info'; +import { UserListingModel } from '../../core/model/user/user-listing'; +import { AuthService } from '../../core/services/auth/auth.service'; +import { CultureService } from '../../core/services/culture/culture-service'; +import { UserService } from '../../core/services/user/user.service'; +import { DmpModel } from '../../core/model/dmp/dmp'; + +const availableLanguages: any[] = require('../../../assets/resources/language.json'); + +@Component({ + selector: 'app-user-profile', + templateUrl: './user-profile.component.html', + styleUrls: ['./user-profile.component.scss'], +}) +export class UserProfileComponent extends BaseComponent implements OnInit, OnDestroy { + + user: Observable; + currentUserId: string; + cultures: Observable; + timezones: Observable; + editMode = false; + languages = availableLanguages; + + formGroup: FormGroup; + constructor( + private userService: UserService, + private route: ActivatedRoute, + private router: Router, + private authService: AuthService, + private language: TranslateService, + private cultureService: CultureService, + private translate: TranslateService, + ) { super(); } + + ngOnInit() { + this.route.params + .pipe(takeUntil(this._destroyed)) + .subscribe((params: Params) => { + this.currentUserId = params['id']; + const userId = params['id'] === this.authService.current().id ? 'me' : params['id']; + this.user = this.userService.getUser(userId).map(result => { + result['additionalinfo'] = JSON.parse(result['additionalinfo']); + this.formGroup = new FormBuilder().group({ + language: new FormControl(result['additionalinfo']['language'] ? availableLanguages.filter(x => x.value === result['additionalinfo']['language']['value']).pop() : ''), + timezone: new FormControl(result['additionalinfo']['timezone']), + culture: new FormControl(result['additionalinfo']['culture']) + }); + //this.formGroup.get('language').valueChanges.pipe(takeUntil(this._destroyed)).subscribe(x => { if (x) this.translate.use(x.value) }) + this.formGroup.get('timezone').valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => { if (x) { this.timezones = this._filterTimezone(x); } }); + this.formGroup.get('culture').valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => { if (x) { this.cultures = this._filterCulture(x); } }); + this.formGroup.disable(); + return result; + }); + }); + + } + + ngOnDestroy(): void { + } + + getUserRole(dmp: DmpModel) { + if (dmp.creator.id === this.currentUserId) { return this.language.instant('USER-PROFILE.DMPS.CREATOR'); } else if (dmp.associatedUsers.map(x => x.id).indexOf(this.currentUserId) !== -1) { return this.language.instant('USER-PROFILE.DMPS.MEMBER'); } + return ''; + } + + showAllDmps() { + this.router.navigate(['/plans']); + } + + navigateToDmp(dmp: DmpModel) { + this.router.navigate(['/plans/edit/' + dmp.id]); + } + + private _filterTimezone(value: string): Observable { + if (value && typeof value === 'string') { + const filterValue = value.toLowerCase(); + return Observable.of(moment.tz.names().filter(option => option.toLowerCase().includes(filterValue))); + } else { + return Observable.of(moment.tz.names()); + } + } + + private _filterCulture(value: string): Observable { + if (value && typeof value === 'string') { + const filterValue = value.toLowerCase(); + return Observable.of(this.cultureService.getCultureValues().filter(option => option.displayName.toLowerCase().includes(filterValue))); + } else { + return Observable.of(this.cultureService.getCultureValues()); + } + } + + displayFn(culture?: CultureInfo): string | undefined { + return culture ? culture.displayName + '-' + culture.nativeName : undefined; + } + + save() { + + } + + public unlock() { + this.editMode = true; + this.formGroup.enable(); + } + + public lock() { + this.userService.updateUserSettings(this.formGroup.value) + .pipe(takeUntil(this._destroyed)) + .subscribe( + x => { + this.editMode = false; + this.translate.use(this.formGroup.value.language); + this.authService.current().culture = this.formGroup.value.culture.name; + this.formGroup.disable(); + this.authService.me() + .pipe(takeUntil(this._destroyed)) + .subscribe(result => window.location.reload()); + }, + error => { + console.log(error); + }); + } + +} diff --git a/dmp-frontend/src/app/ui/user-profile/user-profile.module.ts b/dmp-frontend/src/app/ui/user-profile/user-profile.module.ts new file mode 100644 index 000000000..50a750072 --- /dev/null +++ b/dmp-frontend/src/app/ui/user-profile/user-profile.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from '@angular/core'; +import { CommonFormsModule } from '../../common/forms/common-forms.module'; +import { CommonUiModule } from '../../common/ui/common-ui.module'; +import { FormattingModule } from '../../core/formatting.module'; +import { UserProfileComponent } from './user-profile.component'; +import { UserProfileRoutingModule } from './user-profile.routing'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule, + FormattingModule, + UserProfileRoutingModule + ], + declarations: [ + UserProfileComponent + ] +}) +export class ProjectModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/user-profile/user-profile.routing.ts b/dmp-frontend/src/app/ui/user-profile/user-profile.routing.ts new file mode 100644 index 000000000..0e55168e8 --- /dev/null +++ b/dmp-frontend/src/app/ui/user-profile/user-profile.routing.ts @@ -0,0 +1,19 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { UserProfileComponent } from './user-profile.component'; + +const routes: Routes = [ + { + path: '', + component: UserProfileComponent, + data: { + breadcrumb: true + }, + }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class UserProfileRoutingModule { } \ No newline at end of file diff --git a/dmp-frontend/src/app/unauthorized/unauthorized.component.js.map b/dmp-frontend/src/app/unauthorized/unauthorized.component.js.map deleted file mode 100644 index c61b89104..000000000 --- a/dmp-frontend/src/app/unauthorized/unauthorized.component.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"unauthorized.component.js","sourceRoot":"","sources":["unauthorized.component.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAMzD,IAAa,qBAAqB;IAG9B,+BACY,WAAwB,EACxB,KAAqB,EACrB,MAAc;QAFd,gBAAW,GAAX,WAAW,CAAa;QACxB,UAAK,GAAL,KAAK,CAAgB;QACrB,WAAM,GAAN,MAAM,CAAQ;IACtB,CAAC;IAEL,+CAAe,GAAf;QAAA,iBAaC;QAZG,IAAI,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC;QACpE,IAAI,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QAC3C,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;YACb,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;QAChF,CAAC;QACD,IAAI,CAAC,CAAC;YACF,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,SAAS,CAC3B,UAAA,SAAS;gBACL,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;oBAAC,KAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;YAChG,CAAC,EACD,UAAA,GAAG,IAAI,OAAA,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,GAAG,CAAC,EAAvC,CAAuC,CAAC,CAAC;QACxD,CAAC;IACL,CAAC;IACL,4BAAC;AAAD,CAAC,AAvBD,IAuBC;AArBG;IADC,KAAK,EAAE;;sDACe;AAFd,qBAAqB;IAJjC,SAAS,CAAC;QACP,QAAQ,EAAE,wBAAwB;QAClC,WAAW,EAAE,+BAA+B;KAC/C,CAAC;qCAK2B,WAAW;QACjB,cAAc;QACb,MAAM;GANjB,qBAAqB,CAuBjC;SAvBY,qBAAqB"} \ No newline at end of file diff --git a/dmp-frontend/src/app/unauthorized/unauthorized.component.ts b/dmp-frontend/src/app/unauthorized/unauthorized.component.ts deleted file mode 100644 index 19ed8a28a..000000000 --- a/dmp-frontend/src/app/unauthorized/unauthorized.component.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { AfterViewInit, Component, Input } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../core/common/base/base.component'; -import { AuthService } from '../services/auth/auth.service'; - -@Component({ - selector: 'app-unauthorized-component', - templateUrl: './unauthorized.component.html' -}) -export class UnauthorizedComponent extends BaseComponent implements AfterViewInit { - @Input() - public message: string; - constructor( - private authService: AuthService, - private route: ActivatedRoute, - private router: Router - ) { super(); } - - ngAfterViewInit() { - const returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/'; - const principal = this.authService.current(); - if (!principal) { - this.router.navigate(['/login'], { queryParams: { returnUrl: returnUrl } }); - } else { - this.authService.me() - .pipe(takeUntil(this._destroyed)) - .subscribe( - result => { - if (!result) { this.router.navigate(['/login'], { queryParams: { returnUrl: returnUrl } }); } else { this.router.navigate(['/']); } - }, - err => console.error('An error occurred', err)); - } - } -} diff --git a/dmp-frontend/src/app/unauthorized/unauthorized.module.js.map b/dmp-frontend/src/app/unauthorized/unauthorized.module.js.map deleted file mode 100644 index 126948b9d..000000000 --- a/dmp-frontend/src/app/unauthorized/unauthorized.module.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"unauthorized.module.js","sourceRoot":"","sources":["unauthorized.module.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAmBtD,IAAa,kBAAkB;IAA/B;IAAkC,CAAC;IAAD,yBAAC;AAAD,CAAC,AAAnC,IAAmC;AAAtB,kBAAkB;IAlB9B,QAAQ,CAAC;QACN,OAAO,EAAE;YACL,YAAY;YACZ,WAAW;YACX,gBAAgB;YAChB,kBAAkB;YAClB,YAAY;SACf;QAED,YAAY,EAAE;YACV,qBAAqB;SACxB;QAED,OAAO,EAAE;YACL,qBAAqB;SACxB;KACJ,CAAC;GAEW,kBAAkB,CAAI;SAAtB,kBAAkB"} \ No newline at end of file diff --git a/dmp-frontend/src/app/unauthorized/unauthorized.module.ts b/dmp-frontend/src/app/unauthorized/unauthorized.module.ts deleted file mode 100644 index 88f866139..000000000 --- a/dmp-frontend/src/app/unauthorized/unauthorized.module.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { HttpClientModule } from '@angular/common/http'; -import { NgModule } from '@angular/core'; -import { FormsModule } from '@angular/forms'; - -import { UnauthorizedComponent } from './unauthorized.component'; -import { UnauthorizedRoutes } from './unauthorized.routes'; -import { SharedModule } from '../shared/shared.module'; -@NgModule({ - imports: [ - CommonModule, - FormsModule, - HttpClientModule, - UnauthorizedRoutes, - SharedModule - ], - - declarations: [ - UnauthorizedComponent - ], - - exports: [ - UnauthorizedComponent - ] -}) - -export class UnauthorizedModule { } diff --git a/dmp-frontend/src/app/unauthorized/unauthorized.routes.js.map b/dmp-frontend/src/app/unauthorized/unauthorized.routes.js.map deleted file mode 100644 index 8a1dbc929..000000000 --- a/dmp-frontend/src/app/unauthorized/unauthorized.routes.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"unauthorized.routes.js","sourceRoot":"","sources":["unauthorized.routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAU,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,IAAM,MAAM,GAAW;IACnB,EAAE,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,qBAAqB,EAAE;CACjD,CAAC;AAEF,MAAM,CAAC,IAAM,kBAAkB,GAAG,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC"} \ No newline at end of file diff --git a/dmp-frontend/src/app/unauthorized/unauthorized.routes.ts b/dmp-frontend/src/app/unauthorized/unauthorized.routes.ts deleted file mode 100644 index e79aa982f..000000000 --- a/dmp-frontend/src/app/unauthorized/unauthorized.routes.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { RouterModule, Routes } from '@angular/router'; - -import { UnauthorizedComponent } from './unauthorized.component'; - -const routes: Routes = [ - { path: '', component: UnauthorizedComponent } -]; - -export const UnauthorizedRoutes = RouterModule.forChild(routes); diff --git a/dmp-frontend/src/app/user-management/admin-login/admin-login.component.ts b/dmp-frontend/src/app/user-management/admin-login/admin-login.component.ts deleted file mode 100644 index 7348cae3b..000000000 --- a/dmp-frontend/src/app/user-management/admin-login/admin-login.component.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Credential } from '../../models/login/Credential'; -import { LoginOptions } from '../utilties/LoginOptions'; -import { LoginService } from '../utilties/login-service'; -import { HttpClient } from '@angular/common/http'; -import { Component, OnInit, ElementRef, AfterViewInit, VERSION, Injectable, NgZone } from '@angular/core'; -import { Router, ActivatedRoute, Params } from '@angular/router'; -import { MatPaginator, MatSort, MatSnackBar } from '@angular/material'; -import { TranslateService } from '@ngx-translate/core'; - - - -@Component({ - selector: 'app-admin-login', - templateUrl: './admin-login.component.html', - styleUrls: ['./admin-login.component.scss'] -}) -export class AdminLoginComponent implements OnInit { - - public auth2: any; - public credential: Credential = new Credential(); - - constructor( - private loginService: LoginService - ) { } - - - - ngOnInit() { - } - - public nativeLogin() { - this.loginService.nativeLogin(this.credential); - } - -} diff --git a/dmp-frontend/src/app/user-management/login.module.ts b/dmp-frontend/src/app/user-management/login.module.ts deleted file mode 100644 index 7eb95e2a4..000000000 --- a/dmp-frontend/src/app/user-management/login.module.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { FormsModule } from '@angular/forms'; -import { TwitterLoginComponent } from './login/twitter-login/twitter-login.component'; -import { SnackBarNotificationComponent } from '../shared/components/notificaiton/snack-bar-notification.component'; -import { LinkedInLoginComponent } from './login/linkedin-login/linkedin-login.component'; -import { LoginRoutes } from './login.routes'; -import { MaterialModule } from '../shared/material/material.module'; -import { SharedModule } from '../shared/shared.module'; -import { LoginServiceConfiguration } from './utilties/LoginServiceConfiguration'; -import { LoginService } from './utilties/login-service'; -import { LoginComponent } from './login/login.component'; -import { ModuleWithProviders, NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { AdminLoginComponent } from '../user-management/admin-login/admin-login.component'; - -@NgModule({ - imports: [ - SharedModule, - CommonModule, - LoginRoutes, - FormsModule - ], - declarations: [ - LoginComponent, - LinkedInLoginComponent, - TwitterLoginComponent, - AdminLoginComponent - ], - exports: [ - LoginComponent, - LinkedInLoginComponent, - TwitterLoginComponent, - AdminLoginComponent - ], - providers: [LoginService] -}) -export class LoginModule { - static forRoot(config: LoginServiceConfiguration): ModuleWithProviders { - return { - ngModule: LoginModule, - providers: [ - { provide: LoginServiceConfiguration, useValue: config } - ], - }; - } -} diff --git a/dmp-frontend/src/app/user-management/login.routes.ts b/dmp-frontend/src/app/user-management/login.routes.ts deleted file mode 100644 index c4446518a..000000000 --- a/dmp-frontend/src/app/user-management/login.routes.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { TwitterLoginComponent } from './login/twitter-login/twitter-login.component'; -import { LinkedInLoginComponent } from './login/linkedin-login/linkedin-login.component'; -import { LoginComponent } from './login/login.component'; -import { RouterModule, Routes } from '@angular/router'; -import { AdminLoginComponent } from '../user-management/admin-login/admin-login.component'; - -const routes: Routes = [ - { path: 'login', component: LoginComponent }, - { path: 'login/admin', component: AdminLoginComponent }, - { path: 'login/linkedin', component: LinkedInLoginComponent }, - { path: 'login/twitter', component: TwitterLoginComponent } -]; - -export const LoginRoutes = RouterModule.forChild(routes); diff --git a/dmp-frontend/src/app/user-management/login/b2access/b2access-login.component.ts b/dmp-frontend/src/app/user-management/login/b2access/b2access-login.component.ts deleted file mode 100644 index 61953b7df..000000000 --- a/dmp-frontend/src/app/user-management/login/b2access/b2access-login.component.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { LoginService } from '../../utilties/login-service'; - -@Component({ - selector: 'app-b2access-login', - templateUrl: './b2access-login.component.html', -}) -export class B2AccessLoginComponent extends BaseComponent implements OnInit { - - constructor( - private router: Router, - private route: ActivatedRoute, - private loginService: LoginService - ) { - super(); - } - - ngOnInit(): void { - this.route.queryParams - .pipe(takeUntil(this._destroyed)) - .subscribe((data: any) => { - if (!data['code']) { this.loginService.b2AccessGetAuthCode(); } else { this.loginService.b2AccessLogin(data['code']); } - }); - } - -} diff --git a/dmp-frontend/src/app/user-management/login/linkedin-login/linkedin-login.component.ts b/dmp-frontend/src/app/user-management/login/linkedin-login/linkedin-login.component.ts deleted file mode 100644 index 2fb3ab8e4..000000000 --- a/dmp-frontend/src/app/user-management/login/linkedin-login/linkedin-login.component.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { LoginService } from '../../utilties/login-service'; - -@Component({ - selector: 'app-linkedin-login', - templateUrl: './linkedin-login.component.html', -}) -export class LinkedInLoginComponent extends BaseComponent implements OnInit { - - constructor( - private router: Router, - private route: ActivatedRoute, - private loginService: LoginService - ) { - super(); - } - - ngOnInit(): void { - this.route.queryParams - .pipe(takeUntil(this._destroyed)) - .subscribe((data: any) => { - if (!data['code']) { this.loginService.linkedinAuthorize(); } else { this.loginService.linkedInloginUser(data['code']); } - }); - } - -} diff --git a/dmp-frontend/src/app/user-management/login/login.component.html b/dmp-frontend/src/app/user-management/login/login.component.html deleted file mode 100644 index f4be1e6e4..000000000 --- a/dmp-frontend/src/app/user-management/login/login.component.html +++ /dev/null @@ -1,48 +0,0 @@ -
-
-
-
-

Login

- - -
-
- -
-
- email - - - -
-
- lock_outline - - - -
-
- -
-

You dont need to have a registered account for OpenDMP

-
-
-
diff --git a/dmp-frontend/src/app/user-management/login/login.component.ts b/dmp-frontend/src/app/user-management/login/login.component.ts deleted file mode 100644 index a3718aaa9..000000000 --- a/dmp-frontend/src/app/user-management/login/login.component.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Credential } from '../../models/login/Credential'; -import { LoginOptions } from '../utilties/LoginOptions'; -import { LoginService } from '../utilties/login-service'; -import { HttpClient } from '@angular/common/http'; -import { Component, OnInit, ElementRef, AfterViewInit, VERSION, Injectable, NgZone } from '@angular/core'; -import { Router, ActivatedRoute, Params } from '@angular/router'; -import { MatPaginator, MatSort, MatSnackBar } from '@angular/material'; -import { TranslateService } from '@ngx-translate/core'; - - - -@Component({ - selector: 'app-login', - templateUrl: './login.component.html', - styleUrls: ['./login.component.scss'] -}) -export class LoginComponent implements AfterViewInit { - - public auth2: any; - public credential: Credential = new Credential(); - - constructor( - private loginService: LoginService - ) { - } - - ngAfterViewInit() { - this.loginService.initProviders(); - } - - public facebookLogin() { - this.loginService.facebookLogin(); - } - - public linkedInLogin() { - this.loginService.linkedInInitialiseLogin(); - } - - public twitterLogin() { - this.loginService.twitterInitialiseLogin(); - } - - public nativeLogin() { - this.loginService.nativeLogin(this.credential); - } - - public b2AccessLogin() { - return this.loginService.b2AccessInitialiseLogin(); - } - - public hasFacebookOauth(): boolean { - return this.loginService.hasProvider(LoginOptions.facebookOauth); - } - - public hasLinkedInOauth(): boolean { - return this.loginService.hasProvider(LoginOptions.linkedInOauth); - } - - public hasTwitterOauth(): boolean { - return this.loginService.hasProvider(LoginOptions.twitterOauth); - } - - public hasGoogleOauth(): boolean { - return this.loginService.hasProvider(LoginOptions.googleOauth); - } - - public hasNativeLogin(): boolean { - return this.loginService.hasProvider(LoginOptions.nativeLogin); - } - - public hasB2AccessOauth(): boolean { - return this.loginService.hasProvider(LoginOptions.b2Access); - } - -} diff --git a/dmp-frontend/src/app/user-management/login/twitter-login/twitter-login.component.ts b/dmp-frontend/src/app/user-management/login/twitter-login/twitter-login.component.ts deleted file mode 100644 index 46e1a0420..000000000 --- a/dmp-frontend/src/app/user-management/login/twitter-login/twitter-login.component.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { LoginService } from '../../utilties/login-service'; -@Component({ - selector: 'app-twitter-login', - templateUrl: './twitter-login.component.html', -}) -export class TwitterLoginComponent extends BaseComponent implements OnInit { - constructor( - private router: Router, - private route: ActivatedRoute, - private loginService: LoginService - ) { - super(); - } - - ngOnInit(): void { - this.route.queryParams - .pipe(takeUntil(this._destroyed)) - .subscribe((data: any) => { - if (!data['oauth_token'] && !data['oauth_verifier']) { this.loginService.twitterAuthorize(); } else { this.loginService.twitterLogin(data['oauth_token'], data['oauth_verifier']); } - }); - } - -} diff --git a/dmp-frontend/src/app/user-management/utilties/LoginOptions.ts b/dmp-frontend/src/app/user-management/utilties/LoginOptions.ts deleted file mode 100644 index 31923a66d..000000000 --- a/dmp-frontend/src/app/user-management/utilties/LoginOptions.ts +++ /dev/null @@ -1,9 +0,0 @@ -export enum LoginOptions { - linkedInOauth = 1, - facebookOauth = 2, - twitterOauth = 3, - googleOauth = 4, - nativeLogin = 5, - b2Access = 6, - all = 7, -} diff --git a/dmp-frontend/src/app/user-management/utilties/LoginProviderConfiguration.ts b/dmp-frontend/src/app/user-management/utilties/LoginProviderConfiguration.ts deleted file mode 100644 index 1ed091a81..000000000 --- a/dmp-frontend/src/app/user-management/utilties/LoginProviderConfiguration.ts +++ /dev/null @@ -1,23 +0,0 @@ -export abstract class LoginProviderConfiguration { - public clientId: string; -} - -export class FacebookLoginConfiguration extends LoginProviderConfiguration { -} - -export class GoogleLoginConfiguration extends LoginProviderConfiguration { -} - -export class TwitterLoginConfiguration extends LoginProviderConfiguration { - public oauthUrl: string; -} - -export class LinkedInConfiguration extends LoginProviderConfiguration { - public oauthUrl: string; - public redirectUri: string; -} - -export class B2AccessConfiguration extends LoginProviderConfiguration { - public oauthUrl: string; - public redirectUri: string; -} diff --git a/dmp-frontend/src/app/user-management/utilties/LoginServiceConfiguration.ts b/dmp-frontend/src/app/user-management/utilties/LoginServiceConfiguration.ts deleted file mode 100644 index 87560c1ef..000000000 --- a/dmp-frontend/src/app/user-management/utilties/LoginServiceConfiguration.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { - FacebookLoginConfiguration, - GoogleLoginConfiguration, - LinkedInConfiguration, - TwitterLoginConfiguration, - B2AccessConfiguration, -} from './LoginProviderConfiguration'; -import { LoginOptions } from './LoginOptions'; -export class LoginServiceConfiguration { - public loginProviders: LoginOptions[]; - public facebookConfiguration?: FacebookLoginConfiguration; - public googleConfiguration?: GoogleLoginConfiguration; - public twitterConfiguration?: TwitterLoginConfiguration; - public linkedInConfiguration?: LinkedInConfiguration; - public b2accessConfiguration?: B2AccessConfiguration; -} diff --git a/dmp-frontend/src/app/user-management/utilties/login-service.ts b/dmp-frontend/src/app/user-management/utilties/login-service.ts deleted file mode 100644 index de5680db5..000000000 --- a/dmp-frontend/src/app/user-management/utilties/login-service.ts +++ /dev/null @@ -1,250 +0,0 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable, NgZone, Optional } from '@angular/core'; -import { MatSnackBar } from '@angular/material'; -import { ActivatedRoute, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { takeUntil } from 'rxjs/operators'; -import { environment } from '../../../environments/environment'; -import { BaseService } from '../../core/common/base/base.service'; -import { Credential } from '../../models/login/Credential'; -import { LoginProviders } from '../../models/login/LoginInfo'; -import { AuthService } from '../../services/auth/auth.service'; -import { SnackBarNotificationComponent } from '../../shared/components/notificaiton/snack-bar-notification.component'; -import { CultureService } from '../../utilities/culture/culture-service'; -import { LoginOptions } from './LoginOptions'; -import { LoginProviderConfiguration } from './LoginProviderConfiguration'; -import { LoginServiceConfiguration } from './LoginServiceConfiguration'; - -declare const gapi: any; -declare const FB: any; -declare const IN: any; - -@Injectable() -export class LoginService extends BaseService { - - private providers: LoginOptions[]; - private auth2: any; - constructor( - private router: Router, - public authService: AuthService, - public route: ActivatedRoute, - public snackBar: MatSnackBar, - public language: TranslateService, - private zone: NgZone, - private httpClient: HttpClient, - private cultureService: CultureService, - @Optional() private config: LoginServiceConfiguration - ) { - super(); - if (config) { - this.providers = config.loginProviders; - } else { this.providers = [LoginOptions.nativeLogin]; } - } - - public initProviders() { - if (this.hasProvider(LoginOptions.googleOauth)) { this.initialiseGoogleOauth(); } - if (this.hasProvider(LoginOptions.facebookOauth)) { this.initialiseFacebookOauth(); } - } - - public hasProvider(provider: LoginOptions) { - for (let i = 0; i < this.providers.length; i++) { - if (provider === this.providers[i]) { return this.isProviderProperlyConfigured(provider); } - } - return false; - } - - private isProviderProperlyConfigured(provider: LoginOptions) { - switch (provider) { - case LoginOptions.facebookOauth: return this.hasAllRequiredFieldsConfigured(this.config.facebookConfiguration); - case LoginOptions.googleOauth: return this.hasAllRequiredFieldsConfigured(this.config.googleConfiguration); - case LoginOptions.linkedInOauth: return this.hasAllRequiredFieldsConfigured(this.config.linkedInConfiguration); - case LoginOptions.twitterOauth: return this.hasAllRequiredFieldsConfigured(this.config.twitterConfiguration); - case LoginOptions.b2Access: return this.hasAllRequiredFieldsConfigured(this.config.b2accessConfiguration); - case LoginOptions.nativeLogin: return true; - default: throw new Error('Unsupported Provider Type'); - } - } - - private hasAllRequiredFieldsConfigured(configuration: LoginProviderConfiguration) { - if (configuration != null && configuration.clientId != null) { return true; } - return false; - } - - /* - * GOOGLE SIGN IN - */ - - private initialiseGoogleOauth(): void { - gapi.load('auth2', () => { - this.auth2 = gapi.auth2.init({ - client_id: this.config.googleConfiguration.clientId, - cookiepolicy: 'single_host_origin', - scope: 'profile email' - }); - this.attachGoogleSignin(document.getElementById('googleSignInButton')); - }); - } - - public attachGoogleSignin(element) { - if (!element) { return; } - this.auth2.attachClickHandler(element, {}, - (googleUser) => { - const id_token = googleUser.getAuthResponse().id_token; - if (id_token) { - this.authService.login({ ticket: id_token, provider: LoginProviders.Google }) - .pipe(takeUntil(this._destroyed)) - .subscribe( - res => this.onLogInSuccess(res), - error => this.onLogInError(error) - ); - } - }, (error) => { - }); - } - - - - /* - * FACEBOOK SIGN IN - */ - - - private initialiseFacebookOauth(): void { - FB.init({ - appId: this.config.facebookConfiguration.clientId, - cookie: false, - xfbml: true, - version: 'v2.8' - }); - } - - - - - public facebookLogin() { - FB.login((response: any) => { - if (response.status === 'connected' || 'not_authorized') { - this.authService.login({ ticket: response.authResponse.accessToken, provider: LoginProviders.Facebook }) - .pipe(takeUntil(this._destroyed)) - .subscribe( - res => this.onLogInSuccess(res), - error => this.onLogInError(error) - ); - } - }, { scope: 'user_friends,email' }); - } - - /* - * LINKEDIN SIGN IN - */ - - public linkedinAuthorize() { - window.location.href = this.config.linkedInConfiguration.oauthUrl + '?response_type=code&client_id=' + this.config.linkedInConfiguration.clientId + '&redirect_uri=' + this.config.linkedInConfiguration.redirectUri + '&state=987654321'; - } - - public linkedInInitialiseLogin() { - this.router.navigate(['/login/linkedin']); - } - - public linkedInloginUser(code: string) { - this.authService.login({ ticket: code, provider: LoginProviders.LinkedIn }) - .pipe(takeUntil(this._destroyed)) - .subscribe( - res => this.onLogInSuccess(res), - error => this.onLogInError(error) - ); - } - - /* - * TWITTER SIGN IN - */ - public twitterInitialiseLogin() { - this.router.navigate(['/login/twitter']); - } - - public twitterAuthorize() { - let headers = new HttpHeaders(); - headers = headers.set('Content-Type', 'application/json'); - headers = headers.set('Accept', 'application/json'); - this.httpClient.get(environment.Server + 'auth/twitterRequestToken', { headers: headers }) - .pipe(takeUntil(this._destroyed)) - .subscribe((data: any) => { - window.location.href = this.config.twitterConfiguration.oauthUrl + '?oauth_token=' + data.payload.value; - }); - } - - public twitterLogin(token: string, verifier: string) { - this.authService.login({ ticket: token, provider: LoginProviders.Twitter, data: verifier }) - .pipe(takeUntil(this._destroyed)) - .subscribe( - res => this.onLogInSuccess(res), - error => this.onLogInError(error) - ); - } - - /* - * B2ACCESS LOG IN - */ - - public b2AccessInitialiseLogin() { - this.router.navigate(['/api/oauth/authorized/b2access']); - } - - public b2AccessGetAuthCode() { - window.location.href = this.config.b2accessConfiguration.oauthUrl + '?response_type=code&client_id=' + this.config.b2accessConfiguration.clientId + '&redirect_uri=' + this.config.b2accessConfiguration.redirectUri + '&state=987654321&scope=USER_PROFILE'; - } - - public b2AccessLogin(code: String) { - let headers = new HttpHeaders(); - headers = headers.set('Content-Type', 'application/json'); - headers = headers.set('Accept', 'application/json'); - this.httpClient.post(environment.Server + 'auth/b2AccessRequestToken', { code: code }, { headers: headers }) - .pipe(takeUntil(this._destroyed)) - .subscribe((data: any) => { - this.authService.login({ ticket: data.payload.accessToken, provider: LoginProviders.B2Accesss, data: null }) - .pipe(takeUntil(this._destroyed)) - .subscribe( - res => this.onLogInSuccess(res), - error => this.onLogInError(error) - ); - }); - } - - - /* - * NATIVE LOGIN - */ - - public nativeLogin(credentials: Credential) { - this.authService.nativeLogin(credentials) - .pipe(takeUntil(this._destroyed)) - .subscribe( - res => this.onLogInSuccess(res), - error => this.onLogInError(error) - ); - } - - - /* - * LOGIN HANDLERS - */ - - - public onLogInSuccess(logoutMessage: any) { - this.snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: 'GENERAL.SNACK-BAR.SUCCESSFUL-LOGIN', language: this.language }, - duration: 3000, - }); - if (this.authService.current().culture) { this.cultureService.cultureSelected(this.authService.current().culture); } - const params = this.router['rawUrlTree'].queryParams; - const redirectUrl = params['returnUrl'] ? params['returnUrl'] : '/'; - this.zone.run(() => this.router.navigate([redirectUrl])); - } - - public onLogInError(errorMessage: string) { - this.snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: 'GENERAL.SNACK-BAR.UNSUCCESSFUL-LOGIN', language: this.language }, - duration: 3000, - }); - } -} diff --git a/dmp-frontend/src/app/users/activity/RecentActivityTypes.ts b/dmp-frontend/src/app/users/activity/RecentActivityTypes.ts deleted file mode 100644 index bdf36f506..000000000 --- a/dmp-frontend/src/app/users/activity/RecentActivityTypes.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum RecentActivityTypes { - PROJECT = 0, - DATASET = 1, - DMP = 2 -} diff --git a/dmp-frontend/src/app/users/activity/recent-activity.component.html b/dmp-frontend/src/app/users/activity/recent-activity.component.html deleted file mode 100644 index 9ca9fac9f..000000000 --- a/dmp-frontend/src/app/users/activity/recent-activity.component.html +++ /dev/null @@ -1,67 +0,0 @@ -
-
- - - - {{'RECENT-ACTIVITY.MY-TITLE-DMP' | translate}} - - - - - -

- {{activity.label}} -

-

- {{activity.timestamp | date:'shortDate'}} -

-
-
-
-
-
-
- - - - {{'RECENT-ACTIVITY.MY-TITLE-PROJECT' | translate}} - - - - - -

- {{activity.label}} -

-

- {{activity.timestamp | date:'shortDate'}} -

-
-
-
- -
-
-
- - - - {{'RECENT-ACTIVITY.MY-TITLE-DATASET' | translate}} - - - - - -

- {{activity.label}} -

-

- {{activity.timestamp | date:'shortDate'}} -

-
-
- -
-
-
-
diff --git a/dmp-frontend/src/app/users/activity/recent-activity.component.ts b/dmp-frontend/src/app/users/activity/recent-activity.component.ts deleted file mode 100644 index 405978be2..000000000 --- a/dmp-frontend/src/app/users/activity/recent-activity.component.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { Router } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { UserReferenceService } from '../../services/user-reference/user-reference-data.service'; -import { RecentActivityTypes } from '../../users/activity/RecentActivityTypes'; - -@Component({ - selector: 'app-recent-activity', - templateUrl: './recent-activity.component.html', - styleUrls: ['./recent-activity.component.scss'], - providers: [ - UserReferenceService - ] -}) -export class RecentActivityComponent extends BaseComponent implements OnInit { - - datasetActivities: any[]; - projectActivities: any[]; - dmpActivities: any[]; - public RecentActivityTypes = RecentActivityTypes; - constructor( - private router: Router, - private userReferenceService: UserReferenceService - ) { super(); } - - ngOnInit() { - this.userReferenceService.getRecentActivity() - .pipe(takeUntil(this._destroyed)) - .subscribe(response => { - this.datasetActivities = response['recentDatasetActivities']; - this.dmpActivities = response['recentDmpActivities']; - this.projectActivities = response['recentProjectActivities']; - }); - } - - redirect(id: string, type: RecentActivityTypes) { - switch (type) { - case RecentActivityTypes.PROJECT: { - this.router.navigate(['projects/edit/' + id]); - return; - } - case RecentActivityTypes.DATASET: { - this.router.navigate(['datasets/edit/' + id]); - return; - } - case RecentActivityTypes.DMP: { - this.router.navigate(['dmps/edit/' + id]); - return; - } - default: throw new Error('Unsupported Activity Type '); - } - - } -} diff --git a/dmp-frontend/src/app/users/components/roles/user-role-editor.component.scss b/dmp-frontend/src/app/users/components/roles/user-role-editor.component.scss deleted file mode 100644 index b09cc9d8d..000000000 --- a/dmp-frontend/src/app/users/components/roles/user-role-editor.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.roles-width-80 { - width: 80%; -} diff --git a/dmp-frontend/src/app/users/components/roles/user-role-editor.component.ts b/dmp-frontend/src/app/users/components/roles/user-role-editor.component.ts deleted file mode 100644 index 6114b98ab..000000000 --- a/dmp-frontend/src/app/users/components/roles/user-role-editor.component.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { AbstractControl, FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms'; -import { MatSnackBar } from '@angular/material'; -import { TranslateService } from '@ngx-translate/core'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { Principal } from '../../../models/login/Principal'; -import { UserErrorModel } from '../../../models/users/UserErrorModel'; -import { UserListingModel } from '../../../models/users/UserListingModel'; -import { UserReferenceService } from '../../../services/user-reference/user-reference-data.service'; -import { SnackBarNotificationComponent } from '../../../shared/components/notificaiton/snack-bar-notification.component'; -import { Utilities } from '../../../utilities/utilities'; -import { Validation, ValidationContext } from '../../../utilities/validators/ValidationContext'; - -@Component({ - selector: 'app-user-role-editor-component', - templateUrl: './user-role-editor.component.html', - styleUrls: ['./user-role-editor.component.scss'], - providers: [Utilities] -}) -export class UserRoleEditorComponent extends BaseComponent implements OnInit { - - @Input() public item: UserListingModel; - public formGroup: FormGroup = null; - public nowEditing = false; - public errorModel: UserErrorModel; - constructor( - public language: TranslateService, - public userService: UserReferenceService, - public formBuilder: FormBuilder, - public snackBar: MatSnackBar, - public utilities: Utilities - ) { super(); } - - ngOnInit() { - if (this.errorModel == null) { this.errorModel = new UserErrorModel(); } - if (this.formGroup == null) { this.formGroup = this.buildForm(); } - } - - buildForm(): FormGroup { - const context: ValidationContext = this.createValidationContext(); - - return this.formBuilder.group({ - appRoles: new FormControl({ value: this.item.appRoles, disabled: true }, context.getValidation('appRoles').validators) - }); - } - - createValidationContext(): ValidationContext { - const validationContext: ValidationContext = new ValidationContext(); - const validationArray: Validation[] = new Array(); - - validationArray.push({ key: 'appRoles' }); - - validationContext.validation = validationArray; - return validationContext; - } - - formSubmit(): void { - this.clearErrorModel(); - - const modifiedItem = new UserListingModel().fromJSONObject(this.item); - modifiedItem.appRoles = this.getFormControl('appRoles').value; - - if (!this.isFormValid()) { return; } - this.userService.updateRoles(modifiedItem) - .pipe(takeUntil(this._destroyed)) - .subscribe( - (res) => this.onCallbackSuccess(), - (error) => this.onCallbackError(error) - ); - } - - editItem(): void { - this.formGroup.enable(); - this.nowEditing = true; - } - - isFormValid(): boolean { - this.touchAllFormFields(this.formGroup); - this.validateAllFormFields(this.formGroup); - return this.formGroup.valid; - } - - getFormData(): any { - return this.formGroup.value; - } - - getFormControl(controlName: string): AbstractControl { - return this.formGroup.get(controlName); - } - - validateAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.updateValueAndValidity({ emitEvent: false }); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.validateAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.validateAllFormFields(item); - }); - } - } - - touchAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.markAsTouched(); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.touchAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.touchAllFormFields(item); - }); - } - } - - setErrorModel(errorModel: UserErrorModel) { - Object.keys(errorModel).forEach(item => { - (this.errorModel)[item] = (errorModel)[item]; - }); - } - - clearErrorModel() { - Object.keys(this.errorModel).forEach(item => { - (this.errorModel)[item] = ''; - }); - } - - onCallbackSuccess() { - this.nowEditing = false; - this.formGroup.disable(); - this.snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, - duration: 3000, - }); - } - onCallbackError(error: any) { - this.setErrorModel(error.error); - this.validateAllFormFields(this.formGroup); - this.snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: 'GENERAL.SNACK-BAR.UNSUCCESSFUL-UPDATE', language: this.language }, - duration: 3000, - }); - } - - getPrincipalAppRoleValues(): Number[] { - let keys: string[] = Object.keys(Principal.AppRole); - keys = keys.slice(0, keys.length / 2); - const values: Number[] = keys.map(Number); - return values; - } - - getPrincipalAppRoleWithLanguage(role: Principal.AppRole): string { - let result = ''; - this.language.get(this.utilities.convertFromPrincipalAppRole(role)) - .pipe(takeUntil(this._destroyed)) - .subscribe((value: string) => { - result = value; - }); - return result; - } -} diff --git a/dmp-frontend/src/app/users/components/users.component.html b/dmp-frontend/src/app/users/components/users.component.html deleted file mode 100644 index da5367a74..000000000 --- a/dmp-frontend/src/app/users/components/users.component.html +++ /dev/null @@ -1,41 +0,0 @@ -
-

{{'USERS.LISTING.TITLE' | translate}}

- - - - - - - - - - {{'USERS.LISTING.LABEL' | translate}} - {{row.name}} - - - - {{'USERS.LISTING.EMAIL' | translate}} - {{row.email}} - - - - {{'USERS.LISTING.LAST-LOGGED-IN' | translate}} - {{row.lastloggedin | date:'shortDate'}} - - - - - {{'USERS.LISTING.ROLES' | translate}} - - - - - - - - - - - - -
diff --git a/dmp-frontend/src/app/users/components/users.component.scss b/dmp-frontend/src/app/users/components/users.component.scss deleted file mode 100644 index 347214ffa..000000000 --- a/dmp-frontend/src/app/users/components/users.component.scss +++ /dev/null @@ -1,12 +0,0 @@ -.mat-card { - overflow: auto; - padding: 0px; - - mat-table { - margin: 24px; - } - - mat-progress-bar { - position: absolute; - } -} diff --git a/dmp-frontend/src/app/users/components/users.component.ts b/dmp-frontend/src/app/users/components/users.component.ts deleted file mode 100644 index 90518c524..000000000 --- a/dmp-frontend/src/app/users/components/users.component.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { DataSource } from '@angular/cdk/table'; -import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core'; -import { MatPaginator, MatSnackBar, MatSort } from '@angular/material'; -import { Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { Observable } from 'rxjs/Rx'; -import { UserCriteria } from '../../models/criteria/users/UserCriteria'; -import { DataTableRequest } from '../../models/data-table/DataTableRequest'; -import { UserListingModel } from '../../models/users/UserListingModel'; -import { UserReferenceService } from '../../services/user-reference/user-reference-data.service'; -import { UsersCriteriaComponent } from '../../shared/components/criteria/users/users-criteria.component'; -import { SnackBarNotificationComponent } from '../../shared/components/notificaiton/snack-bar-notification.component'; - - -export class UsersDataSource extends DataSource { - - totalCount = 0; - isLoadingResults = false; - - constructor( - private _service: UserReferenceService, - private _paginator: MatPaginator, - private _sort: MatSort, - private _languageService: TranslateService, - private _snackBar: MatSnackBar, - private _criteria: UsersCriteriaComponent - ) { - super(); - - //this._paginator.page.pipe(takeUntil(this._destroyed)).subscribe((pageEvent: PageEvent) => { - // this.store.dispatch(new LoadPhotosRequestAction(pageEvent.pageIndex, pageEvent.pageSize)) - //}) - } - - connect(): Observable { - const displayDataChanges = [ - this._paginator.page - //this._sort.matSortChange - ]; - - // If the user changes the sort order, reset back to the first page. - //this._sort.matSortChange.pipe(takeUntil(this._destroyed)).subscribe(() => { - // this._paginator.pageIndex = 0; - //}) - - return Observable.merge(...displayDataChanges) - .startWith(null) - .switchMap(() => { - setTimeout(() => { - this.isLoadingResults = true; - }); - const startIndex = this._paginator.pageIndex * this._paginator.pageSize; - let fields: Array = new Array(); - if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; } - const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); - request.criteria = this._criteria.getFormData(); - return this._service.getPaged(request); - }) - .catch((error: any) => { - this._snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService }, - duration: 3000, - }); - this._criteria.onCallbackError(error); - return Observable.of(null); - }) - .map(result => { - setTimeout(() => { - this.isLoadingResults = false; - }); - return result; - }) - .map(result => { - if (!result) { return []; } - if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; } - //result.data.forEach((element: any) => { - // const roles: String[] = []; - // element.roles.forEach((role: any) => { - // this._languageService.get(this._utilities.convertFromPrincipalAppRole(role)).pipe(takeUntil(this._destroyed)).subscribe( - // value => roles.push(value) - // ); - // }); - // element.roles = roles; - //}); - return result.data; - }); - } - - disconnect() { - // No-op - } -} - -@Component({ - selector: 'app-users-component', - templateUrl: './users.component.html', - styleUrls: ['./users.component.scss'] -}) -export class UsersComponent implements OnInit, AfterViewInit { - - @ViewChild(MatPaginator) _paginator: MatPaginator; - @ViewChild(MatSort) sort: MatSort; - @ViewChild(UsersCriteriaComponent) criteria: UsersCriteriaComponent; - - dataSource: UsersDataSource | null; - displayedColumns: String[] = ['name', 'email', 'lastloggedin', 'roles']; - - constructor(private userService: UserReferenceService, private router: Router, private languageService: TranslateService, public snackBar: MatSnackBar) { - - } - - ngOnInit() { - //this.refresh(); //called on ngAfterViewInit with default criteria - } - - ngAfterViewInit() { - setTimeout(() => { - this.criteria.setRefreshCallback(() => this.refresh()); - this.criteria.setCriteria(this.getDefaultCriteria()); - this.criteria.controlModified(); - }); - } - - refresh() { - this.dataSource = new UsersDataSource(this.userService, this._paginator, this.sort, this.languageService, this.snackBar, this.criteria); - } - - getDefaultCriteria(): UserCriteria { - const defaultCriteria = new UserCriteria(); - return defaultCriteria; - } -} diff --git a/dmp-frontend/src/app/users/profile/user-profile.component.html b/dmp-frontend/src/app/users/profile/user-profile.component.html deleted file mode 100644 index 3c80a4002..000000000 --- a/dmp-frontend/src/app/users/profile/user-profile.component.html +++ /dev/null @@ -1,90 +0,0 @@ -
- - -
-
- -
- {{userProfile.name}} - {{userProfile.email}} -
-
-
- - -
-
-

{{ 'USER-PROFILE.ASSOCIATED-DMPS' | translate}}

-
-
- - -
- {{ dmp.label }} -
-
- - {{ getUserRole(dmp) }} - -
-
-
- -
-
-
-
- - - -

{{ 'USER-PROFILE.SETTINGS.TITLE' | translate}}

- - -
-
- -
-
-
- - - - - {{ timezone | timezoneInfoDisplay }} - - - -
-
- - - - - {{ culture.displayName }} - {{ culture.nativeName }} - - - -
-
- - - - {{ language.label }} - - - -
-
-
-
-
-
- - diff --git a/dmp-frontend/src/app/users/profile/user-profile.component.ts b/dmp-frontend/src/app/users/profile/user-profile.component.ts deleted file mode 100644 index 107a898af..000000000 --- a/dmp-frontend/src/app/users/profile/user-profile.component.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; -import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; -import { ActivatedRoute, Params, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import * as moment from 'moment-timezone'; -import { takeUntil } from 'rxjs/operators'; -import { Observable } from 'rxjs/Rx'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { DataManagementPlanModel } from '../../models/data-managemnt-plans/DataManagementPlanModel'; -import { UserListingModel } from '../../models/users/UserListingModel'; -import { AuthService } from '../../services/auth/auth.service'; -import { UserReferenceService } from '../../services/user-reference/user-reference-data.service'; -import { CultureService } from '../../utilities/culture/culture-service'; -import { CultureInfo } from '../../utilities/culture/models/culture-info'; - -const availableLanguages: any[] = require('../../../assets/resources/language.json'); - -@Component({ - selector: 'app-user-profile', - templateUrl: './user-profile.component.html', - styleUrls: ['./user-profile.component.scss'], - providers: [ - UserReferenceService, - CultureService - ] -}) -export class UserProfileComponent extends BaseComponent implements OnInit, OnDestroy { - - user: Observable; - currentUserId: string; - cultures: Observable; - timezones: Observable; - editMode = false; - languages = availableLanguages; - - formGroup: FormGroup; - constructor( - private userReferenceService: UserReferenceService, - private route: ActivatedRoute, - private router: Router, - private authService: AuthService, - private language: TranslateService, - private cultureService: CultureService, - private translate: TranslateService, - ) { super(); } - - ngOnInit() { - this.route.params - .pipe(takeUntil(this._destroyed)) - .subscribe((params: Params) => { - this.currentUserId = params['id']; - const userId = params['id'] === this.authService.current().id ? 'me' : params['id']; - this.user = this.userReferenceService.getUser(userId).map(result => { - result['additionalinfo'] = JSON.parse(result['additionalinfo']); - this.formGroup = new FormBuilder().group({ - language: new FormControl(result['additionalinfo']['language'] ? availableLanguages.filter(x => x.value === result['additionalinfo']['language']['value']).pop() : ''), - timezone: new FormControl(result['additionalinfo']['timezone']), - culture: new FormControl(result['additionalinfo']['culture']) - }); - //this.formGroup.get('language').valueChanges.pipe(takeUntil(this._destroyed)).subscribe(x => { if (x) this.translate.use(x.value) }) - this.formGroup.get('timezone').valueChanges - .pipe(takeUntil(this._destroyed)) - .subscribe(x => { if (x) { this.timezones = this._filterTimezone(x); } }); - this.formGroup.get('culture').valueChanges - .pipe(takeUntil(this._destroyed)) - .subscribe(x => { if (x) { this.cultures = this._filterCulture(x); } }); - this.formGroup.disable(); - return result; - }); - }); - - } - - ngOnDestroy(): void { - } - - getUserRole(dmp: DataManagementPlanModel) { - if (dmp.creator.id === this.currentUserId) { return this.language.instant('USER-PROFILE.DMPS.CREATOR'); } else if (dmp.associatedUsers.map(x => x.id).indexOf(this.currentUserId) !== -1) { return this.language.instant('USER-PROFILE.DMPS.MEMBER'); } - return ''; - } - - showAllDmps() { - this.router.navigate(['/dmps']); - } - - navigateToDmp(dmp: DataManagementPlanModel) { - this.router.navigate(['/dmps/edit/' + dmp.id]); - } - - private _filterTimezone(value: string): Observable { - if (value && typeof value === 'string') { - const filterValue = value.toLowerCase(); - return Observable.of(moment.tz.names().filter(option => option.toLowerCase().includes(filterValue))); - } else { - return Observable.of(moment.tz.names()); - } - } - - private _filterCulture(value: string): Observable { - if (value && typeof value === 'string') { - const filterValue = value.toLowerCase(); - return Observable.of(this.cultureService.getCultureValues().filter(option => option.displayName.toLowerCase().includes(filterValue))); - } else { - return Observable.of(this.cultureService.getCultureValues()); - } - } - - displayFn(culture?: CultureInfo): string | undefined { - return culture ? culture.displayName + '-' + culture.nativeName : undefined; - } - - save() { - - } - - public unlock() { - this.editMode = true; - this.formGroup.enable(); - } - - public lock() { - this.userReferenceService.updateUserSettings(this.formGroup.value) - .pipe(takeUntil(this._destroyed)) - .subscribe( - x => { - this.editMode = false; - this.translate.use(this.formGroup.value.language); - this.authService.current().culture = this.formGroup.value.culture.name; - this.formGroup.disable(); - this.authService.me() - .pipe(takeUntil(this._destroyed)) - .subscribe(result => window.location.reload()); - }, - error => { - console.log(error); - }); - } - -} diff --git a/dmp-frontend/src/app/users/users.module.ts b/dmp-frontend/src/app/users/users.module.ts deleted file mode 100644 index e7a8e3f6f..000000000 --- a/dmp-frontend/src/app/users/users.module.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { TranslateHttpLoader } from '@ngx-translate/http-loader'; -import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; -import { UsersCriteriaComponent } from '../shared/components/criteria/users/users-criteria.component'; -import { MaterialModule } from '../shared/material/material.module'; -import { SharedModule } from '../shared/shared.module'; -import { CommonModule } from '@angular/common'; -import { HttpClient, HttpClientModule } from '@angular/common/http'; -import { NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; - -import { UsersComponent } from './components/users.component'; -import { UserRoleEditorComponent } from './components/roles/user-role-editor.component'; -import { RecentActivityComponent } from '../users/activity/recent-activity.component'; -import { UserReferenceService } from '../services/user-reference/user-reference-data.service'; -import { RouterModule } from '@angular/router'; -import { UsersRoutes } from './users.routes'; -import { BaseHttpModule } from '../utilities/cite-http-service-module/cite-http.module'; -import { BaseHttpService } from '../utilities/cite-http-service-module/base-http.service'; -import { UserProfileComponent } from './profile/user-profile.component'; -import { TimezoneInfoDisplayPipe } from '../utilities/culture/pipes/TimezoneInfoDisplayPipe'; - -@NgModule({ - imports: [ - CommonModule, - SharedModule, - BaseHttpModule.forRoot(), - - RouterModule.forChild(UsersRoutes), - TranslateModule.forRoot({ - loader: { - provide: TranslateLoader, - useFactory: HttpLoaderFactory, - deps: [HttpClient] - } - }), - ReactiveFormsModule, - MaterialModule - ], - - declarations: [ - UsersComponent, - UsersCriteriaComponent, - UserRoleEditorComponent, - UserProfileComponent, - TimezoneInfoDisplayPipe - ], - providers: [ - BaseHttpService, - UserReferenceService - ], - exports: [ - UsersComponent - - ] -}) - -export class UsersModule { - constructor(private translate: TranslateService) { - translate.setDefaultLang('en'); - translate.use('en'); - } -} - -export function HttpLoaderFactory(httpClient: HttpClient) { - return new TranslateHttpLoader(httpClient, 'assets/lang/', '.json'); -} diff --git a/dmp-frontend/src/app/users/users.routes.ts b/dmp-frontend/src/app/users/users.routes.ts deleted file mode 100644 index 8cbaae4f3..000000000 --- a/dmp-frontend/src/app/users/users.routes.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { RouterModule, Routes } from '@angular/router'; -import { UsersComponent } from './components/users.component'; -import { UserProfileComponent } from './profile/user-profile.component'; - -export const UsersRoutes: Routes = [ - { path: '', component: UsersComponent }, - { path: ':id', component: UserProfileComponent } -]; diff --git a/dmp-frontend/src/app/utilities/JsonSerializer.ts b/dmp-frontend/src/app/utilities/JsonSerializer.ts deleted file mode 100644 index b7c502484..000000000 --- a/dmp-frontend/src/app/utilities/JsonSerializer.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Serializable } from '../models/interfaces/Serializable'; -export class JsonSerializer { - - public static fromJSONArray>(items: any[], type: { new(): T; }): T[] { - if (!items) { return new Array(); } - const objectList: T[] = new Array(); - for (let i = 0; i < items.length; i++) { - objectList.push(new type().fromJSONObject(items[i])); - } - return objectList; - } - - public static fromJSONObject>(item: any, type: { new(): T; }): T { - if (!item) { return null; } - return new type().fromJSONObject(item); - } - - public static copy>(item: any, itemToCopy: any): T { - if (!item) { return null; } - return item.fromJSONObject(itemToCopy); - } -} diff --git a/dmp-frontend/src/app/utilities/UrlUtilities.ts b/dmp-frontend/src/app/utilities/UrlUtilities.ts deleted file mode 100644 index 91ec68a07..000000000 --- a/dmp-frontend/src/app/utilities/UrlUtilities.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Injectable } from '@angular/core'; - -@Injectable() -export class UrlUtilities { - - public applyUrlTemplate(url: string, params: any): string { - let paramsToString = ''; - if (params) { paramsToString = '?'; } - const keys = Object.keys(params); - keys.forEach(x => { - if (keys.indexOf(x) > 0) { paramsToString += '&'; } - paramsToString += x + '=' + params[x]; - }); - return url + paramsToString; - } - -} diff --git a/dmp-frontend/src/app/utilities/cite-http-service-module/base-http.service.ts b/dmp-frontend/src/app/utilities/cite-http-service-module/base-http.service.ts deleted file mode 100644 index 60bf3bde0..000000000 --- a/dmp-frontend/src/app/utilities/cite-http-service-module/base-http.service.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { Message } from '@angular/compiler/src/i18n/i18n_ast'; -import { ApiMessageCode } from '../types/ApiMessageCode'; -import { Injectable } from '@angular/core'; -import { Http, RequestOptions, Response, Headers } from '@angular/http'; -import { Observable } from 'rxjs'; -import { Router, ActivatedRoute, RouterStateSnapshot } from '@angular/router'; -import { MatSnackBar } from '@angular/material'; -import { TranslateService } from '@ngx-translate/core'; -import { HttpClient } from '@angular/common/http'; -import { AuthService } from '../../services/auth/auth.service'; -import { SnackBarNotificationComponent } from '../../shared/components/notificaiton/snack-bar-notification.component'; -import { BaseHttpResponseModel } from '../../models/http/BaseHttpResponseModel'; -import { ApiResponseCode } from '../../utilities/types/ApiResponseCode'; - -@Injectable() -export class BaseHttpService { - constructor( - protected http: HttpClient, - private router: Router, - private authService: AuthService, - public language: TranslateService, - public snackBar: MatSnackBar, - public route: ActivatedRoute - ) { - } - get(url: string, options?: any, appendOptions: boolean = true): Observable { - return this.interceptRepsonse(this.http.get(url, this.buildRequestOptions(appendOptions, options))); - } - post(url: string, body: any, options?: any, appendOptions: boolean = true): Observable { - return this.interceptRepsonse(this.http.post(url, body, this.buildRequestOptions(appendOptions, options))); - } - put(url: string, body: any, options?: any, appendOptions: boolean = true): Observable { - return this.interceptRepsonse(this.http.put(url, body, this.buildRequestOptions(appendOptions, options))); - } - delete(url: string, options?: any, appendOptions: boolean = true): Observable { - return this.interceptRepsonse(this.http.delete(url, this.buildRequestOptions(appendOptions, options))); - } - patch(url: string, body: any, options?: any, appendOptions: boolean = true): Observable { - return this.interceptRepsonse(this.http.patch(url, body, this.buildRequestOptions(appendOptions, options))); - } - head(url: string, options?: any, appendOptions: boolean = true): Observable { - return this.interceptRepsonse(this.http.head(url, this.buildRequestOptions(appendOptions, options))); - } - options(url: string, options?: any, appendOptions: boolean = true): Observable { - return this.interceptRepsonse(this.http.options(url, this.buildRequestOptions(appendOptions, options))); - } - - protected buildRequestOptions(appendOptions: boolean, options?: any): Object { - if (options == null) { - options = new RequestOptions(); - } - if (options.headers == null) { - options.headers = new Headers(); - } - if (!options.headers.has('Content-Type') && appendOptions) { - options.headers = options.headers.set('Content-Type', 'application/json'); - } - if (!options.headers.has('Content-Type') && appendOptions) { - options.headers = options.headers.set('Content-Type', 'application/json'); - } - if (!options.headers.has('AuthToken')) { - const principal = this.authService.current(); - if (principal) { - options.headers = options.headers.set('AuthToken', principal.token); - } - } - - return options; - } - - private interceptRepsonse(observable: Observable): Observable { - return observable - .catch((errorResponse) => { - if (errorResponse.status === 401) { - this.snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: 'GENERAL.SNACK-BAR.SUCCESSFUL-LOGOUT', language: this.language }, - duration: 3000, - }); - const currentPage = this.router.url; - this.router.navigate(['/unauthorized'], { queryParams: { returnUrl: currentPage } }); - //this.notification.httpError(error); - return Observable.of(); - } else { - const error: any = errorResponse.error; - if (error.statusCode === ApiMessageCode.ERROR_MESSAGE) { - this.snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: error.message, language: null }, - duration: 3000, - }); - return Observable.throw(errorResponse); - } else if (error.statusCode === ApiMessageCode.VALIDATION_MESSAGE) { - return Observable.throw(errorResponse); - } else { - this.snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: 'GENERAL.ERRORS.HTTP-REQUEST-ERROR', language: this.language }, - duration: 3000, - }); - return Observable.throw(errorResponse); - } - } - }) - .map(response => { - if (response instanceof Blob) { return response; } - if (response['statusCode'] === ApiMessageCode.SUCCESS_MESSAGE) { - //throw new Error('Request failed'); - this.snackBar.openFromComponent(SnackBarNotificationComponent, { - data: { message: response['message'], language: null }, - duration: 3000, - }); - return response['payload']; - - } else if (response['statusCode'] === ApiMessageCode.NO_MESSAGE) { - return response['payload']; - } else { - return response['payload']; - } - }); - } - - // public handleResponse(response: BaseHttpResponseModel) { - // if (response.statusCode < 200 || response.statusCode >= 300) { - // //throw new Error('Request failed'); - // this.snackBar.openFromComponent(SnackBarNotificationComponent, { - // data: { message: 'GENERAL.ERRORS.HTTP-REQUEST-ERROR', language: this.language }, - // duration: 3000, - // extraClasses: ['snackbar-warning'] - // }) - // } - // else { - // return response.payload; - // } - // } -} diff --git a/dmp-frontend/src/app/utilities/cite-http-service-module/cite-http.module.ts b/dmp-frontend/src/app/utilities/cite-http-service-module/cite-http.module.ts deleted file mode 100644 index d4e9c4a92..000000000 --- a/dmp-frontend/src/app/utilities/cite-http-service-module/cite-http.module.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule, ModuleWithProviders } from '@angular/core'; -import { AuthService } from '../../services/auth/auth.service'; -import { BaseHttpService } from './base-http.service'; -import { TranslateService, TranslateModule, TranslateLoader } from '@ngx-translate/core'; -import { HttpLoaderFactory } from '../../projects/projects.module'; -import { HttpClient, HttpClientModule } from '@angular/common/http'; - -@NgModule({ - imports: [ - CommonModule, - HttpClientModule - ] -}) -export class BaseHttpModule { - static forRoot(): ModuleWithProviders { - return { - ngModule: BaseHttpModule, - providers: [ - AuthService, - BaseHttpService - ] - }; - } -} diff --git a/dmp-frontend/src/app/utilities/culture/culture-service.ts b/dmp-frontend/src/app/utilities/culture/culture-service.ts deleted file mode 100644 index 72267fcf6..000000000 --- a/dmp-frontend/src/app/utilities/culture/culture-service.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Observable, Subject } from 'rxjs'; -import { CultureInfo } from './models/culture-info'; -import { registerLocaleData } from '@angular/common'; -import { AuthService } from '../../services/auth/auth.service'; - -const availableCultures: CultureInfo[] = require('../../../assets/resources/available-cultures.json'); - -@Injectable() -export class CultureService { - - private cultureValues = new Map(); // cultures by name - private cultureChangeSubject = new Subject(); - private currentCulture: CultureInfo; - - constructor( - private authService: AuthService - ) { - if (availableCultures) { - this.cultureValues = new Map(); - availableCultures.forEach(culture => { - this.cultureValues.set(culture.name, culture); - }); - } - } - - getCultureValues(): CultureInfo[] { - const values: CultureInfo[] = []; - this.cultureValues.forEach((value) => values.push(value)); - return values; - } - - getCultureValue(culture: string): CultureInfo | undefined { - return this.cultureValues.get(culture); - } - - cultureSelected(culture: string | CultureInfo) { - let newCultureName: string; - if (typeof culture === 'string') { - if (this.currentCulture && this.currentCulture.name === culture) { return; } - newCultureName = culture; - } else { - if (this.currentCulture && this.currentCulture.name === culture.name) { return; } - newCultureName = culture.name; - } - - const newCulture = this.cultureValues.get(newCultureName); - if (!newCulture) { - //console.error(`unsupported culture given: ${newCultureName}`); //TODO: throw error? - return; - } - this.currentCulture = newCulture; - this.cultureChangeSubject.next(newCulture); - - // Set angular locale based on user selection. - let locale = newCulture.name; - import(`@angular/common/locales/${locale}.js`).catch(reason => { - //console.warn('Could not load locale: ' + locale); - locale = newCulture.name.split('-')[0]; - //console.warn('Will try ' + locale); - return import(`@angular/common/locales/${locale}.js`).catch(resutl => { - //console.error('Could not load locale: ' + locale); - }); - }).then(selectedLocale => { - registerLocaleData(selectedLocale.default); - }); - } - - getCultureChangeObservable(): Observable { - return this.cultureChangeSubject.asObservable(); - } - - getCurrentCulture(): String { - return this.authService.current() && this.authService.current().culture ? this.authService.current().culture : this.currentCulture.name; - } -} diff --git a/dmp-frontend/src/app/utilities/culture/models/culture-info.ts b/dmp-frontend/src/app/utilities/culture/models/culture-info.ts deleted file mode 100644 index d365c5974..000000000 --- a/dmp-frontend/src/app/utilities/culture/models/culture-info.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class CultureInfo { - public name: string; - public displayName: string; - public nativeName: string; -} diff --git a/dmp-frontend/src/app/utilities/culture/pipes/TimezoneInfoDisplayPipe.ts b/dmp-frontend/src/app/utilities/culture/pipes/TimezoneInfoDisplayPipe.ts deleted file mode 100644 index 70eb69143..000000000 --- a/dmp-frontend/src/app/utilities/culture/pipes/TimezoneInfoDisplayPipe.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import * as moment from 'moment'; -import 'moment-timezone'; - -@Pipe({ name: 'timezoneInfoDisplay' }) -export class TimezoneInfoDisplayPipe implements PipeTransform { - constructor() { } - - public transform(value): any { - return value + ' (GMT' + moment['tz'](value).format('Z') + ')'; - } -} diff --git a/dmp-frontend/src/app/utilities/form-focus-service/form-focus.service.ts b/dmp-frontend/src/app/utilities/form-focus-service/form-focus.service.ts deleted file mode 100644 index 76c4f7ff4..000000000 --- a/dmp-frontend/src/app/utilities/form-focus-service/form-focus.service.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Injectable } from '@angular/core'; -import { CompositeField } from '../../models/CompositeField'; -import { Router, ActivatedRoute } from '@angular/router'; -import { Pair } from '../../models/helpers/Pair'; -import '../../utilities/enhancers/groupBy'; -import { VisibilityRulesService } from '../visibility-rules/visibility-rules.service'; - -@Injectable() -export class FormFocusService { - - private compositeFields: Pair[] = []; - - constructor( - public router: Router, - public route: ActivatedRoute, - public visibilityService: VisibilityRulesService - ) { - - } - - setFields(compositeFields: Pair[]) { - this.compositeFields = compositeFields; - } - - focusNext(field: CompositeField) { - const flattenedCompositeFields = this.compositeFields.groupBy(x => x.right) - .map(x => x.reduce((first: Pair, second: Pair) => - (new Pair(first.left.concat(second.left), first.right)))); - const page = flattenedCompositeFields.filter(x => x['left'].map(y => y.id).indexOf(field.id) !== -1)[0]; - let pageIndex = page['right']; - const currentFields = page['left'].filter(x => this.visibilityService.checkElementVisibility(x.id)).map(x => x.id); - const fieldIndex = currentFields.indexOf(field.id); - if (fieldIndex === currentFields.length - 1) { pageIndex = pageIndex + 1; } - this.router.navigate(['datasets/' + this.route.snapshot.url[0] + '/' + this.route.snapshot.url[1]], { fragment: page['left'].filter(x => this.visibilityService.checkElementVisibility(x.id))[fieldIndex].id, queryParams: { page: pageIndex } }); - } -} diff --git a/dmp-frontend/src/app/utilities/forms/FormGenerator.ts b/dmp-frontend/src/app/utilities/forms/FormGenerator.ts deleted file mode 100644 index c253af2e6..000000000 --- a/dmp-frontend/src/app/utilities/forms/FormGenerator.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ValidationContext } from '../validators/ValidationContext'; -import { FormGroup } from '@angular/forms'; - -export interface FormGenerator { - buildForm(validation: ValidationContext, disabled?: boolean): FormGroup; -} diff --git a/dmp-frontend/src/app/utilities/mark-for-considerations/mark-for-consideration.service.ts b/dmp-frontend/src/app/utilities/mark-for-considerations/mark-for-consideration.service.ts deleted file mode 100644 index 948ec952f..000000000 --- a/dmp-frontend/src/app/utilities/mark-for-considerations/mark-for-consideration.service.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Injectable } from '@angular/core'; -import { CompositeField } from '../../models/CompositeField'; - -@Injectable() -export class MarkForConsiderationService { - - private compositeFields: CompositeField[] = []; - - markForConsideration(field: CompositeField) { - if (this.exists(field)) { - this.compositeFields.push(field); - } - } - - getFields() { - return this.compositeFields; - } - - exists(field: CompositeField) { - return this.compositeFields.map(x => x.id).indexOf(field.id) === -1; - } -} diff --git a/dmp-frontend/src/app/utilities/types/ApiResponseCode.ts b/dmp-frontend/src/app/utilities/types/ApiResponseCode.ts deleted file mode 100644 index bb64a7ef5..000000000 --- a/dmp-frontend/src/app/utilities/types/ApiResponseCode.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum ApiResponseCode { - JSON_RESPONSE = 0, - FILE_RESPONSE = 1, -} diff --git a/dmp-frontend/src/app/utilities/utilities.ts b/dmp-frontend/src/app/utilities/utilities.ts deleted file mode 100644 index 393e4d9f3..000000000 --- a/dmp-frontend/src/app/utilities/utilities.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Injectable } from '@angular/core'; -import { FormBuilder, FormArray, FormGroup } from '@angular/forms'; -import { Principal } from '../models/login/Principal'; -import { DMPProfileFieldDataType, DMPProfileType } from '../models/data-management-plan-profile/DataManagementProfileField'; -import { DatasetStatus } from '../models/datasets/DatasetWizardModel'; -import { TranslateService } from '@ngx-translate/core'; -import { DataManagementPlanStatus } from '../models/data-managemnt-plans/DataManagementPlanModel'; - -@Injectable() -export class Utilities { - - constructor(private language: TranslateService) { - - } - - convertFromPrincipalAppRole(status: Principal.AppRole): string { - switch (status) { - case Principal.AppRole.Admin: return 'TYPES.APP-ROLE.ADMIN'; - case Principal.AppRole.User: return 'TYPES.APP-ROLE.USER'; - case Principal.AppRole.Manager: return 'TYPES.APP-ROLE.MANAGER'; - } - } - - convertFromDMPProfileDataType(type: DMPProfileFieldDataType): string { - switch (type) { - case DMPProfileFieldDataType.DATE: return 'TYPES.DMP-PROFILE-FIELD.DATA-TYPE.DATE'; - case DMPProfileFieldDataType.NUMBER: return 'TYPES.DMP-PROFILE-FIELD.DATA-TYPE.NUMBER'; - case DMPProfileFieldDataType.TEXT: return 'TYPES.DMP-PROFILE-FIELD.DATA-TYPE.TEXT'; - } - } - - convertFromDMPProfileType(type: DMPProfileType): string { - switch (type) { - case DMPProfileType.INPUT: return 'TYPES.DMP-PROFILE-FIELD.TYPE.INPUT'; - } - } - - convertFromDatasetStatus(status: DatasetStatus): string { - switch (status) { - case DatasetStatus.Draft: return this.language.instant('TYPES.DATASET-STATUS.DRAFT'); - case DatasetStatus.Finalised: return this.language.instant('TYPES.DATASET-STATUS.FINALISED'); - } - } - - convertFromDMPStatus(status: DataManagementPlanStatus): string { - switch (status) { - case DataManagementPlanStatus.Draft: return this.language.instant('TYPES.DMP.DRAFT'); - case DataManagementPlanStatus.Finalised: return this.language.instant('TYPES.DMP.FINALISED'); - } - } -} diff --git a/dmp-frontend/src/app/utilities/validators/BackendErrorValidator.ts b/dmp-frontend/src/app/utilities/validators/BackendErrorValidator.ts deleted file mode 100644 index 14adbee9a..000000000 --- a/dmp-frontend/src/app/utilities/validators/BackendErrorValidator.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ValidatorFn, AbstractControl } from '@angular/forms'; -import { BaseErrorModel } from '../../models/error/BaseErrorModel'; - -export function BackendErrorValidator(errorModel: BaseErrorModel, propertyName: string): ValidatorFn { - return (control: AbstractControl): { [key: string]: any } => { - const error: string = (errorModel)[propertyName]; - return error ? { 'backendError': { value: error } } : null; - }; -} diff --git a/dmp-frontend/src/app/utilities/validators/ValidationContext.ts b/dmp-frontend/src/app/utilities/validators/ValidationContext.ts deleted file mode 100644 index 37b831bb5..000000000 --- a/dmp-frontend/src/app/utilities/validators/ValidationContext.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ValidatorFn } from '@angular/forms'; - -export class ValidationContext { - validation: Validation[] = []; - - getValidation(key: string): Validation { - for (let i = 0; i < this.validation.length; i++) { - if (this.validation[i].key === key) { - return this.validation[i]; - } - } - throw new Error('Key Was Not Found In The Validation Context'); - } -} - -export class Validation { - key: string; - validators?: ValidatorFn[] = new Array(); - descendantValidations?: ValidationContext; -} diff --git a/dmp-frontend/src/app/utilities/visibility-rules/models/VisibilityRule.ts b/dmp-frontend/src/app/utilities/visibility-rules/models/VisibilityRule.ts deleted file mode 100644 index 0a1958e25..000000000 --- a/dmp-frontend/src/app/utilities/visibility-rules/models/VisibilityRule.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { VisibilityRuleSource } from './VisibilityRuleSource'; -export class VisibilityRule { - public targetControlId: string; - public sourceVisibilityRules: Array; -} diff --git a/dmp-frontend/src/app/utilities/visibility-rules/models/VisibilityRulesContext.ts b/dmp-frontend/src/app/utilities/visibility-rules/models/VisibilityRulesContext.ts deleted file mode 100644 index 22d5f3f75..000000000 --- a/dmp-frontend/src/app/utilities/visibility-rules/models/VisibilityRulesContext.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { VisibilityRuleSource } from './VisibilityRuleSource'; -import { VisibilityRule } from './VisibilityRule'; -import { Rule } from '../../../models/Rule'; -export class VisibilityRulesContext { - public rules: Array = new Array(); - - public getRulesFromKey(id: string): VisibilityRule { - - for (let i = 0; i < this.rules.length; i++) { - if (id === this.rules[i].targetControlId) { return this.rules[i]; } - } - return null; - } - - public buildVisibilityRuleContext(items: Array) { - items.forEach(item => { - this.addToVisibilityRulesContext(item); - }); - } - - private addToVisibilityRulesContext(item: Rule): void { - for (let i = 0; i < this.rules.length; i++) { - if (this.rules[i].targetControlId === item.targetField) { - this.rules[i].sourceVisibilityRules.push({ sourceControlId: item.sourceField, sourceControlValue: item.requiredValue }); - return; - } - } - const newVisibilityRuleArray = [({ sourceControlId: item.sourceField, sourceControlValue: item.requiredValue })]; - this.rules.push({ targetControlId: item.targetField, sourceVisibilityRules: newVisibilityRuleArray }); - return; - } -} diff --git a/dmp-frontend/src/app/utilities/visibility-rules/visibility-rules.service.ts b/dmp-frontend/src/app/utilities/visibility-rules/visibility-rules.service.ts deleted file mode 100644 index 8f51cbe1c..000000000 --- a/dmp-frontend/src/app/utilities/visibility-rules/visibility-rules.service.ts +++ /dev/null @@ -1,148 +0,0 @@ -import { VisibilityRule } from './models/VisibilityRule'; -import { VisibilityRulesContext } from './models/VisibilityRulesContext'; -import { FormGroup } from '@angular/forms'; -import { Injectable, ApplicationRef, NgZone } from '@angular/core'; -import { Rule } from '../../models/Rule'; -import { DatasetProfileDefinitionModel } from '../../models/DatasetProfileDefinitionModel'; -import { JsonSerializer } from '../JsonSerializer'; -@Injectable() -export class VisibilityRulesService { - - public formGroup: FormGroup; - public visibilityRuleContext: VisibilityRulesContext; - public fieldsPathMemory: any = {}; - private elementVisibilityMap = new Map(); - private initialModel: DatasetProfileDefinitionModel; - private currentModel: DatasetProfileDefinitionModel; - - constructor(public applicationReference: ApplicationRef, public ngZone: NgZone) { - - } - - public setModel(model: DatasetProfileDefinitionModel) { - this.initialModel = JsonSerializer.fromJSONObject(model, DatasetProfileDefinitionModel); - this.currentModel = model; - //this.visibilityRuleContext.rules.forEach(item => this.evaluateVisibility(item)) - } - - public triggerVisibilityEvaluation() { - this.visibilityRuleContext.rules.forEach(item => this.evaluateVisibility(item)); - } - - public getFormGroup(id: string): FormGroup { - const pathKeyArray = this.search('pages', this.initialModel.pages, id).split('.'); - - pathKeyArray.pop(); - const pathKey = pathKeyArray.join('.'); - if (!this.fieldsPathMemory[id] && pathKey) { this.fieldsPathMemory[id] = pathKey; } - return (this.formGroup.get(pathKey)); - } - - public checkElementVisibility(id: string): boolean { - return !this.elementVisibilityMap.has(id) || this.elementVisibilityMap.get(id); - } - - public buildVisibilityRules(item: Array) { - this.visibilityRuleContext = new VisibilityRulesContext(); - this.visibilityRuleContext.buildVisibilityRuleContext(item); - } - - public updateValueAndVisibility(id: string) { - const visibilityRules = this.visibilityRuleContext.rules.filter(item => item.sourceVisibilityRules.filter(source => source.sourceControlId === id).length > 0); - visibilityRules.forEach(item => this.evaluateVisibility(item)); - } - - private evaluateVisibility(visibilityRule: VisibilityRule) { - for (let i = 0; i < visibilityRule.sourceVisibilityRules.length; i++) { - const pathKey = this.fieldsPathMemory[visibilityRule.sourceVisibilityRules[i].sourceControlId]; - if (this.formGroup.get(pathKey + '.value') && (this.parseValue(this.formGroup.get(pathKey + '.value').value) !== this.parseValue(visibilityRule.sourceVisibilityRules[i].sourceControlValue))) { - if (this.formGroup.get(pathKey).parent.get('id')) { - if (!this.checkElementVisibility(this.formGroup.get(pathKey).parent.get('id').value)) { - const targetPathKey = this.fieldsPathMemory[visibilityRule.targetControlId]; - this.getObject(this.currentModel, 'id', visibilityRule.targetControlId, this.currentModel, true); - this.elementVisibilityMap.set(visibilityRule.targetControlId, false); - this.clearValues(targetPathKey); - return; - } - } else { - const targetPathKey = this.fieldsPathMemory[visibilityRule.targetControlId]; - this.getObject(this.currentModel, 'id', visibilityRule.targetControlId, this.currentModel, true); - this.elementVisibilityMap.set(visibilityRule.targetControlId, false); - this.clearValues(targetPathKey); - return; - } - } - } - const obj = this.getObject(this.initialModel, 'id', visibilityRule.targetControlId, this.initialModel); - const targetObjPathKey = this.fieldsPathMemory[visibilityRule.targetControlId] ? this.fieldsPathMemory[visibilityRule.targetControlId] : this.search('pages', this.initialModel.pages, obj); - this.updateValue(this.currentModel, obj, targetObjPathKey); - this.elementVisibilityMap.set(visibilityRule.targetControlId, true); - } - - private clearValues(pathKey) { - if (pathKey && this.formGroup.get(pathKey + '.value')) { this.formGroup.get(pathKey + '.value').patchValue(null); } - if (pathKey && this.formGroup.get(pathKey)['controls'].fields) { - for (let i = 0; i < this.formGroup.get(pathKey)['controls'].fields.length; i++) { - this.clearValues(pathKey + '.fields.' + i); - } - } - } - - parseValue(value: any) { - if (typeof value === 'string') { - if (value === 'true') { return true; } else if (value === 'false') { return false; } else { return this.translate(value); } - } else { return value; } - } - - updateValue(obj, value, path) { - let i; - path = path.split('.'); - - for (i = 0; i < path.length - 1; i++) { - obj = obj[path[i]]; - } - - for (let propIndex = 0; propIndex < obj.length; propIndex++) { - if (obj[propIndex] && obj[propIndex]['id'] === value['id']) { return; } - } - obj[path[i]] = value; - } - - search(path, obj, target) { - for (const k in obj) { - if (obj.hasOwnProperty(k)) { - if (obj[k] === target) { - return path + '.' + k; - } else if (typeof obj[k] === 'object') { - const result = this.search(path + '.' + k, obj[k], target); - if (result) { - return result; - } - } - } - } - return false; - } - - private getObject(obj, key, val, parent, deleteObj = false) { - for (const i in obj) { - if (!obj.hasOwnProperty(i)) { continue; } - if (typeof obj[i] === 'object') { - const returnObj = this.getObject(obj[i], key, val, obj, deleteObj); - if (returnObj) { return returnObj; } - } else if (i === key && obj[key] === val) { - //console.log(obj[key]) - if (deleteObj) { parent[parent.indexOf(obj)] = null; } - return obj; - } - } - } - - private translate(item: any) { - try { - return JSON.parse(item).value; - } catch (error) { - return item; - } - } -} diff --git a/dmp-frontend/src/app/welcomepage/welcomepage.component.html b/dmp-frontend/src/app/welcomepage/welcomepage.component.html deleted file mode 100644 index 171e9b627..000000000 --- a/dmp-frontend/src/app/welcomepage/welcomepage.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/dmp-frontend/src/app/welcomepage/welcomepage.component.ts b/dmp-frontend/src/app/welcomepage/welcomepage.component.ts deleted file mode 100644 index e92b28f61..000000000 --- a/dmp-frontend/src/app/welcomepage/welcomepage.component.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { Router, ActivatedRoute } from '@angular/router'; -import { DashboardService } from '../../app/services/dashboard/dashboard.service'; -import { DashboardStatisticsModel } from '../models/dashboard/DashboardStatisticsModel'; -import { JsonSerializer } from '../utilities/JsonSerializer'; -import { HomepageComponent } from '../homepage/homepage.component'; -import { IBreadCrumbComponent } from '../shared/components/breadcrumb/definition/IBreadCrumbComponent'; -import { Observable } from 'rxjs'; -import { BreadcrumbItem } from '../shared/components/breadcrumb/definition/breadcrumb-item'; - -@Component({ - selector: 'app-welcomepage', - templateUrl: './welcomepage.component.html', - // styleUrls: ['./homepage.component.css'], - providers: [DashboardService] -}) -export class WelcomepageComponent implements OnInit, IBreadCrumbComponent { - - breadCrumbs: Observable = Observable.of([]); - private userInfo: any; - private dashboardStatisticsData: DashboardStatisticsModel = new DashboardStatisticsModel(); - - constructor() { - } - - ngOnInit() { - //this.breadCrumbs = Observable.of([{ parentComponentName: null, label: 'Home', url: "/welcome" }]) - } - -} diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json new file mode 100644 index 000000000..3ab907f3b --- /dev/null +++ b/dmp-frontend/src/assets/i18n/en.json @@ -0,0 +1,603 @@ +{ + "GENERAL": { + "VALIDATION": { + "REQUIRED": "Required" + }, + "DELETE-CONFIRMATION": { + "TITLE": "Warning", + "MESSAGE": "Are you sure you want to delete this item?", + "POSITIVE": "Yes", + "NEGATIVE": "Cancel" + }, + "SNACK-BAR": { + "SUCCESSFUL-CREATION": "Created Successfully", + "SUCCESSFUL-UPDATE": "Updated Successfully", + "SUCCESSFUL-LOGIN": "Successful Login", + "SUCCESSFUL-LOGOUT": "Successful Logout", + "UNSUCCESSFUL-LOGOUT": "Unsuccessful Logout", + "UNSUCCESSFUL-LOGIN": "Unsuccessful Login" + }, + "ERRORS": { + "HTTP-REQUEST-ERROR": "An Unexpected Error Has Occured" + }, + "NAMES": { + "DATASET": "Dataset" + }, + "STATUSES": { + "EDIT": "Edited", + "FINALISED": "Finalized" + } + }, + "NAV-BAR": { + "TITLE": "OpenDMP", + "PROJECTS": "Projects", + "DMPS": "DMPs", + "DATASETS": "Datasets", + "PUBLIC-DATASETS": "Explore OpenDMP", + "USERS": "Users", + "DATASETS-ADMIN": "Dataset Profiles", + "DMP-PROFILES": "DMP Profiles", + "ABOUT": "About" + }, + "DATASET-PROFILE-EDITOR": { + "TITLE": { + "NEW": "New API Client" + }, + "FIELDS": { + "DATASET-TITLE": "Dataset Template Name", + "ROLES": "Roles" + }, + "STEPS": { + "PAGES": { + "TITLE": "Page Description", + "PAGE-PREFIX": "Page", + "PAGE-INPUT-TITLE": "Page Title" + }, + "FORM": { + "TITLE": "Form Description", + "SECTION": { + "TITLE": "Section Information", + "FIELDS": { + "ID": "Section Unique Identifier", + "TITLE": "Section Name", + "PAGE": "Page to appear", + "ORDER": "Order", + "FIELDS-TITLE": "Fields", + "SUB-SECTIONS-TITLE": "Sub-Sections" + }, + "ACTIONS": { + "ADD-SUB-SECTION": "Add Sub-Section +", + "ADD-FIELD": "Add Field +" + } + }, + "COMPOSITE-FIELD": { + "TITLE": "Composite Field Information", + "SIMPLE-FIELD-TITLE": "Field Information", + "SUB-FIELDS-TITLE": "Child Fields", + "FIELDS": { + "COMPOSITE-CHECKBOX": "Composite Field", + "MULTIPLICITY-CHECKBOX": "Multiplicity", + "COMMENT-CHECKBOX": "Include Comment Field", + "COMPOSITE-TITLE": "Composite Field Name", + "FIELD-TITLE": "Field Name", + "DESCRIPTION": "Description", + "EXTENDED-DESCRIPTION": "Extended Description", + "MULTIPLICITY-MIN": "Multiplicity Min", + "MULTIPLICITY-MAX": "Multiplicity Max", + "ORDER": "Order" + }, + "ACTIONS": { + "ADD-CHILD-FIELD": "Add Child Field +" + } + }, + "FIELD": { + "FIELDS": { + "RULES-TITLE": "Visibility Rules", + "ID": "Section Unique Identifier", + "VIEW-STYLE": "Type", + "MULTIPLICITY-MIN": "Multiplicity Min", + "MULTIPLICITY-MAX": "Multiplicity Max", + "ORDER": "Order", + "DEFAULT-VALUE": "Default Value", + "VALIDATION": "Validation", + "MULTIPLICITY-CHECKBOX": "Multiplicity", + "FIELD-TEXT-AREA-TITLE": "Text Area Data", + "FIELD-TEXT-AREA-PLACEHOLDER": "Input Placeholder", + "FIELD-BOOLEAN-DECISION-TITLE": "Boolean Decision Data", + "FIELD-BOOLEAN-DECISION-PLACEHOLDER": "Input Placeholder", + "FIELD-CHECKBOX-TITLE": "Checkbox Data", + "FIELD-CHECKBOX-PLACEHOLDER": "Input Placeholder", + "FIELD-FREE-TEXT-TITLE": "Free Text Data", + "FIELD-FREE-TEXT-PLACEHOLDER": "Input Placeholder", + "FIELD-COMBO-BOX-TYPE": "Type of Combo Box", + "FIELD-WORD-LIST-TITLE": "Word List Data", + "FIELD-WORD-LIST-PLACEHOLDER": "Input Placeholder", + "FIELD-WORD-LIST-LABEL": "Label", + "FIELD-WORD-LIST-VALUE": "Value", + "FIELD-RADIO-BOX-TITLE": "Radio Box Data", + "FIELD-RADIO-BOX-PLACEHOLDER": "Input Placeholder", + "FIELD-RADIO-BOX-LABEL": "Label", + "FIELD-RADIO-BOX-VALUE": "Value", + "FIELD-AUTOCOMPLETE-TITLE": "Autocomplete Data", + "FIELD-AUTOCOMPLETE-PLACEHOLDER": "Input Placeholder", + "FIELD-AUTOCOMPLETE-LABEL": "Label", + "FIELD-AUTOCOMPLETE-VALUE": "Value", + "FIELD-AUTOCOMPLETE-URL": "Url", + "FIELD-AUTOCOMPLETE-OPTIONS-ROOT": "Options Root" + }, + "ACTIONS": { + "ADD-RULE": "Add Visibility Rule +" + } + }, + "RULE": { + "FIELDS": { + "RULE-TYPE": "Rule Type", + "TARGET": "Target Field Id", + "VALUE": "Required Value" + } + } + } + }, + "ACTIONS": { + "SAVE": "Save", + "CANCEL": "Cancel", + "DELETE": "Delete", + "ADD-PAGE": "Add Page +", + "ADD-SECTION": "Add Section +" + } + }, + "PROJECT-LISTING": { + "TITLE": "Projects", + "COLUMNS": { + "AVATAR": "Image", + "NAME": "Name", + "ABBREVIATION": "Abbreviation", + "START": "Start", + "END": "End", + "ACTIONS": "Actions", + "DMPS": "DMPs" + } + }, + "DMP-LISTING": { + "TITLE": "Data Management Plans", + "COLUMNS": { + "NAME": "Name", + "PROJECT": "Project", + "PROFILE": "Profile", + "CREATION-TIME": "Creation Time", + "ORGANISATIONS": "Organisations", + "LATEST_VERSION": "Latest Version", + "ACTIONS": "Actions", + "DATASETS": "Datasets", + "STATUS": "Status" + }, + "ACTIONS": { + "EDIT": "Edit", + "INVITE": "Invite Contributors", + "ADD-DATASET": "Add Dataset To DMP", + "DATASETS": "List All DMP Datasets", + "NEW-VERSION": "New Version", + "VIEW-VERSION": "All DMP Versions", + "CLONE": "Clone", + "DOWNLOAD-XML": "Download XML", + "DOWNLOAD-DOCX": "Download Document", + "DOWNLOAD-PDF": "Download PDF" + } + }, + "DATASET-WIZARD": { + "TITLE": { + "NEW": "New Dataset Description" + }, + "EDITOR": { + "FIELDS": { + "EXTERNAL-DATASET-TYPE": "Type" + } + }, + "FIRST-STEP": { + "TITLE": "Dataset Information", + "DMP": "Data Management Plan", + "PROFILE": "Dataset Profile" + }, + "SECOND-STEP": { + "TITLE": "External References" + }, + "THIRD-STEP": { + "TITLE": "Description" + }, + "ACTIONS": { + "NEXT": "Next", + "BACK": "Back", + "DELETE": "Delete", + "GO-TO-PROJECT": "Go to Dataset Project", + "GO-TO-DMP": "Go to Dataset DMP", + "SAVE": "Save", + "SAVE-AND-FINALISE": "Save and Finalise", + "DOWNLOAD-PDF": "Download PDF", + "DOWNLOAD-XML": "Download XML" + } + }, + "DATASET-LISTING": { + "TITLE": "Datasets", + "COLUMNS": { + "NAME": "Name", + "REFERNCE": "Reference", + "PROJECT": "Project", + "URI": "Uri", + "STATUS": "Status", + "DESCRIPTION": "Description", + "CREATED": "Created", + "ACTIONS": "Actions", + "DMP": "Dmp", + "PROFILE": "Profile", + "DATAREPOSITORIES": "Data Repositories", + "REGISTRIES": "Registries", + "SERVICES": "Services" + }, + "ACTIONS": { + "EDIT": "Edit", + "MAKE-IT-PUBLIC": "Make it public", + "VIEW": "View" + } + }, + "DATASET-PUBLIC-LISTING": { + "TITLE": "Published dataset descriptions" + }, + "DATASET-PROFILE-LISTING": { + "TITLE": "Dataset Profiles", + "COLUMNS": { + "NAME": "Name", + "REFERNCE": "Reference", + "PROJECT": "Project", + "URI": "Uri", + "STATUS": "Status", + "DESCRIPTION": "Description", + "CREATED": "Created", + "ACTIONS": "Actions", + "DMP": "Dmp", + "PROFILE": "Profile", + "DATAREPOSITORIES": "Data Repositories", + "REGISTRIES": "Registries", + "SERVICES": "Services" + }, + "ACTIONS": { + "EDIT": "Edit", + "MAKE-IT-PUBLIC": "Make it public", + "VIEW": "View", + "CLONE": "Clone" + } + }, + "DMP-PROFILE-EDITOR": { + "TITLE": { + "NEW": "New DMP Profile", + "EDIT": "Edit" + }, + "FIELDS": { + "TITLE": "Fields", + "LABEL": "Name", + "TYPE": "Type", + "DATATYPE": "Data Type", + "REQUIRED": "Required" + }, + "ACTIONS": { + "SAVE": "Save", + "CANCEL": "Cancel", + "DELETE": "Delete" + } + }, + "PROJECT-EDITOR": { + "TITLE": { + "NEW": "New Project", + "EDIT": "Edit" + }, + "FIELDS": { + "LABEL": "Title", + "ABBREVIATION": "Abbreviation", + "URI": "URL", + "START": "Start", + "END": "End", + "DESCRIPTION": "Description", + "LOGO": "Project Logo" + }, + "ACTIONS": { + "SAVE": "Save", + "CANCEL": "Cancel", + "DELETE": "Delete", + "GO-TO-DMPS": "Go To DMPs" + } + }, + "DMP-EDITOR": { + "TITLE": { + "NEW": "New Data Management Plan", + "EDIT": "Edit" + }, + "FIELDS": { + "NAME": "Name", + "PROJECT": "Project", + "DESCRIPTION": "Description", + "ORGANISATIONS": "Organisations", + "RESEARCHERS": "Researchers", + "PROFILES": "Available Dataset Profiles", + "PROFILE": "DMP Profile", + "GRANT": "Grant", + "FUNDER": "Funder" + }, + "ACTIONS": { + "GO-TO-PROJECT": "Go To DMP Project", + "GO-TO-DATASETS": "Go To Datasets", + "SAVE": "Save", + "CANCEL": "Cancel", + "DELETE": "Delete", + "FINALISE": "Finalize" + } + }, + "DMP-PROFILE-LISTING": { + "TITLE": "DMP Profiles", + "COLUMNS": { + "NAME": "Name", + "STATUS": "Status", + "CREATED": "Created" + } + }, + "DYNAMIC-FORM": { + "FIELDS": { + "LABEL": "Label" + }, + "ACTIONS": { + "PREVIEW": "Preview", + "ADD-PAGE": "Add Page +", + "ADD-SECTION": "Add Section +" + } + }, + "CRITERIA": { + "FILTERS": "Filters", + "PROJECTS": { + "LIKE": "Search", + "PERIOD-FROM": "Project Start", + "PERIOD-TO": "Project End", + "PROJECT-STATE-TYPE": "Project Status", + "TYPES": { + "ON-GOING": "On Going", + "FINISHED": "Finished" + } + }, + "DATASET-PROFILE": { + "LIKE": "Search" + }, + "DATA-SETS": { + "PERIOD-FROM": "Start", + "PERIOD-TO": "End", + "STATUS": "Status", + "TAGS": "Tags" + }, + "DMP": { + "LIKE": "Search", + "PROJECTS": "Projects" + }, + "USERS": { + "LABEL": "Search", + "ROLE": "Role" + } + }, + "DATASET-EDITOR": { + "TITLE": { + "NEW": "New Data Management Plan", + "EDIT": "Edit" + }, + "FIELDS": { + "NAME": "Name of the Dataset", + "DESCRIPTION": "Description", + "PROFILE": "Profile", + "URI": "Uri", + "DMP": "DMP", + "DATAREPOSITORIES": "Data Repositories", + "REGISTRIES": "Registries", + "SERVICES": "Services", + "EXTERNAL-DATASETS": "External Datasets", + "EXTERNAL-DATASET-TYPE": "External Datasets Type", + "EXTERNAL-DATASET-INFO": "External Datasets Info", + "DATAREPOSITORIES-INFO": "Data Repositories Info", + "TAGS": "Tags", + "CREATE": "Create New" + }, + "ACTIONS": { + "SAVE": "Save", + "CANCEL": "Cancel", + "DELETE": "Delete" + } + }, + "INVITATION-EDITOR": { + "TITLE": "Send Invitations for ", + "AUTOCOMPLETE-TITLE": "User/Email", + "ACTIONS": { + "SEND-INVITATION": "Send Invitations", + "CANCEL": "Cancel" + } + }, + "USERS": { + "LISTING": { + "TITLE": "Users", + "EMAIL": "Email", + "LAST-LOGGED-IN": "Last Logged In", + "LABEL": "Label", + "ROLES": "Roles" + } + }, + "TYPES": { + "APP-ROLE": { + "ADMIN": "Admin", + "USER": "User", + "MANAGER": "Manager" + }, + "DMP-PROFILE-FIELD": { + "DATA-TYPE": { + "DATE": "Date", + "NUMBER": "Number", + "TEXT": "Text" + }, + "TYPE": { + "INPUT": "Input" + } + }, + "DATASET-STATUS": { + "DRAFT": "Draft", + "FINALISED": "Finalized" + }, + "EXTERNAL-DATASET-TYPE": { + "SOURCE": "Source", + "OUTPUT": "Output" + }, + "DMP": { + "FINALISED": "Finalized", + "DRAFT": "Draft" + }, + "DATASET-PROFILE-FIELD-VALIDATION-TYPE": { + "NONE": "None", + "REQUIRED": "Required" + }, + "DATASET-PROFILE-FIELD-VIEW-STYLE": { + "BOOLEAN-DECISION": "Boolean Decision", + "CHECKBOX": "Checkbox", + "COMBO-BOX": "Combo Box", + "FREE-TEXT": "Free Text", + "RADIO-BOX": "Radio Box", + "TEXT-AREA": "Text Area" + }, + "DATASET-PROFILE-COMBO-BOX-TYPE": { + "WORD-LIST": "Word List", + "AUTOCOMPLETE": "Autocomplete" + } + }, + "ADDRESEARCHERS-EDITOR": { + "TITLE": "Add a Researcher", + "FIRST_NAME": "First Name", + "LAST_NAME": "Last Name", + "ACTIONS": { + "SAVE": "Save", + "CANCEL": "Cancel" + } + }, + "DMP-WIZARD": { + "FIRST-STEP": { + "DMP": "DMP Editor", + "DATASETS": "Datasets" + }, + "ACTIONS": { + "NEXT": "Next", + "BACK": "Back", + "SAVE": "Save" + } + }, + "DATASET-PROFILE": { + "PREVIEW": "Preview", + "FORM-DESCRIPTION": "Form Description", + "PAGES-DESCRIPTION": "Pages Description" + }, + "RECENT-ACTIVITY": { + "MY-TITLE-PROJECT": "My Recent Project Activity", + "MY-TITLE-DMP": "My Recent DMP Activity", + "MY-TITLE-DATASET": "My Recent Dataset Activity" + }, + "FILE-UPLOADER": { + "DEFAULT": "Choose a file", + "PROJECT": "", + "UPLOAD": "Upload" + }, + "URL-LISTING-COMPONENT": { + "SHOW-MORE": "Show more" + }, + "HOMEPAGE": { + "OPEN-DMPS": { + "STATS": "OpenDMP Dashboard" + }, + "MY-DMPS": { + "STATS": "My Dashboard" + } + }, + "ABOUT": { + "TITLE": "-Our Mission-", + "MAIN-CONTENT": "Our goal is to make your research data FAIR, that is findable, accessible,interoperable and re-usable. These principles precede implementation choices and do not necessarily suggest any specific technology, standard, or implementationsolution.", + "CONTRIBUTORS": "Contributors" + }, + "DASHBOARD": { + "MY-PROJECTS": "My Projects", + "PROJECTS": "Projects", + "MY-DMPS": "My DMPs", + "DMPS": "DMPs", + "MY-DATASETS": "My Datasets", + "DATASETS": "Datasets", + "SEARCH": "Search" + }, + "USER-DIALOG": { + "USER-PROFILE": "My Profile", + "EXIT": "Exit " + }, + "USER-PROFILE": { + "SETTINGS": { + "TITLE": "Settings", + "TIMEZONE": "Time Zone", + "CULTURE": "Culture", + "LANGUAGE": "Language" + }, + "ASSOCIATED-DMPS": "Associated DMPs", + "DMPS": { + "SHOW-ALL": "Show All", + "CREATOR": "Creator", + "MEMBER": "Member" + } + }, + "DATASET-REFERENCED-MODELS": { + "SERVICES": { + "TITLE": "Add New Service", + "LABEL": "Label", + "ABBREVIATION": "Abbreviation", + "URI": "Uri" + }, + "DATA-REPOSITORY": { + "TITLE": "Add New Service", + "LABEL": "Label", + "ABBREVIATION": "Abbreviation", + "URI": "Uri" + }, + "EXTERNAL-DATASET": { + "TITLE": "Add New Service", + "LABEL": "Label", + "ABBREVIATION": "Abbreviation" + }, + "REGISTRY": { + "TITLE": "Add New Service", + "LABEL": "Label", + "ABBREVIATION": "Abbreviation", + "URI": "Uri" + } + }, + "FACET-SEARCH": { + "FILTER": "Filter", + "PROJECT-STATUS": { + "TITLE": "Project Status", + "OPTIONS": { + "ACTIVE": "Active", + "INACTIVE": "Inactive" + } + }, + "PROJECT": { + "TITLE": "Project", + "FILTER": "Filter Projects" + }, + "PROFILES": { + "TITLE": "Dataset specification" + }, + "DMP-ORGANISATIONS": { + "TITLE": "DMP Organisations", + "FILTER": "Filter Organisations" + } + }, + "DMP-FINALISE-DIALOG": { + "SUBMIT": "Submit", + "FINALISE-TITLE": "Do you want to finalise any of the following Datasets?", + "ALREADY-FINALISED-DATASETS": "Already Finalized Datasets", + "NONE": "None", + "VALIDATION": { + "AT-LEAST-ONE-DATASET-FINALISED": "You need to have at least one Dataset Finalized" + } + } +} diff --git a/dmp-frontend/src/assets/i18n/gr.json b/dmp-frontend/src/assets/i18n/gr.json new file mode 100644 index 000000000..0d5810d52 --- /dev/null +++ b/dmp-frontend/src/assets/i18n/gr.json @@ -0,0 +1,21 @@ +{ + "GENERAL": { + "VALIDATION": { + "REQUIRED": "Required" + } + }, + "USER-PROFILE": { + "SETTINGS": { + "TITLE": "Ρυθμίσεις", + "TIMEZONE": "Ζώνη Ώρας", + "CULTURE": "Κουλτούρα", + "LANGUAGE": "Γλώσσα" + }, + "ASSOCIATED-DMPS": "Συσχετιζόμενα DMPs", + "DMPS": { + "SHOW-ALL": "Όλα", + "CREATOR": "Δημιουργός", + "MEMBER": "Μέλος" + } + } +} diff --git a/dmp-frontend/src/assets/lang/en.json b/dmp-frontend/src/assets/lang/en.json index 273af2fe2..9e2127e5d 100644 --- a/dmp-frontend/src/assets/lang/en.json +++ b/dmp-frontend/src/assets/lang/en.json @@ -39,6 +39,26 @@ "DMP-PROFILES": "DMP Profiles", "ABOUT": "About" }, + "DATASET-PROFILE-EDITOR": { + "TITLE": { + "NEW": "New API Client" + }, + "FIELDS": { + "DATASET-TITLE": "Dataset Template Name", + "ROLES": "Roles" + }, + "STEPS": { + "PAGES": "Page Description", + "FORM": "Form Description" + }, + "ACTIONS": { + "SAVE": "Save", + "CANCEL": "Cancel", + "DELETE": "Delete", + "ADD-PAGE": "Add Page +", + "ADD-SECTION": "Add Section +" + } + }, "PROJECT-LISTING": { "TITLE": "Projects", "COLUMNS": { @@ -332,14 +352,14 @@ }, "DATASET-STATUS": { "DRAFT": "Draft", - "FINALISED": "Finalised" + "FINALISED": "Finalized" }, "EXTERNAL-DATASET-TYPE": { "SOURCE": "Source", "OUTPUT": "Output" }, "DMP": { - "FINALISED": "Finalised", + "FINALISED": "Finalized", "DRAFT": "Draft" } }, @@ -470,10 +490,10 @@ "DMP-FINALISE-DIALOG": { "SUBMIT": "Submit", "FINALISE-TITLE": "Do you want to finalise any of the following Datasets?", - "ALREADY-FINALISED-DATASETS": "Already Finalised Datasets", + "ALREADY-FINALISED-DATASETS": "Already Finalized Datasets", "NONE": "None", "VALIDATION": { - "AT-LEAST-ONE-DATASET-FINALISED": "You need to have at least one Dataset Finalised" + "AT-LEAST-ONE-DATASET-FINALISED": "You need to have at least one Dataset Finalized" } } } diff --git a/dmp-frontend/src/assets/localization/available-cultures.json b/dmp-frontend/src/assets/localization/available-cultures.json new file mode 100644 index 000000000..102b0d38a --- /dev/null +++ b/dmp-frontend/src/assets/localization/available-cultures.json @@ -0,0 +1,2816 @@ +[{ + "name": "aa-DJ", + "displayName": "Qafar (Yabuuti)", + "nativeName": "Qafar (Yabuuti)" + }, + { + "name": "aa-ER", + "displayName": "Qafar (Eretria)", + "nativeName": "Qafar (Eretria)" + }, + { + "name": "aa-ET", + "displayName": "Qafar (Otobbia)", + "nativeName": "Qafar (Otobbia)" + }, + { + "name": "af-NA", + "displayName": "Afrikaans (Namibië)", + "nativeName": "Afrikaans (Namibië)" + }, + { + "name": "af-ZA", + "displayName": "Afrikaans (South Africa)", + "nativeName": "Afrikaans (Suid-Afrika)" + }, + { + "name": "agq-CM", + "displayName": "Aghem (Kàmàlûŋ)", + "nativeName": "Aghem (Kàmàlûŋ)" + }, + { + "name": "ak-GH", + "displayName": "Akan (Gaana)", + "nativeName": "Akan (Gaana)" + }, + { + "name": "am-ET", + "displayName": "Amharic (Ethiopia)", + "nativeName": "አማርኛ (ኢትዮጵያ)" + }, + { + "name": "ar-001", + "displayName": "العربية (العالم)", + "nativeName": "العربية (العالم)" + }, + { + "name": "ar-AE", + "displayName": "Arabic (United Arab Emirates)", + "nativeName": "العربية (الإمارات العربية المتحدة)" + }, + { + "name": "ar-BH", + "displayName": "Arabic (Bahrain)", + "nativeName": "العربية (البحرين)" + }, + { + "name": "ar-DJ", + "displayName": "العربية (جيبوتي)", + "nativeName": "العربية (جيبوتي)" + }, + { + "name": "ar-DZ", + "displayName": "Arabic (Algeria)", + "nativeName": "العربية (الجزائر)" + }, + { + "name": "ar-EG", + "displayName": "Arabic (Egypt)", + "nativeName": "العربية (مصر)" + }, + { + "name": "ar-ER", + "displayName": "العربية (إريتريا)", + "nativeName": "العربية (إريتريا)" + }, + { + "name": "ar-IL", + "displayName": "العربية (إسرائيل)", + "nativeName": "العربية (إسرائيل)" + }, + { + "name": "ar-IQ", + "displayName": "Arabic (Iraq)", + "nativeName": "العربية (العراق)" + }, + { + "name": "ar-JO", + "displayName": "Arabic (Jordan)", + "nativeName": "العربية (الأردن)" + }, + { + "name": "ar-KM", + "displayName": "العربية (جزر القمر)", + "nativeName": "العربية (جزر القمر)" + }, + { + "name": "ar-KW", + "displayName": "Arabic (Kuwait)", + "nativeName": "العربية (الكويت)" + }, + { + "name": "ar-LB", + "displayName": "Arabic (Lebanon)", + "nativeName": "العربية (لبنان)" + }, + { + "name": "ar-LY", + "displayName": "Arabic (Libya)", + "nativeName": "العربية (ليبيا)" + }, + { + "name": "ar-MA", + "displayName": "Arabic (Morocco)", + "nativeName": "العربية (المملكة المغربية)" + }, + { + "name": "ar-MR", + "displayName": "العربية (موريتانيا)", + "nativeName": "العربية (موريتانيا)" + }, + { + "name": "ar-OM", + "displayName": "Arabic (Oman)", + "nativeName": "العربية (عمان)" + }, + { + "name": "ar-PS", + "displayName": "العربية (السلطة الفلسطينية)", + "nativeName": "العربية (السلطة الفلسطينية)" + }, + { + "name": "ar-QA", + "displayName": "Arabic (Qatar)", + "nativeName": "العربية (قطر)" + }, + { + "name": "ar-SA", + "displayName": "Arabic (Saudi Arabia)", + "nativeName": "العربية (المملكة العربية السعودية)" + }, + { + "name": "ar-SD", + "displayName": "العربية (السودان)", + "nativeName": "العربية (السودان)" + }, + { + "name": "ar-SO", + "displayName": "العربية (الصومال)", + "nativeName": "العربية (الصومال)" + }, + { + "name": "ar-SS", + "displayName": "العربية (جنوب السودان)", + "nativeName": "العربية (جنوب السودان)" + }, + { + "name": "ar-SY", + "displayName": "Arabic (Syria)", + "nativeName": "العربية (سوريا)" + }, + { + "name": "ar-TD", + "displayName": "العربية (تشاد)", + "nativeName": "العربية (تشاد)" + }, + { + "name": "ar-TN", + "displayName": "Arabic (Tunisia)", + "nativeName": "العربية (تونس)" + }, + { + "name": "ar-YE", + "displayName": "Arabic (Yemen)", + "nativeName": "العربية (اليمن)" + }, + { + "name": "arn-CL", + "displayName": "Mapudungun (Chile)", + "nativeName": "Mapudungun (Chile)" + }, + { + "name": "as-IN", + "displayName": "Assamese (India)", + "nativeName": "অসমীয়া (ভাৰত)" + }, + { + "name": "asa-TZ", + "displayName": "Kipare (Tadhania)", + "nativeName": "Kipare (Tadhania)" + }, + { + "name": "ast-ES", + "displayName": "asturianu (España)", + "nativeName": "asturianu (España)" + }, + { + "name": "az-Cyrl-AZ", + "displayName": "Azerbaijani (Cyrillic, Azerbaijan)", + "nativeName": "азәрбајҹан (Азәрбајҹан)" + }, + { + "name": "az-Latn-AZ", + "displayName": "Azerbaijani (Latin, Azerbaijan)", + "nativeName": "azərbaycan (Azərbaycan)" + }, + { + "name": "ba-RU", + "displayName": "Bashkir (Russia)", + "nativeName": "Башҡорт (Рәсәй)" + }, + { + "name": "bas-CM", + "displayName": "Ɓàsàa (Kàmɛ̀rûn)", + "nativeName": "Ɓàsàa (Kàmɛ̀rûn)" + }, + { + "name": "be-BY", + "displayName": "Belarusian (Belarus)", + "nativeName": "Беларуская (Беларусь)" + }, + { + "name": "bem-ZM", + "displayName": "Ichibemba (Zambia)", + "nativeName": "Ichibemba (Zambia)" + }, + { + "name": "bez-TZ", + "displayName": "Hibena (Hutanzania)", + "nativeName": "Hibena (Hutanzania)" + }, + { + "name": "bg-BG", + "displayName": "Bulgarian (Bulgaria)", + "nativeName": "български (България)" + }, + { + "name": "bin-NG", + "displayName": "Edo (Nigeria)", + "nativeName": "Ẹ̀dó (Nigeria)" + }, + { + "name": "bm-Latn-ML", + "displayName": "bamanakan (Mali)", + "nativeName": "bamanakan (Mali)" + }, + { + "name": "bn-BD", + "displayName": "Bangla (Bangladesh)", + "nativeName": "বাংলা (বাংলাদেশ)" + }, + { + "name": "bn-IN", + "displayName": "Bangla (India)", + "nativeName": "বাংলা (ভারত)" + }, + { + "name": "bo-CN", + "displayName": "Tibetan (China)", + "nativeName": "བོད་ཡིག (ཀྲུང་ཧྭ་མི་དམངས་སྤྱི་མཐུན་རྒྱལ་ཁབ།)" + }, + { + "name": "bo-IN", + "displayName": "བོད་སྐད་ (རྒྱ་གར་)", + "nativeName": "བོད་སྐད་ (རྒྱ་གར་)" + }, + { + "name": "br-FR", + "displayName": "Breton (France)", + "nativeName": "brezhoneg (Frañs)" + }, + { + "name": "brx-IN", + "displayName": "बड़ो (भारत)", + "nativeName": "बड़ो (भारत)" + }, + { + "name": "bs-Cyrl-BA", + "displayName": "Bosnian (Cyrillic, Bosnia and Herzegovina)", + "nativeName": "босански (Босна и Херцеговина)" + }, + { + "name": "bs-Latn-BA", + "displayName": "Bosnian (Latin, Bosnia and Herzegovina)", + "nativeName": "bosanski (Bosna i Hercegovina)" + }, + { + "name": "byn-ER", + "displayName": "ብሊን (ኤርትራ)", + "nativeName": "ብሊን (ኤርትራ)" + }, + { + "name": "ca-AD", + "displayName": "català (Andorra)", + "nativeName": "català (Andorra)" + }, + { + "name": "ca-ES", + "displayName": "Catalan (Catalan)", + "nativeName": "català (català)" + }, + { + "name": "ca-ES-valencia", + "displayName": "Valencian (Spain)", + "nativeName": "valencià (Espanya)" + }, + { + "name": "ca-FR", + "displayName": "català (França)", + "nativeName": "català (França)" + }, + { + "name": "ca-IT", + "displayName": "català (Itàlia)", + "nativeName": "català (Itàlia)" + }, + { + "name": "ce-RU", + "displayName": "нохчийн (Росси)", + "nativeName": "нохчийн (Росси)" + }, + { + "name": "cgg-UG", + "displayName": "Rukiga (Uganda)", + "nativeName": "Rukiga (Uganda)" + }, + { + "name": "chr-Cher-US", + "displayName": "Cherokee (Cherokee, United States)", + "nativeName": "ᏣᎳᎩ (ᏌᏊ ᎢᏳᎾᎵᏍᏔᏅ ᏍᎦᏚᎩ)" + }, + { + "name": "co-FR", + "displayName": "Corsican (France)", + "nativeName": "Corsu (Francia)" + }, + { + "name": "cs-CZ", + "displayName": "Czech (Czechia)", + "nativeName": "čeština (Česko)" + }, + { + "name": "cu-RU", + "displayName": "церковнослове́нскїй (рѡссі́а)", + "nativeName": "церковнослове́нскїй (рѡссі́а)" + }, + { + "name": "cy-GB", + "displayName": "Welsh (United Kingdom)", + "nativeName": "Cymraeg (Y Deyrnas Unedig)" + }, + { + "name": "da-DK", + "displayName": "Danish (Denmark)", + "nativeName": "dansk (Danmark)" + }, + { + "name": "da-GL", + "displayName": "dansk (Grønland)", + "nativeName": "dansk (Grønland)" + }, + { + "name": "dav-KE", + "displayName": "Kitaita (Kenya)", + "nativeName": "Kitaita (Kenya)" + }, + { + "name": "de-AT", + "displayName": "German (Austria)", + "nativeName": "Deutsch (Österreich)" + }, + { + "name": "de-BE", + "displayName": "Deutsch (Belgien)", + "nativeName": "Deutsch (Belgien)" + }, + { + "name": "de-CH", + "displayName": "German (Switzerland)", + "nativeName": "Deutsch (Schweiz)" + }, + { + "name": "de-DE", + "displayName": "German (Germany)", + "nativeName": "Deutsch (Deutschland)" + }, + { + "name": "de-IT", + "displayName": "Deutsch (Italien)", + "nativeName": "Deutsch (Italien)" + }, + { + "name": "de-LI", + "displayName": "German (Liechtenstein)", + "nativeName": "Deutsch (Liechtenstein)" + }, + { + "name": "de-LU", + "displayName": "German (Luxembourg)", + "nativeName": "Deutsch (Luxemburg)" + }, + { + "name": "dje-NE", + "displayName": "Zarmaciine (Nižer)", + "nativeName": "Zarmaciine (Nižer)" + }, + { + "name": "dsb-DE", + "displayName": "Lower Sorbian (Germany)", + "nativeName": "dolnoserbšćina (Nimska)" + }, + { + "name": "dua-CM", + "displayName": "duálá (Cameroun)", + "nativeName": "duálá (Cameroun)" + }, + { + "name": "dv-MV", + "displayName": "Divehi (Maldives)", + "nativeName": "ދިވެހިބަސް (ދިވެހި ރާއްޖެ)" + }, + { + "name": "dyo-SN", + "displayName": "joola (Senegal)", + "nativeName": "joola (Senegal)" + }, + { + "name": "dz-BT", + "displayName": "Dzongkha (Bhutan)", + "nativeName": "རྫོང་ཁ (འབྲུག)" + }, + { + "name": "ebu-KE", + "displayName": "Kĩembu (Kenya)", + "nativeName": "Kĩembu (Kenya)" + }, + { + "name": "ee-GH", + "displayName": "Eʋegbe (Ghana nutome)", + "nativeName": "Eʋegbe (Ghana nutome)" + }, + { + "name": "ee-TG", + "displayName": "Eʋegbe (Togo nutome)", + "nativeName": "Eʋegbe (Togo nutome)" + }, + { + "name": "el-CY", + "displayName": "Ελληνικά (Κύπρος)", + "nativeName": "Ελληνικά (Κύπρος)" + }, + { + "name": "el-GR", + "displayName": "Greek (Greece)", + "nativeName": "Ελληνικά (Ελλάδα)" + }, + { + "name": "en-001", + "displayName": "English (World)", + "nativeName": "English (World)" + }, + { + "name": "en-029", + "displayName": "English (Caribbean)", + "nativeName": "English (Caribbean)" + }, + { + "name": "en-150", + "displayName": "English (Europe)", + "nativeName": "English (Europe)" + }, + { + "name": "en-AG", + "displayName": "English (Antigua and Barbuda)", + "nativeName": "English (Antigua and Barbuda)" + }, + { + "name": "en-AI", + "displayName": "English (Anguilla)", + "nativeName": "English (Anguilla)" + }, + { + "name": "en-AS", + "displayName": "English (American Samoa)", + "nativeName": "English (American Samoa)" + }, + { + "name": "en-AT", + "displayName": "English (Austria)", + "nativeName": "English (Austria)" + }, + { + "name": "en-AU", + "displayName": "English (Australia)", + "nativeName": "English (Australia)" + }, + { + "name": "en-BB", + "displayName": "English (Barbados)", + "nativeName": "English (Barbados)" + }, + { + "name": "en-BE", + "displayName": "English (Belgium)", + "nativeName": "English (Belgium)" + }, + { + "name": "en-BI", + "displayName": "English (Burundi)", + "nativeName": "English (Burundi)" + }, + { + "name": "en-BM", + "displayName": "English (Bermuda)", + "nativeName": "English (Bermuda)" + }, + { + "name": "en-BS", + "displayName": "English (Bahamas)", + "nativeName": "English (Bahamas)" + }, + { + "name": "en-BW", + "displayName": "English (Botswana)", + "nativeName": "English (Botswana)" + }, + { + "name": "en-BZ", + "displayName": "English (Belize)", + "nativeName": "English (Belize)" + }, + { + "name": "en-CA", + "displayName": "English (Canada)", + "nativeName": "English (Canada)" + }, + { + "name": "en-CC", + "displayName": "English (Cocos (Keeling) Islands)", + "nativeName": "English (Cocos (Keeling) Islands)" + }, + { + "name": "en-CH", + "displayName": "English (Switzerland)", + "nativeName": "English (Switzerland)" + }, + { + "name": "en-CK", + "displayName": "English (Cook Islands)", + "nativeName": "English (Cook Islands)" + }, + { + "name": "en-CM", + "displayName": "English (Cameroon)", + "nativeName": "English (Cameroon)" + }, + { + "name": "en-CX", + "displayName": "English (Christmas Island)", + "nativeName": "English (Christmas Island)" + }, + { + "name": "en-CY", + "displayName": "English (Cyprus)", + "nativeName": "English (Cyprus)" + }, + { + "name": "en-DE", + "displayName": "English (Germany)", + "nativeName": "English (Germany)" + }, + { + "name": "en-DK", + "displayName": "English (Denmark)", + "nativeName": "English (Denmark)" + }, + { + "name": "en-DM", + "displayName": "English (Dominica)", + "nativeName": "English (Dominica)" + }, + { + "name": "en-ER", + "displayName": "English (Eritrea)", + "nativeName": "English (Eritrea)" + }, + { + "name": "en-FI", + "displayName": "English (Finland)", + "nativeName": "English (Finland)" + }, + { + "name": "en-FJ", + "displayName": "English (Fiji)", + "nativeName": "English (Fiji)" + }, + { + "name": "en-FK", + "displayName": "English (Falkland Islands)", + "nativeName": "English (Falkland Islands)" + }, + { + "name": "en-FM", + "displayName": "English (Micronesia)", + "nativeName": "English (Micronesia)" + }, + { + "name": "en-GB", + "displayName": "English (United Kingdom)", + "nativeName": "English (United Kingdom)" + }, + { + "name": "en-GD", + "displayName": "English (Grenada)", + "nativeName": "English (Grenada)" + }, + { + "name": "en-GG", + "displayName": "English (Guernsey)", + "nativeName": "English (Guernsey)" + }, + { + "name": "en-GH", + "displayName": "English (Ghana)", + "nativeName": "English (Ghana)" + }, + { + "name": "en-GI", + "displayName": "English (Gibraltar)", + "nativeName": "English (Gibraltar)" + }, + { + "name": "en-GM", + "displayName": "English (Gambia)", + "nativeName": "English (Gambia)" + }, + { + "name": "en-GU", + "displayName": "English (Guam)", + "nativeName": "English (Guam)" + }, + { + "name": "en-GY", + "displayName": "English (Guyana)", + "nativeName": "English (Guyana)" + }, + { + "name": "en-HK", + "displayName": "English (Hong Kong SAR)", + "nativeName": "English (Hong Kong SAR)" + }, + { + "name": "en-ID", + "displayName": "English (Indonesia)", + "nativeName": "English (Indonesia)" + }, + { + "name": "en-IE", + "displayName": "English (Ireland)", + "nativeName": "English (Ireland)" + }, + { + "name": "en-IL", + "displayName": "English (Israel)", + "nativeName": "English (Israel)" + }, + { + "name": "en-IM", + "displayName": "English (Isle of Man)", + "nativeName": "English (Isle of Man)" + }, + { + "name": "en-IN", + "displayName": "English (India)", + "nativeName": "English (India)" + }, + { + "name": "en-IO", + "displayName": "English (British Indian Ocean Territory)", + "nativeName": "English (British Indian Ocean Territory)" + }, + { + "name": "en-JE", + "displayName": "English (Jersey)", + "nativeName": "English (Jersey)" + }, + { + "name": "en-JM", + "displayName": "English (Jamaica)", + "nativeName": "English (Jamaica)" + }, + { + "name": "en-KE", + "displayName": "English (Kenya)", + "nativeName": "English (Kenya)" + }, + { + "name": "en-KI", + "displayName": "English (Kiribati)", + "nativeName": "English (Kiribati)" + }, + { + "name": "en-KN", + "displayName": "English (Saint Kitts and Nevis)", + "nativeName": "English (Saint Kitts and Nevis)" + }, + { + "name": "en-KY", + "displayName": "English (Cayman Islands)", + "nativeName": "English (Cayman Islands)" + }, + { + "name": "en-LC", + "displayName": "English (Saint Lucia)", + "nativeName": "English (Saint Lucia)" + }, + { + "name": "en-LR", + "displayName": "English (Liberia)", + "nativeName": "English (Liberia)" + }, + { + "name": "en-LS", + "displayName": "English (Lesotho)", + "nativeName": "English (Lesotho)" + }, + { + "name": "en-MG", + "displayName": "English (Madagascar)", + "nativeName": "English (Madagascar)" + }, + { + "name": "en-MH", + "displayName": "English (Marshall Islands)", + "nativeName": "English (Marshall Islands)" + }, + { + "name": "en-MO", + "displayName": "English (Macao SAR)", + "nativeName": "English (Macao SAR)" + }, + { + "name": "en-MP", + "displayName": "English (Northern Mariana Islands)", + "nativeName": "English (Northern Mariana Islands)" + }, + { + "name": "en-MS", + "displayName": "English (Montserrat)", + "nativeName": "English (Montserrat)" + }, + { + "name": "en-MT", + "displayName": "English (Malta)", + "nativeName": "English (Malta)" + }, + { + "name": "en-MU", + "displayName": "English (Mauritius)", + "nativeName": "English (Mauritius)" + }, + { + "name": "en-MW", + "displayName": "English (Malawi)", + "nativeName": "English (Malawi)" + }, + { + "name": "en-MY", + "displayName": "English (Malaysia)", + "nativeName": "English (Malaysia)" + }, + { + "name": "en-NA", + "displayName": "English (Namibia)", + "nativeName": "English (Namibia)" + }, + { + "name": "en-NF", + "displayName": "English (Norfolk Island)", + "nativeName": "English (Norfolk Island)" + }, + { + "name": "en-NG", + "displayName": "English (Nigeria)", + "nativeName": "English (Nigeria)" + }, + { + "name": "en-NL", + "displayName": "English (Netherlands)", + "nativeName": "English (Netherlands)" + }, + { + "name": "en-NR", + "displayName": "English (Nauru)", + "nativeName": "English (Nauru)" + }, + { + "name": "en-NU", + "displayName": "English (Niue)", + "nativeName": "English (Niue)" + }, + { + "name": "en-NZ", + "displayName": "English (New Zealand)", + "nativeName": "English (New Zealand)" + }, + { + "name": "en-PG", + "displayName": "English (Papua New Guinea)", + "nativeName": "English (Papua New Guinea)" + }, + { + "name": "en-PH", + "displayName": "English (Philippines)", + "nativeName": "English (Philippines)" + }, + { + "name": "en-PK", + "displayName": "English (Pakistan)", + "nativeName": "English (Pakistan)" + }, + { + "name": "en-PN", + "displayName": "English (Pitcairn Islands)", + "nativeName": "English (Pitcairn Islands)" + }, + { + "name": "en-PR", + "displayName": "English (Puerto Rico)", + "nativeName": "English (Puerto Rico)" + }, + { + "name": "en-PW", + "displayName": "English (Palau)", + "nativeName": "English (Palau)" + }, + { + "name": "en-RW", + "displayName": "English (Rwanda)", + "nativeName": "English (Rwanda)" + }, + { + "name": "en-SB", + "displayName": "English (Solomon Islands)", + "nativeName": "English (Solomon Islands)" + }, + { + "name": "en-SC", + "displayName": "English (Seychelles)", + "nativeName": "English (Seychelles)" + }, + { + "name": "en-SD", + "displayName": "English (Sudan)", + "nativeName": "English (Sudan)" + }, + { + "name": "en-SE", + "displayName": "English (Sweden)", + "nativeName": "English (Sweden)" + }, + { + "name": "en-SG", + "displayName": "English (Singapore)", + "nativeName": "English (Singapore)" + }, + { + "name": "en-SH", + "displayName": "English (St Helena, Ascension, Tristan da Cunha)", + "nativeName": "English (St Helena, Ascension, Tristan da Cunha)" + }, + { + "name": "en-SI", + "displayName": "English (Slovenia)", + "nativeName": "English (Slovenia)" + }, + { + "name": "en-SL", + "displayName": "English (Sierra Leone)", + "nativeName": "English (Sierra Leone)" + }, + { + "name": "en-SS", + "displayName": "English (South Sudan)", + "nativeName": "English (South Sudan)" + }, + { + "name": "en-SX", + "displayName": "English (Sint Maarten)", + "nativeName": "English (Sint Maarten)" + }, + { + "name": "en-SZ", + "displayName": "English (Swaziland)", + "nativeName": "English (Swaziland)" + }, + { + "name": "en-TC", + "displayName": "English (Turks and Caicos Islands)", + "nativeName": "English (Turks and Caicos Islands)" + }, + { + "name": "en-TK", + "displayName": "English (Tokelau)", + "nativeName": "English (Tokelau)" + }, + { + "name": "en-TO", + "displayName": "English (Tonga)", + "nativeName": "English (Tonga)" + }, + { + "name": "en-TT", + "displayName": "English (Trinidad and Tobago)", + "nativeName": "English (Trinidad and Tobago)" + }, + { + "name": "en-TV", + "displayName": "English (Tuvalu)", + "nativeName": "English (Tuvalu)" + }, + { + "name": "en-TZ", + "displayName": "English (Tanzania)", + "nativeName": "English (Tanzania)" + }, + { + "name": "en-UG", + "displayName": "English (Uganda)", + "nativeName": "English (Uganda)" + }, + { + "name": "en-UM", + "displayName": "English (U.S. Outlying Islands)", + "nativeName": "English (U.S. Outlying Islands)" + }, + { + "name": "en-US", + "displayName": "English (United States)", + "nativeName": "English (United States)" + }, + { + "name": "en-VC", + "displayName": "English (Saint Vincent and the Grenadines)", + "nativeName": "English (Saint Vincent and the Grenadines)" + }, + { + "name": "en-VG", + "displayName": "English (British Virgin Islands)", + "nativeName": "English (British Virgin Islands)" + }, + { + "name": "en-VI", + "displayName": "English (U.S. Virgin Islands)", + "nativeName": "English (U.S. Virgin Islands)" + }, + { + "name": "en-VU", + "displayName": "English (Vanuatu)", + "nativeName": "English (Vanuatu)" + }, + { + "name": "en-WS", + "displayName": "English (Samoa)", + "nativeName": "English (Samoa)" + }, + { + "name": "en-ZA", + "displayName": "English (South Africa)", + "nativeName": "English (South Africa)" + }, + { + "name": "en-ZM", + "displayName": "English (Zambia)", + "nativeName": "English (Zambia)" + }, + { + "name": "en-ZW", + "displayName": "English (Zimbabwe)", + "nativeName": "English (Zimbabwe)" + }, + { + "name": "eo-001", + "displayName": "esperanto (World)", + "nativeName": "esperanto (World)" + }, + { + "name": "es-419", + "displayName": "Spanish (Latin America)", + "nativeName": "español (Latinoamérica)" + }, + { + "name": "es-AR", + "displayName": "Spanish (Argentina)", + "nativeName": "español (Argentina)" + }, + { + "name": "es-BO", + "displayName": "Spanish (Bolivia)", + "nativeName": "español (Bolivia)" + }, + { + "name": "es-BR", + "displayName": "español (Brasil)", + "nativeName": "español (Brasil)" + }, + { + "name": "es-BZ", + "displayName": "español (Belice)", + "nativeName": "español (Belice)" + }, + { + "name": "es-CL", + "displayName": "Spanish (Chile)", + "nativeName": "español (Chile)" + }, + { + "name": "es-CO", + "displayName": "Spanish (Colombia)", + "nativeName": "español (Colombia)" + }, + { + "name": "es-CR", + "displayName": "Spanish (Costa Rica)", + "nativeName": "español (Costa Rica)" + }, + { + "name": "es-CU", + "displayName": "Spanish (Cuba)", + "nativeName": "español (Cuba)" + }, + { + "name": "es-DO", + "displayName": "Spanish (Dominican Republic)", + "nativeName": "español (República Dominicana)" + }, + { + "name": "es-EC", + "displayName": "Spanish (Ecuador)", + "nativeName": "español (Ecuador)" + }, + { + "name": "es-ES", + "displayName": "Spanish (Spain, International Sort)", + "nativeName": "español (España, alfabetización internacional)" + }, + { + "name": "es-GQ", + "displayName": "español (Guinea Ecuatorial)", + "nativeName": "español (Guinea Ecuatorial)" + }, + { + "name": "es-GT", + "displayName": "Spanish (Guatemala)", + "nativeName": "español (Guatemala)" + }, + { + "name": "es-HN", + "displayName": "Spanish (Honduras)", + "nativeName": "español (Honduras)" + }, + { + "name": "es-MX", + "displayName": "Spanish (Mexico)", + "nativeName": "español (México)" + }, + { + "name": "es-NI", + "displayName": "Spanish (Nicaragua)", + "nativeName": "español (Nicaragua)" + }, + { + "name": "es-PA", + "displayName": "Spanish (Panama)", + "nativeName": "español (Panamá)" + }, + { + "name": "es-PE", + "displayName": "Spanish (Peru)", + "nativeName": "español (Perú)" + }, + { + "name": "es-PH", + "displayName": "español (Filipinas)", + "nativeName": "español (Filipinas)" + }, + { + "name": "es-PR", + "displayName": "Spanish (Puerto Rico)", + "nativeName": "español (Puerto Rico)" + }, + { + "name": "es-PY", + "displayName": "Spanish (Paraguay)", + "nativeName": "español (Paraguay)" + }, + { + "name": "es-SV", + "displayName": "Spanish (El Salvador)", + "nativeName": "español (El Salvador)" + }, + { + "name": "es-US", + "displayName": "Spanish (United States)", + "nativeName": "español (Estados Unidos)" + }, + { + "name": "es-UY", + "displayName": "Spanish (Uruguay)", + "nativeName": "español (Uruguay)" + }, + { + "name": "es-VE", + "displayName": "Spanish (Venezuela)", + "nativeName": "español (Venezuela)" + }, + { + "name": "et-EE", + "displayName": "Estonian (Estonia)", + "nativeName": "eesti (Eesti)" + }, + { + "name": "eu-ES", + "displayName": "Basque (Basque)", + "nativeName": "euskara (euskara)" + }, + { + "name": "ewo-CM", + "displayName": "ewondo (Kamərún)", + "nativeName": "ewondo (Kamərún)" + }, + { + "name": "fa-IR", + "displayName": "Persian (Iran)", + "nativeName": "فارسى (ایران)" + }, + { + "name": "ff-CM", + "displayName": "Pulaar (Kameruun)", + "nativeName": "Pulaar (Kameruun)" + }, + { + "name": "ff-GN", + "displayName": "Pulaar (Gine)", + "nativeName": "Pulaar (Gine)" + }, + { + "name": "ff-Latn-SN", + "displayName": "Fulah (Latin, Senegal)", + "nativeName": "Fulah (Sénégal)" + }, + { + "name": "ff-MR", + "displayName": "Pulaar (Muritani)", + "nativeName": "Pulaar (Muritani)" + }, + { + "name": "ff-NG", + "displayName": "Fulah (Nigeria)", + "nativeName": "Pulaar (Nigeria)" + }, + { + "name": "fi-FI", + "displayName": "Finnish (Finland)", + "nativeName": "suomi (Suomi)" + }, + { + "name": "fil-PH", + "displayName": "Filipino (Philippines)", + "nativeName": "Filipino (Pilipinas)" + }, + { + "name": "fo-DK", + "displayName": "føroyskt (Danmark)", + "nativeName": "føroyskt (Danmark)" + }, + { + "name": "fo-FO", + "displayName": "Faroese (Faroe Islands)", + "nativeName": "føroyskt (Føroyar)" + }, + { + "name": "fr-029", + "displayName": "French (Caribbean)", + "nativeName": "français (caraïbes)" + }, + { + "name": "fr-BE", + "displayName": "French (Belgium)", + "nativeName": "français (Belgique)" + }, + { + "name": "fr-BF", + "displayName": "français (Burkina Faso)", + "nativeName": "français (Burkina Faso)" + }, + { + "name": "fr-BI", + "displayName": "français (Burundi)", + "nativeName": "français (Burundi)" + }, + { + "name": "fr-BJ", + "displayName": "français (Bénin)", + "nativeName": "français (Bénin)" + }, + { + "name": "fr-BL", + "displayName": "français (Saint-Barthélemy)", + "nativeName": "français (Saint-Barthélemy)" + }, + { + "name": "fr-CA", + "displayName": "French (Canada)", + "nativeName": "français (Canada)" + }, + { + "name": "fr-CD", + "displayName": "French Congo (DRC)", + "nativeName": "français (Congo, République démocratique du)" + }, + { + "name": "fr-CF", + "displayName": "français (République centrafricaine)", + "nativeName": "français (République centrafricaine)" + }, + { + "name": "fr-CG", + "displayName": "français (Congo)", + "nativeName": "français (Congo)" + }, + { + "name": "fr-CH", + "displayName": "French (Switzerland)", + "nativeName": "français (Suisse)" + }, + { + "name": "fr-CI", + "displayName": "French (Côte d’Ivoire)", + "nativeName": "français (Côte d’Ivoire)" + }, + { + "name": "fr-CM", + "displayName": "French (Cameroon)", + "nativeName": "français (Cameroun)" + }, + { + "name": "fr-DJ", + "displayName": "français (Djibouti)", + "nativeName": "français (Djibouti)" + }, + { + "name": "fr-DZ", + "displayName": "français (Algérie)", + "nativeName": "français (Algérie)" + }, + { + "name": "fr-FR", + "displayName": "French (France)", + "nativeName": "français (France)" + }, + { + "name": "fr-GA", + "displayName": "français (Gabon)", + "nativeName": "français (Gabon)" + }, + { + "name": "fr-GF", + "displayName": "français (Guyane française)", + "nativeName": "français (Guyane française)" + }, + { + "name": "fr-GN", + "displayName": "français (Guinée)", + "nativeName": "français (Guinée)" + }, + { + "name": "fr-GP", + "displayName": "français (Guadeloupe)", + "nativeName": "français (Guadeloupe)" + }, + { + "name": "fr-GQ", + "displayName": "français (Guinée équatoriale)", + "nativeName": "français (Guinée équatoriale)" + }, + { + "name": "fr-HT", + "displayName": "French (Haiti)", + "nativeName": "français (Haïti)" + }, + { + "name": "fr-KM", + "displayName": "français (Comores)", + "nativeName": "français (Comores)" + }, + { + "name": "fr-LU", + "displayName": "French (Luxembourg)", + "nativeName": "français (Luxembourg)" + }, + { + "name": "fr-MA", + "displayName": "French (Morocco)", + "nativeName": "français (Maroc)" + }, + { + "name": "fr-MC", + "displayName": "French (Monaco)", + "nativeName": "français (Monaco)" + }, + { + "name": "fr-MF", + "displayName": "français (Saint-Martin)", + "nativeName": "français (Saint-Martin)" + }, + { + "name": "fr-MG", + "displayName": "français (Madagascar)", + "nativeName": "français (Madagascar)" + }, + { + "name": "fr-ML", + "displayName": "French (Mali)", + "nativeName": "français (Mali)" + }, + { + "name": "fr-MQ", + "displayName": "français (Martinique)", + "nativeName": "français (Martinique)" + }, + { + "name": "fr-MR", + "displayName": "français (Mauritanie)", + "nativeName": "français (Mauritanie)" + }, + { + "name": "fr-MU", + "displayName": "français (Maurice)", + "nativeName": "français (Maurice)" + }, + { + "name": "fr-NC", + "displayName": "français (Nouvelle-Calédonie)", + "nativeName": "français (Nouvelle-Calédonie)" + }, + { + "name": "fr-NE", + "displayName": "français (Niger)", + "nativeName": "français (Niger)" + }, + { + "name": "fr-PF", + "displayName": "français (Polynésie française)", + "nativeName": "français (Polynésie française)" + }, + { + "name": "fr-PM", + "displayName": "français (Saint-Pierre-et-Miquelon)", + "nativeName": "français (Saint-Pierre-et-Miquelon)" + }, + { + "name": "fr-RE", + "displayName": "French (Réunion)", + "nativeName": "français (La Réunion)" + }, + { + "name": "fr-RW", + "displayName": "français (Rwanda)", + "nativeName": "français (Rwanda)" + }, + { + "name": "fr-SC", + "displayName": "français (Seychelles)", + "nativeName": "français (Seychelles)" + }, + { + "name": "fr-SN", + "displayName": "French (Senegal)", + "nativeName": "français (Sénégal)" + }, + { + "name": "fr-SY", + "displayName": "français (Syrie)", + "nativeName": "français (Syrie)" + }, + { + "name": "fr-TD", + "displayName": "français (Tchad)", + "nativeName": "français (Tchad)" + }, + { + "name": "fr-TG", + "displayName": "français (Togo)", + "nativeName": "français (Togo)" + }, + { + "name": "fr-TN", + "displayName": "français (Tunisie)", + "nativeName": "français (Tunisie)" + }, + { + "name": "fr-VU", + "displayName": "français (Vanuatu)", + "nativeName": "français (Vanuatu)" + }, + { + "name": "fr-WF", + "displayName": "français (Wallis-et-Futuna)", + "nativeName": "français (Wallis-et-Futuna)" + }, + { + "name": "fr-YT", + "displayName": "français (Mayotte)", + "nativeName": "français (Mayotte)" + }, + { + "name": "fur-IT", + "displayName": "furlan (Italie)", + "nativeName": "furlan (Italie)" + }, + { + "name": "fy-NL", + "displayName": "Western Frisian (Netherlands)", + "nativeName": "Frysk (Nederlân)" + }, + { + "name": "ga-IE", + "displayName": "Irish (Ireland)", + "nativeName": "Gaeilge (Éire)" + }, + { + "name": "gd-GB", + "displayName": "Scottish Gaelic (United Kingdom)", + "nativeName": "Gàidhlig (An Rìoghachd Aonaichte)" + }, + { + "name": "gl-ES", + "displayName": "Galician (Galician)", + "nativeName": "galego (galego)" + }, + { + "name": "gn-PY", + "displayName": "Guarani (Paraguay)", + "nativeName": "Avañe’ẽ (Paraguái)" + }, + { + "name": "gsw-CH", + "displayName": "Schwiizertüütsch (Schwiiz)", + "nativeName": "Schwiizertüütsch (Schwiiz)" + }, + { + "name": "gsw-FR", + "displayName": "Alsatian (France)", + "nativeName": "Elsässisch (Frànkrisch)" + }, + { + "name": "gsw-LI", + "displayName": "Schwiizertüütsch (Liächteschtäi)", + "nativeName": "Schwiizertüütsch (Liächteschtäi)" + }, + { + "name": "gu-IN", + "displayName": "Gujarati (India)", + "nativeName": "ગુજરાતી (ભારત)" + }, + { + "name": "guz-KE", + "displayName": "Ekegusii (Kenya)", + "nativeName": "Ekegusii (Kenya)" + }, + { + "name": "gv-IM", + "displayName": "Gaelg (Ellan Vannin)", + "nativeName": "Gaelg (Ellan Vannin)" + }, + { + "name": "ha-Latn-GH", + "displayName": "Hausa (Gana)", + "nativeName": "Hausa (Gana)" + }, + { + "name": "ha-Latn-NE", + "displayName": "Hausa (Nijar)", + "nativeName": "Hausa (Nijar)" + }, + { + "name": "ha-Latn-NG", + "displayName": "Hausa (Latin, Nigeria)", + "nativeName": "Hausa (Najeriya)" + }, + { + "name": "haw-US", + "displayName": "Hawaiian (United States)", + "nativeName": "ʻŌlelo Hawaiʻi (ʻAmelika Hui Pū ʻIa)" + }, + { + "name": "he-IL", + "displayName": "Hebrew (Israel)", + "nativeName": "עברית (ישראל)" + }, + { + "name": "hi-IN", + "displayName": "Hindi (India)", + "nativeName": "हिंदी (भारत)" + }, + { + "name": "hr-BA", + "displayName": "Croatian (Bosnia and Herzegovina)", + "nativeName": "hrvatski (Bosna i Hercegovina)" + }, + { + "name": "hr-HR", + "displayName": "Croatian (Croatia)", + "nativeName": "hrvatski (Hrvatska)" + }, + { + "name": "hsb-DE", + "displayName": "Upper Sorbian (Germany)", + "nativeName": "hornjoserbšćina (Němska)" + }, + { + "name": "hu-HU", + "displayName": "Hungarian (Hungary)", + "nativeName": "magyar (Magyarország)" + }, + { + "name": "hy-AM", + "displayName": "Armenian (Armenia)", + "nativeName": "Հայերեն (Հայաստան)" + }, + { + "name": "ia-001", + "displayName": "interlingua (World)", + "nativeName": "interlingua (World)" + }, + { + "name": "ia-FR", + "displayName": "interlingua (Francia)", + "nativeName": "interlingua (Francia)" + }, + { + "name": "ibb-NG", + "displayName": "Ibibio (Nigeria)", + "nativeName": "Ibibio-Efik (Nigeria)" + }, + { + "name": "id-ID", + "displayName": "Indonesian (Indonesia)", + "nativeName": "Indonesia (Indonesia)" + }, + { + "name": "ig-NG", + "displayName": "Igbo (Nigeria)", + "nativeName": "Igbo (Nigeria)" + }, + { + "name": "ii-CN", + "displayName": "Yi (China)", + "nativeName": "ꆈꌠꁱꂷ (ꍏꉸꏓꂱꇭꉼꇩ)" + }, + { + "name": "is-IS", + "displayName": "Icelandic (Iceland)", + "nativeName": "íslenska (Ísland)" + }, + { + "name": "it-CH", + "displayName": "Italian (Switzerland)", + "nativeName": "italiano (Svizzera)" + }, + { + "name": "it-IT", + "displayName": "Italian (Italy)", + "nativeName": "italiano (Italia)" + }, + { + "name": "it-SM", + "displayName": "italiano (San Marino)", + "nativeName": "italiano (San Marino)" + }, + { + "name": "it-VA", + "displayName": "italiano (Città del Vaticano)", + "nativeName": "italiano (Città del Vaticano)" + }, + { + "name": "iu-Cans-CA", + "displayName": "Inuktitut (Syllabics, Canada)", + "nativeName": "ᐃᓄᒃᑎᑐᑦ (ᑲᓇᑕᒥ)" + }, + { + "name": "iu-Latn-CA", + "displayName": "Inuktitut (Latin, Canada)", + "nativeName": "Inuktitut (Kanatami)" + }, + { + "name": "ja-JP", + "displayName": "Japanese (Japan)", + "nativeName": "日本語 (日本)" + }, + { + "name": "jgo-CM", + "displayName": "Ndaꞌa (Kamɛlûn)", + "nativeName": "Ndaꞌa (Kamɛlûn)" + }, + { + "name": "jmc-TZ", + "displayName": "Kimachame (Tanzania)", + "nativeName": "Kimachame (Tanzania)" + }, + { + "name": "jv-Java-ID", + "displayName": "ꦧꦱꦗꦮ (Indonesia)", + "nativeName": "ꦧꦱꦗꦮ (Indonesia)" + }, + { + "name": "jv-Latn-ID", + "displayName": "Basa Jawa (Indonesia)", + "nativeName": "Basa Jawa (Indonesia)" + }, + { + "name": "ka-GE", + "displayName": "Georgian (Georgia)", + "nativeName": "ქართული (საქართველო)" + }, + { + "name": "kab-DZ", + "displayName": "Taqbaylit (Lezzayer)", + "nativeName": "Taqbaylit (Lezzayer)" + }, + { + "name": "kam-KE", + "displayName": "Kikamba (Kenya)", + "nativeName": "Kikamba (Kenya)" + }, + { + "name": "kde-TZ", + "displayName": "Chimakonde (Tanzania)", + "nativeName": "Chimakonde (Tanzania)" + }, + { + "name": "kea-CV", + "displayName": "kabuverdianu (Kabu Verdi)", + "nativeName": "kabuverdianu (Kabu Verdi)" + }, + { + "name": "khq-ML", + "displayName": "Koyra ciini (Maali)", + "nativeName": "Koyra ciini (Maali)" + }, + { + "name": "ki-KE", + "displayName": "Gikuyu (Kenya)", + "nativeName": "Gikuyu (Kenya)" + }, + { + "name": "kk-KZ", + "displayName": "Kazakh (Kazakhstan)", + "nativeName": "қазақ тілі (Қазақстан)" + }, + { + "name": "kkj-CM", + "displayName": "kakɔ (Kamɛrun)", + "nativeName": "kakɔ (Kamɛrun)" + }, + { + "name": "kl-GL", + "displayName": "Greenlandic (Greenland)", + "nativeName": "kalaallisut (Kalaallit Nunaat)" + }, + { + "name": "kln-KE", + "displayName": "Kalenjin (Emetab Kenya)", + "nativeName": "Kalenjin (Emetab Kenya)" + }, + { + "name": "km-KH", + "displayName": "Khmer (Cambodia)", + "nativeName": "ភាសាខ្មែរ (កម្ពុជា)" + }, + { + "name": "kn-IN", + "displayName": "Kannada (India)", + "nativeName": "ಕನ್ನಡ (ಭಾರತ)" + }, + { + "name": "ko-KP", + "displayName": "한국어 (조선민주주의인민공화국)", + "nativeName": "한국어 (조선민주주의인민공화국)" + }, + { + "name": "ko-KR", + "displayName": "Korean (Korea)", + "nativeName": "한국어(대한민국)" + }, + { + "name": "kok-IN", + "displayName": "Konkani (India)", + "nativeName": "कोंकणी (भारत)" + }, + { + "name": "kr-NG", + "displayName": "Kanuri (Nigeria)", + "nativeName": "Kanuri (Nigeria)" + }, + { + "name": "ks-Arab-IN", + "displayName": "کٲشُر (اَربی)", + "nativeName": "کٲشُر (اَربی)" + }, + { + "name": "ks-Deva-IN", + "displayName": "Kashmiri (Devanagari)", + "nativeName": "कॉशुर" + }, + { + "name": "ksb-TZ", + "displayName": "Kishambaa (Tanzania)", + "nativeName": "Kishambaa (Tanzania)" + }, + { + "name": "ksf-CM", + "displayName": "rikpa (kamɛrún)", + "nativeName": "rikpa (kamɛrún)" + }, + { + "name": "ksh-DE", + "displayName": "Kölsch (Doütschland)", + "nativeName": "Kölsch (Doütschland)" + }, + { + "name": "ku-Arab-IQ", + "displayName": "Central Kurdish (Iraq)", + "nativeName": "کوردیی ناوەڕاست (عێراق)" + }, + { + "name": "ku-Arab-IR", + "displayName": "کوردی (ئێران)", + "nativeName": "کوردی (ئێران)" + }, + { + "name": "kw-GB", + "displayName": "kernewek (Rywvaneth Unys)", + "nativeName": "kernewek (Rywvaneth Unys)" + }, + { + "name": "ky-KG", + "displayName": "Kyrgyz (Kyrgyzstan)", + "nativeName": "Кыргыз (Кыргызстан)" + }, + { + "name": "la-001", + "displayName": "Latin (World)", + "nativeName": "lingua latīna (World)" + }, + { + "name": "lag-TZ", + "displayName": "Kɨlaangi (Taansanía)", + "nativeName": "Kɨlaangi (Taansanía)" + }, + { + "name": "lb-LU", + "displayName": "Luxembourgish (Luxembourg)", + "nativeName": "Lëtzebuergesch (Lëtzebuerg)" + }, + { + "name": "lg-UG", + "displayName": "Luganda (Yuganda)", + "nativeName": "Luganda (Yuganda)" + }, + { + "name": "lkt-US", + "displayName": "Lakȟólʼiyapi (Mílahaŋska Tȟamákȟočhe)", + "nativeName": "Lakȟólʼiyapi (Mílahaŋska Tȟamákȟočhe)" + }, + { + "name": "ln-AO", + "displayName": "lingála (Angóla)", + "nativeName": "lingála (Angóla)" + }, + { + "name": "ln-CD", + "displayName": "lingála (Republíki ya Kongó Demokratíki)", + "nativeName": "lingála (Republíki ya Kongó Demokratíki)" + }, + { + "name": "ln-CF", + "displayName": "lingála (Repibiki ya Afríka ya Káti)", + "nativeName": "lingála (Repibiki ya Afríka ya Káti)" + }, + { + "name": "ln-CG", + "displayName": "lingála (Kongo)", + "nativeName": "lingála (Kongo)" + }, + { + "name": "lo-LA", + "displayName": "Lao (Laos)", + "nativeName": "ລາວ (ລາວ)" + }, + { + "name": "lrc-IQ", + "displayName": "لۊری شومالی (Iraq)", + "nativeName": "لۊری شومالی (Iraq)" + }, + { + "name": "lrc-IR", + "displayName": "لۊری شومالی (Iran)", + "nativeName": "لۊری شومالی (Iran)" + }, + { + "name": "lt-LT", + "displayName": "Lithuanian (Lithuania)", + "nativeName": "lietuvių (Lietuva)" + }, + { + "name": "lu-CD", + "displayName": "Tshiluba (Ditunga wa Kongu)", + "nativeName": "Tshiluba (Ditunga wa Kongu)" + }, + { + "name": "luo-KE", + "displayName": "Dholuo (Kenya)", + "nativeName": "Dholuo (Kenya)" + }, + { + "name": "luy-KE", + "displayName": "Luluhia (Kenya)", + "nativeName": "Luluhia (Kenya)" + }, + { + "name": "lv-LV", + "displayName": "Latvian (Latvia)", + "nativeName": "latviešu (Latvija)" + }, + { + "name": "mas-KE", + "displayName": "Maa (Kenya)", + "nativeName": "Maa (Kenya)" + }, + { + "name": "mas-TZ", + "displayName": "Maa (Tansania)", + "nativeName": "Maa (Tansania)" + }, + { + "name": "mer-KE", + "displayName": "Kĩmĩrũ (Kenya)", + "nativeName": "Kĩmĩrũ (Kenya)" + }, + { + "name": "mfe-MU", + "displayName": "kreol morisien (Moris)", + "nativeName": "kreol morisien (Moris)" + }, + { + "name": "mg-MG", + "displayName": "Malagasy (Madagasikara)", + "nativeName": "Malagasy (Madagasikara)" + }, + { + "name": "mgh-MZ", + "displayName": "Makua (Umozambiki)", + "nativeName": "Makua (Umozambiki)" + }, + { + "name": "mgo-CM", + "displayName": "metaʼ (Kamalun)", + "nativeName": "metaʼ (Kamalun)" + }, + { + "name": "mi-NZ", + "displayName": "Maori (New Zealand)", + "nativeName": "Reo Māori (Aotearoa)" + }, + { + "name": "mk-MK", + "displayName": "Macedonian (Macedonia, FYRO)", + "nativeName": "македонски (Република Македонија)" + }, + { + "name": "ml-IN", + "displayName": "Malayalam (India)", + "nativeName": "മലയാളം (ഇന്ത്യ)" + }, + { + "name": "mn-MN", + "displayName": "Mongolian (Mongolia)", + "nativeName": "монгол (Монгол)" + }, + { + "name": "mn-Mong-CN", + "displayName": "Mongolian (Traditional Mongolian, China)", + "nativeName": "ᠮᠣᠩᠭᠣᠤᠯ ᠬᠡᠯᠡ (ᠪᠦᠭᠦᠳᠡ ᠨᠠᠢᠷᠠᠮᠳᠠᠬᠤ ᠳᠤᠮᠳᠠᠳᠤ ᠠᠷᠠᠳ ᠣᠯᠣᠰ)" + }, + { + "name": "mn-Mong-MN", + "displayName": "Mongolian (Traditional Mongolian, Mongolia)", + "nativeName": "ᠮᠣᠩᠭᠣᠯ ᠬᠡᠯᠡ (ᠮᠣᠩᠭᠣᠯ ᠣᠯᠣᠰ)" + }, + { + "name": "mni-IN", + "displayName": "Manipuri (India)", + "nativeName": "মৈতৈলোন্ (India)" + }, + { + "name": "moh-CA", + "displayName": "Mohawk (Mohawk)", + "nativeName": "Kanien'kéha" + }, + { + "name": "mr-IN", + "displayName": "Marathi (India)", + "nativeName": "मराठी (भारत)" + }, + { + "name": "ms-BN", + "displayName": "Malay (Brunei)", + "nativeName": "Bahasa Melayu (Brunei)" + }, + { + "name": "ms-MY", + "displayName": "Malay (Malaysia)", + "nativeName": "Bahasa Melayu (Malaysia)" + }, + { + "name": "ms-SG", + "displayName": "Bahasa Melayu (Singapura)", + "nativeName": "Bahasa Melayu (Singapura)" + }, + { + "name": "mt-MT", + "displayName": "Maltese (Malta)", + "nativeName": "Malti (Malta)" + }, + { + "name": "mua-CM", + "displayName": "MUNDAŊ (kameruŋ)", + "nativeName": "MUNDAŊ (kameruŋ)" + }, + { + "name": "my-MM", + "displayName": "Burmese (Myanmar)", + "nativeName": "မြန်မာ (မြန်မာ)" + }, + { + "name": "mzn-IR", + "displayName": "مازرونی (ایران)", + "nativeName": "مازرونی (ایران)" + }, + { + "name": "naq-NA", + "displayName": "Khoekhoegowab (Namibiab)", + "nativeName": "Khoekhoegowab (Namibiab)" + }, + { + "name": "nb-NO", + "displayName": "Norwegian Bokmål (Norway)", + "nativeName": "norsk bokmål (Norge)" + }, + { + "name": "nb-SJ", + "displayName": "norsk bokmål (Svalbard og Jan Mayen)", + "nativeName": "norsk bokmål (Svalbard og Jan Mayen)" + }, + { + "name": "nd-ZW", + "displayName": "isiNdebele (Zimbabwe)", + "nativeName": "isiNdebele (Zimbabwe)" + }, + { + "name": "nds-DE", + "displayName": "Neddersass’sch (Düütschland)", + "nativeName": "Neddersass’sch (Düütschland)" + }, + { + "name": "nds-NL", + "displayName": "Neddersass’sch (Nedderlannen)", + "nativeName": "Neddersass’sch (Nedderlannen)" + }, + { + "name": "ne-IN", + "displayName": "Nepali (India)", + "nativeName": "नेपाली (भारत)" + }, + { + "name": "ne-NP", + "displayName": "Nepali (Nepal)", + "nativeName": "नेपाली (नेपाल)" + }, + { + "name": "nl-AW", + "displayName": "Nederlands (Aruba)", + "nativeName": "Nederlands (Aruba)" + }, + { + "name": "nl-BE", + "displayName": "Dutch (Belgium)", + "nativeName": "Nederlands (België)" + }, + { + "name": "nl-BQ", + "displayName": "Nederlands (Bonaire, Sint Eustatius en Saba)", + "nativeName": "Nederlands (Bonaire, Sint Eustatius en Saba)" + }, + { + "name": "nl-CW", + "displayName": "Nederlands (Curaçao)", + "nativeName": "Nederlands (Curaçao)" + }, + { + "name": "nl-NL", + "displayName": "Dutch (Netherlands)", + "nativeName": "Nederlands (Nederland)" + }, + { + "name": "nl-SR", + "displayName": "Nederlands (Suriname)", + "nativeName": "Nederlands (Suriname)" + }, + { + "name": "nl-SX", + "displayName": "Nederlands (Sint-Maarten)", + "nativeName": "Nederlands (Sint-Maarten)" + }, + { + "name": "nmg-CM", + "displayName": "Kwasio (Kamerun)", + "nativeName": "Kwasio (Kamerun)" + }, + { + "name": "nn-NO", + "displayName": "Norwegian Nynorsk (Norway)", + "nativeName": "nynorsk (Noreg)" + }, + { + "name": "nnh-CM", + "displayName": "Shwóŋò ngiembɔɔn (Kàmalûm)", + "nativeName": "Shwóŋò ngiembɔɔn (Kàmalûm)" + }, + { + "name": "nqo-GN", + "displayName": "ߒߞߏ (ߖߌ߬ߣߍ߬ ߞߊ߲ߓߍ߲)", + "nativeName": "ߒߞߏ (ߖߌ߬ߣߍ߬ ߞߊ߲ߓߍ߲)" + }, + { + "name": "nr-ZA", + "displayName": "isiNdebele (South Africa)", + "nativeName": "isiNdebele (South Africa)" + }, + { + "name": "nso-ZA", + "displayName": "Sesotho sa Leboa (South Africa)", + "nativeName": "Sesotho sa Leboa (Afrika Borwa)" + }, + { + "name": "nus-SS", + "displayName": "Thok Nath (South Sudan)", + "nativeName": "Thok Nath (South Sudan)" + }, + { + "name": "nyn-UG", + "displayName": "Runyankore (Uganda)", + "nativeName": "Runyankore (Uganda)" + }, + { + "name": "oc-FR", + "displayName": "Occitan (France)", + "nativeName": "Occitan (França)" + }, + { + "name": "om-ET", + "displayName": "Oromo (Ethiopia)", + "nativeName": "Oromoo (Itoophiyaa)" + }, + { + "name": "om-KE", + "displayName": "Oromoo (Keeniyaa)", + "nativeName": "Oromoo (Keeniyaa)" + }, + { + "name": "or-IN", + "displayName": "Odia (India)", + "nativeName": "ଓଡ଼ିଆ (ଭାରତ)" + }, + { + "name": "os-GE", + "displayName": "ирон (Гуырдзыстон)", + "nativeName": "ирон (Гуырдзыстон)" + }, + { + "name": "os-RU", + "displayName": "ирон (Уӕрӕсе)", + "nativeName": "ирон (Уӕрӕсе)" + }, + { + "name": "pa-Arab-PK", + "displayName": "Punjabi (Pakistan)", + "nativeName": "پنجابی (پاکستان)" + }, + { + "name": "pa-IN", + "displayName": "Punjabi (India)", + "nativeName": "ਪੰਜਾਬੀ (ਭਾਰਤ)" + }, + { + "name": "pap-029", + "displayName": "Papiamento (Caribbean)", + "nativeName": "Papiamentu (Caribbean)" + }, + { + "name": "pl-PL", + "displayName": "Polish (Poland)", + "nativeName": "polski (Polska)" + }, + { + "name": "prg-001", + "displayName": "prūsiskan (swītai)", + "nativeName": "prūsiskan (swītai)" + }, + { + "name": "prs-AF", + "displayName": "Dari (Afghanistan)", + "nativeName": "درى (افغانستان)" + }, + { + "name": "ps-AF", + "displayName": "Pashto (Afghanistan)", + "nativeName": "پښتو (افغانستان)" + }, + { + "name": "pt-AO", + "displayName": "português (Angola)", + "nativeName": "português (Angola)" + }, + { + "name": "pt-BR", + "displayName": "Portuguese (Brazil)", + "nativeName": "português (Brasil)" + }, + { + "name": "pt-CH", + "displayName": "português (Suíça)", + "nativeName": "português (Suíça)" + }, + { + "name": "pt-CV", + "displayName": "português (Cabo Verde)", + "nativeName": "português (Cabo Verde)" + }, + { + "name": "pt-GQ", + "displayName": "português (Guiné Equatorial)", + "nativeName": "português (Guiné Equatorial)" + }, + { + "name": "pt-GW", + "displayName": "português (Guiné-Bissau)", + "nativeName": "português (Guiné-Bissau)" + }, + { + "name": "pt-LU", + "displayName": "português (Luxemburgo)", + "nativeName": "português (Luxemburgo)" + }, + { + "name": "pt-MO", + "displayName": "português (RAE de Macau)", + "nativeName": "português (RAE de Macau)" + }, + { + "name": "pt-MZ", + "displayName": "português (Moçambique)", + "nativeName": "português (Moçambique)" + }, + { + "name": "pt-PT", + "displayName": "Portuguese (Portugal)", + "nativeName": "português (Portugal)" + }, + { + "name": "pt-ST", + "displayName": "português (São Tomé e Príncipe)", + "nativeName": "português (São Tomé e Príncipe)" + }, + { + "name": "pt-TL", + "displayName": "português (Timor-Leste)", + "nativeName": "português (Timor-Leste)" + }, + { + "name": "quc-Latn-GT", + "displayName": "K'iche' (Guatemala)", + "nativeName": "K'iche' (Guatemala)" + }, + { + "name": "quz-BO", + "displayName": "Quechua (Bolivia)", + "nativeName": "Runasimi (Bolivia)" + }, + { + "name": "quz-EC", + "displayName": "Quichua (Ecuador)", + "nativeName": "Runasimi (Ecuador)" + }, + { + "name": "quz-PE", + "displayName": "Quechua (Peru)", + "nativeName": "Runasimi (Perú)" + }, + { + "name": "rm-CH", + "displayName": "Romansh (Switzerland)", + "nativeName": "rumantsch (Svizra)" + }, + { + "name": "rn-BI", + "displayName": "Ikirundi (Uburundi)", + "nativeName": "Ikirundi (Uburundi)" + }, + { + "name": "ro-MD", + "displayName": "Romanian (Moldova)", + "nativeName": "română (Republica Moldova)" + }, + { + "name": "ro-RO", + "displayName": "Romanian (Romania)", + "nativeName": "română (România)" + }, + { + "name": "rof-TZ", + "displayName": "Kihorombo (Tanzania)", + "nativeName": "Kihorombo (Tanzania)" + }, + { + "name": "ru-BY", + "displayName": "русский (Беларусь)", + "nativeName": "русский (Беларусь)" + }, + { + "name": "ru-KG", + "displayName": "русский (Киргизия)", + "nativeName": "русский (Киргизия)" + }, + { + "name": "ru-KZ", + "displayName": "русский (Казахстан)", + "nativeName": "русский (Казахстан)" + }, + { + "name": "ru-MD", + "displayName": "Russian (Moldova)", + "nativeName": "русский (Молдова)" + }, + { + "name": "ru-RU", + "displayName": "Russian (Russia)", + "nativeName": "русский (Россия)" + }, + { + "name": "ru-UA", + "displayName": "русский (Украина)", + "nativeName": "русский (Украина)" + }, + { + "name": "rw-RW", + "displayName": "Kinyarwanda (Rwanda)", + "nativeName": "Kinyarwanda (Rwanda)" + }, + { + "name": "rwk-TZ", + "displayName": "Kiruwa (Tanzania)", + "nativeName": "Kiruwa (Tanzania)" + }, + { + "name": "sa-IN", + "displayName": "Sanskrit (India)", + "nativeName": "संस्कृत (भारतम्)" + }, + { + "name": "sah-RU", + "displayName": "Sakha (Russia)", + "nativeName": "Саха (Россия)" + }, + { + "name": "saq-KE", + "displayName": "Kisampur (Kenya)", + "nativeName": "Kisampur (Kenya)" + }, + { + "name": "sbp-TZ", + "displayName": "Ishisangu (Tansaniya)", + "nativeName": "Ishisangu (Tansaniya)" + }, + { + "name": "sd-Arab-PK", + "displayName": "Sindhi (Pakistan)", + "nativeName": "سنڌي (پاکستان)" + }, + { + "name": "sd-Deva-IN", + "displayName": "Sindhi (Devanagari, India)", + "nativeName": "सिन्धी (India)" + }, + { + "name": "se-FI", + "displayName": "Sami, Northern (Finland)", + "nativeName": "davvisámegiella (Suopma)" + }, + { + "name": "se-NO", + "displayName": "Sami, Northern (Norway)", + "nativeName": "davvisámegiella (Norga)" + }, + { + "name": "se-SE", + "displayName": "Sami, Northern (Sweden)", + "nativeName": "davvisámegiella (Ruoŧŧa)" + }, + { + "name": "seh-MZ", + "displayName": "sena (Moçambique)", + "nativeName": "sena (Moçambique)" + }, + { + "name": "ses-ML", + "displayName": "Koyraboro senni (Maali)", + "nativeName": "Koyraboro senni (Maali)" + }, + { + "name": "sg-CF", + "displayName": "Sängö (Ködörösêse tî Bêafrîka)", + "nativeName": "Sängö (Ködörösêse tî Bêafrîka)" + }, + { + "name": "shi-Latn-MA", + "displayName": "Tashelḥiyt (lmɣrib)", + "nativeName": "Tashelḥiyt (lmɣrib)" + }, + { + "name": "shi-Tfng-MA", + "displayName": "ⵜⴰⵛⵍⵃⵉⵜ (ⵍⵎⵖⵔⵉⴱ)", + "nativeName": "ⵜⴰⵛⵍⵃⵉⵜ (ⵍⵎⵖⵔⵉⴱ)" + }, + { + "name": "si-LK", + "displayName": "Sinhala (Sri Lanka)", + "nativeName": "සිංහල (ශ්‍රී ලංකාව)" + }, + { + "name": "sk-SK", + "displayName": "Slovak (Slovakia)", + "nativeName": "slovenčina (Slovensko)" + }, + { + "name": "sl-SI", + "displayName": "Slovenian (Slovenia)", + "nativeName": "slovenščina (Slovenija)" + }, + { + "name": "sma-NO", + "displayName": "Sami, Southern (Norway)", + "nativeName": "åarjelsaemiengïele (Nöörje)" + }, + { + "name": "sma-SE", + "displayName": "Sami, Southern (Sweden)", + "nativeName": "åarjelsaemiengïele (Sveerje)" + }, + { + "name": "smj-NO", + "displayName": "Sami, Lule (Norway)", + "nativeName": "julevusámegiella (Vuodna)" + }, + { + "name": "smj-SE", + "displayName": "Sami, Lule (Sweden)", + "nativeName": "julevusámegiella (Svierik)" + }, + { + "name": "smn-FI", + "displayName": "Sami, Inari (Finland)", + "nativeName": "anarâškielâ (Suomâ)" + }, + { + "name": "sms-FI", + "displayName": "Sami, Skolt (Finland)", + "nativeName": "sää´mǩiõll (Lää´ddjânnam)" + }, + { + "name": "sn-Latn-ZW", + "displayName": "chiShona (Zimbabwe)", + "nativeName": "chiShona (Zimbabwe)" + }, + { + "name": "so-DJ", + "displayName": "Soomaali (Jabuuti)", + "nativeName": "Soomaali (Jabuuti)" + }, + { + "name": "so-ET", + "displayName": "Soomaali (Itoobiya)", + "nativeName": "Soomaali (Itoobiya)" + }, + { + "name": "so-KE", + "displayName": "Soomaali (Kiiniya)", + "nativeName": "Soomaali (Kiiniya)" + }, + { + "name": "so-SO", + "displayName": "Somali (Somalia)", + "nativeName": "Soomaali (Soomaaliya)" + }, + { + "name": "sq-AL", + "displayName": "Albanian (Albania)", + "nativeName": "shqip (Shqipëri)" + }, + { + "name": "sq-MK", + "displayName": "shqip (Republika e Maqedonisë)", + "nativeName": "shqip (Republika e Maqedonisë)" + }, + { + "name": "sq-XK", + "displayName": "shqip (Kosovë)", + "nativeName": "shqip (Kosovë)" + }, + { + "name": "sr-Cyrl-BA", + "displayName": "Serbian (Cyrillic, Bosnia and Herzegovina)", + "nativeName": "српски (Босна и Херцеговина)" + }, + { + "name": "sr-Cyrl-ME", + "displayName": "Serbian (Cyrillic, Montenegro)", + "nativeName": "српски (Црна Гора)" + }, + { + "name": "sr-Cyrl-RS", + "displayName": "Serbian (Cyrillic, Serbia)", + "nativeName": "српски (Србија)" + }, + { + "name": "sr-Cyrl-XK", + "displayName": "српски (Косово)", + "nativeName": "српски (Косово)" + }, + { + "name": "sr-Latn-BA", + "displayName": "Serbian (Latin, Bosnia and Herzegovina)", + "nativeName": "srpski (Bosna i Hercegovina)" + }, + { + "name": "sr-Latn-ME", + "displayName": "Serbian (Latin, Montenegro)", + "nativeName": "srpski (Crna Gora)" + }, + { + "name": "sr-Latn-RS", + "displayName": "Serbian (Latin, Serbia)", + "nativeName": "srpski (Srbija)" + }, + { + "name": "sr-Latn-XK", + "displayName": "srpski (Kosovo)", + "nativeName": "srpski (Kosovo)" + }, + { + "name": "ss-SZ", + "displayName": "siSwati (Swaziland)", + "nativeName": "siSwati (Swaziland)" + }, + { + "name": "ss-ZA", + "displayName": "siSwati (South Africa)", + "nativeName": "siSwati (South Africa)" + }, + { + "name": "ssy-ER", + "displayName": "Saho (Eretria)", + "nativeName": "Saho (Eretria)" + }, + { + "name": "st-LS", + "displayName": "Sesotho (Lesotho)", + "nativeName": "Sesotho (Lesotho)" + }, + { + "name": "st-ZA", + "displayName": "Sesotho (South Africa)", + "nativeName": "Sesotho (South Africa)" + }, + { + "name": "sv-AX", + "displayName": "svenska (Åland)", + "nativeName": "svenska (Åland)" + }, + { + "name": "sv-FI", + "displayName": "Swedish (Finland)", + "nativeName": "svenska (Finland)" + }, + { + "name": "sv-SE", + "displayName": "Swedish (Sweden)", + "nativeName": "svenska (Sverige)" + }, + { + "name": "sw-CD", + "displayName": "Kiswahili (Jamhuri ya Kidemokrasia ya Kongo)", + "nativeName": "Kiswahili (Jamhuri ya Kidemokrasia ya Kongo)" + }, + { + "name": "sw-KE", + "displayName": "Kiswahili (Kenya)", + "nativeName": "Kiswahili (Kenya)" + }, + { + "name": "sw-TZ", + "displayName": "Kiswahili (Tanzania)", + "nativeName": "Kiswahili (Tanzania)" + }, + { + "name": "sw-UG", + "displayName": "Kiswahili (Uganda)", + "nativeName": "Kiswahili (Uganda)" + }, + { + "name": "syr-SY", + "displayName": "Syriac (Syria)", + "nativeName": "ܣܘܪܝܝܐ (ܣܘܪܝܐ)" + }, + { + "name": "ta-IN", + "displayName": "Tamil (India)", + "nativeName": "தமிழ் (இந்தியா)" + }, + { + "name": "ta-LK", + "displayName": "Tamil (Sri Lanka)", + "nativeName": "தமிழ் (இலங்கை)" + }, + { + "name": "ta-MY", + "displayName": "தமிழ் (மலேசியா)", + "nativeName": "தமிழ் (மலேசியா)" + }, + { + "name": "ta-SG", + "displayName": "தமிழ் (சிங்கப்பூர்)", + "nativeName": "தமிழ் (சிங்கப்பூர்)" + }, + { + "name": "te-IN", + "displayName": "Telugu (India)", + "nativeName": "తెలుగు (భారత దేశం)" + }, + { + "name": "teo-KE", + "displayName": "Kiteso (Kenia)", + "nativeName": "Kiteso (Kenia)" + }, + { + "name": "teo-UG", + "displayName": "Kiteso (Uganda)", + "nativeName": "Kiteso (Uganda)" + }, + { + "name": "tg-Cyrl-TJ", + "displayName": "Tajik (Cyrillic, Tajikistan)", + "nativeName": "тоҷикӣ (Тоҷикистон)" + }, + { + "name": "th-TH", + "displayName": "Thai (Thailand)", + "nativeName": "ไทย (ไทย)" + }, + { + "name": "ti-ER", + "displayName": "Tigrinya (Eritrea)", + "nativeName": "ትግርኛ (ኤርትራ)" + }, + { + "name": "ti-ET", + "displayName": "Tigrinya (Ethiopia)", + "nativeName": "ትግርኛ (ኢትዮጵያ)" + }, + { + "name": "tig-ER", + "displayName": "ትግረ (ኤርትራ)", + "nativeName": "ትግረ (ኤርትራ)" + }, + { + "name": "tk-TM", + "displayName": "Turkmen (Turkmenistan)", + "nativeName": "Türkmen dili (Türkmenistan)" + }, + { + "name": "tn-BW", + "displayName": "Setswana (Botswana)", + "nativeName": "Setswana (Botswana)" + }, + { + "name": "tn-ZA", + "displayName": "Setswana (South Africa)", + "nativeName": "Setswana (Aforika Borwa)" + }, + { + "name": "to-TO", + "displayName": "lea fakatonga (Tonga)", + "nativeName": "lea fakatonga (Tonga)" + }, + { + "name": "tr-CY", + "displayName": "Türkçe (Kıbrıs)", + "nativeName": "Türkçe (Kıbrıs)" + }, + { + "name": "tr-TR", + "displayName": "Turkish (Turkey)", + "nativeName": "Türkçe (Türkiye)" + }, + { + "name": "ts-ZA", + "displayName": "Xitsonga (South Africa)", + "nativeName": "Xitsonga (South Africa)" + }, + { + "name": "tt-RU", + "displayName": "Tatar (Russia)", + "nativeName": "Татар (Россия)" + }, + { + "name": "twq-NE", + "displayName": "Tasawaq senni (Nižer)", + "nativeName": "Tasawaq senni (Nižer)" + }, + { + "name": "tzm-Arab-MA", + "displayName": "Central Atlas Tamazight (Arabic, Morocco)", + "nativeName": "أطلس المركزية التامازيتية (Morocco)" + }, + { + "name": "tzm-Latn-DZ", + "displayName": "Central Atlas Tamazight (Latin, Algeria)", + "nativeName": "Tamaziɣt n laṭlaṣ (Djazaïr)" + }, + { + "name": "tzm-Latn-MA", + "displayName": "Tamaziɣt n laṭlaṣ (Meṛṛuk)", + "nativeName": "Tamaziɣt n laṭlaṣ (Meṛṛuk)" + }, + { + "name": "tzm-Tfng-MA", + "displayName": "Central Atlas Tamazight (Tifinagh, Morocco)", + "nativeName": "ⵜⴰⵎⴰⵣⵉⵖⵜ (ⵍⵎⵖⵔⵉⴱ)" + }, + { + "name": "ug-CN", + "displayName": "Uyghur (China)", + "nativeName": "ئۇيغۇرچە (جۇڭخۇا خەلق جۇمھۇرىيىتى)" + }, + { + "name": "uk-UA", + "displayName": "Ukrainian (Ukraine)", + "nativeName": "українська (Україна)" + }, + { + "name": "ur-IN", + "displayName": "Urdu (India)", + "nativeName": "اردو (بھارت)" + }, + { + "name": "ur-PK", + "displayName": "Urdu (Pakistan)", + "nativeName": "اُردو (پاکستان)" + }, + { + "name": "uz-Arab-AF", + "displayName": "اوزبیک (افغانستان)", + "nativeName": "اوزبیک (افغانستان)" + }, + { + "name": "uz-Cyrl-UZ", + "displayName": "Uzbek (Cyrillic, Uzbekistan)", + "nativeName": "ўзбекча (Ўзбекистон)" + }, + { + "name": "uz-Latn-UZ", + "displayName": "Uzbek (Latin, Uzbekistan)", + "nativeName": "o‘zbek (Oʻzbekiston)" + }, + { + "name": "vai-Latn-LR", + "displayName": "Vai (Laibhiya)", + "nativeName": "Vai (Laibhiya)" + }, + { + "name": "vai-Vaii-LR", + "displayName": "ꕙꔤ (ꕞꔤꔫꕩ)", + "nativeName": "ꕙꔤ (ꕞꔤꔫꕩ)" + }, + { + "name": "ve-ZA", + "displayName": "Venda (South Africa)", + "nativeName": "Tshivenḓa (South Africa)" + }, + { + "name": "vi-VN", + "displayName": "Vietnamese (Vietnam)", + "nativeName": "Tiếng Việt (Việt Nam)" + }, + { + "name": "vo-001", + "displayName": "Volapük (World)", + "nativeName": "Volapük (World)" + }, + { + "name": "vun-TZ", + "displayName": "Kyivunjo (Tanzania)", + "nativeName": "Kyivunjo (Tanzania)" + }, + { + "name": "wae-CH", + "displayName": "Walser (Schwiz)", + "nativeName": "Walser (Schwiz)" + }, + { + "name": "wal-ET", + "displayName": "ወላይታቱ (ኢትዮጵያ)", + "nativeName": "ወላይታቱ (ኢትዮጵያ)" + }, + { + "name": "wo-SN", + "displayName": "Wolof (Senegal)", + "nativeName": "Wolof (Senegaal)" + }, + { + "name": "xh-ZA", + "displayName": "isiXhosa (South Africa)", + "nativeName": "isiXhosa (eMzantsi Afrika)" + }, + { + "name": "xog-UG", + "displayName": "Olusoga (Yuganda)", + "nativeName": "Olusoga (Yuganda)" + }, + { + "name": "yav-CM", + "displayName": "nuasue (Kemelún)", + "nativeName": "nuasue (Kemelún)" + }, + { + "name": "yi-001", + "displayName": "Yiddish (World)", + "nativeName": "ייִדיש (וועלט)" + }, + { + "name": "yo-BJ", + "displayName": "Èdè Yorùbá (Orílɛ́ède Bɛ̀nɛ̀)", + "nativeName": "Èdè Yorùbá (Orílɛ́ède Bɛ̀nɛ̀)" + }, + { + "name": "yo-NG", + "displayName": "Yoruba (Nigeria)", + "nativeName": "Èdè Yorùbá (Orílẹ́ède Nàìjíríà)" + }, + { + "name": "zgh-Tfng-MA", + "displayName": "ⵜⴰⵎⴰⵣⵉⵖⵜ (ⵍⵎⵖⵔⵉⴱ)", + "nativeName": "ⵜⴰⵎⴰⵣⵉⵖⵜ (ⵍⵎⵖⵔⵉⴱ)" + }, + { + "name": "zh-CN", + "displayName": "Chinese (Simplified, China)", + "nativeName": "中文(中国)" + }, + { + "name": "zh-Hans-HK", + "displayName": "中文 (香港特别行政区)", + "nativeName": "中文 (香港特别行政区)" + }, + { + "name": "zh-Hans-MO", + "displayName": "中文 (澳门特别行政区)", + "nativeName": "中文 (澳门特别行政区)" + }, + { + "name": "zh-HK", + "displayName": "Chinese (Traditional, Hong Kong SAR)", + "nativeName": "中文(香港特別行政區)" + }, + { + "name": "zh-MO", + "displayName": "Chinese (Traditional, Macao SAR)", + "nativeName": "中文(澳門特別行政區)" + }, + { + "name": "zh-SG", + "displayName": "Chinese (Simplified, Singapore)", + "nativeName": "中文(新加坡)" + }, + { + "name": "zh-TW", + "displayName": "Chinese (Traditional, Taiwan)", + "nativeName": "中文(台灣)" + }, + { + "name": "zu-ZA", + "displayName": "isiZulu (South Africa)", + "nativeName": "isiZulu (i-South Africa)" + } +] diff --git a/dmp-frontend/src/blue-theme.scss b/dmp-frontend/src/blue-theme.scss index 549e1b8bb..9e72e7d71 100644 --- a/dmp-frontend/src/blue-theme.scss +++ b/dmp-frontend/src/blue-theme.scss @@ -1,3 +1,4 @@ +@import 'app/ui/misc/navigation/navigation.component.scss'; @import '../node_modules/@angular/material/theming'; $app-blue-theme-primary-palette: ( @@ -123,6 +124,7 @@ $custom-typography: mat-typography-config( @include mat-core(); @include angular-material-theme($custom-theme); + @include navigation-component-theme($custom-theme); // Override typography CSS classes (e.g., mat-h1, mat-display-1, mat-typography, etc.). @include mat-base-typography($custom-typography); diff --git a/dmp-frontend/src/environments/environment.prod.ts b/dmp-frontend/src/environments/environment.prod.ts index 11211908a..4290dabaa 100644 --- a/dmp-frontend/src/environments/environment.prod.ts +++ b/dmp-frontend/src/environments/environment.prod.ts @@ -8,19 +8,20 @@ export const environment = { }, defaultCulture: 'en-US', loginProviders: { - facebookConfiguration: { clientId: '' }, - googleConfiguration: { clientId: '' }, + enabled: [1, 2, 3, 4, 5], + facebookConfiguration: { clientId: '613977555670785' }, + googleConfiguration: { clientId: '596924546661-83nhl986pnrpug5h624i5kptuao03dcd.apps.googleusercontent.com' }, linkedInConfiguration: { - clientId: '', + clientId: '86w8xorrsdzjud', oauthUrl: 'https://www.linkedin.com/oauth/v2/authorization', redirectUri: 'http://localhost:4200/login/linkedin', }, twitterConfiguration: { - clientId: '', + clientId: 'HiR4hQH9HNubKC5iKQy0l4mAZ', oauthUrl: 'https://api.twitter.com/oauth/authenticate' }, b2accessConfiguration: { - clientId: '', + clientId: 'eudatdmptool', oauthUrl: 'https://b2access-integration.fz-juelich.de:443/oauth2-as/oauth2-authz', redirectUri: 'http://opendmp.eu/api/oauth/authorized/b2access' } diff --git a/dmp-frontend/src/environments/environment.staging.ts b/dmp-frontend/src/environments/environment.staging.ts index 11211908a..eb186fa90 100644 --- a/dmp-frontend/src/environments/environment.staging.ts +++ b/dmp-frontend/src/environments/environment.staging.ts @@ -8,19 +8,20 @@ export const environment = { }, defaultCulture: 'en-US', loginProviders: { - facebookConfiguration: { clientId: '' }, - googleConfiguration: { clientId: '' }, + enabled: [1, 2, 3, 4, 5], + facebookConfiguration: { clientId: '613977555670785' }, + googleConfiguration: { clientId: '596924546661-83nhl986pnrpug5h624i5kptuao03dcd.apps.googleusercontent.com' }, linkedInConfiguration: { - clientId: '', + clientId: '86w8xorrsdzjud', oauthUrl: 'https://www.linkedin.com/oauth/v2/authorization', - redirectUri: 'http://localhost:4200/login/linkedin', + redirectUri: 'https://devel.opendmp.eu/login/linkedin', }, twitterConfiguration: { - clientId: '', + clientId: 'HiR4hQH9HNubKC5iKQy0l4mAZ', oauthUrl: 'https://api.twitter.com/oauth/authenticate' }, b2accessConfiguration: { - clientId: '', + clientId: 'eudatdmptool', oauthUrl: 'https://b2access-integration.fz-juelich.de:443/oauth2-as/oauth2-authz', redirectUri: 'http://opendmp.eu/api/oauth/authorized/b2access' } diff --git a/dmp-frontend/src/environments/environment.ts b/dmp-frontend/src/environments/environment.ts index fd6b7bc27..b217147fd 100644 --- a/dmp-frontend/src/environments/environment.ts +++ b/dmp-frontend/src/environments/environment.ts @@ -1,8 +1,3 @@ -// The file contents for the current environment will overwrite these during build. -// The build system defaults to the dev environment which uses `environment.ts`, but if you do -// `ng build --env=prod` then `environment.prod.ts` will be used instead. -// The list of which env maps to which file can be found in `.angular-cli.json`. - export const environment = { production: false, Server: 'http://localhost:8080/api/', @@ -13,17 +8,16 @@ export const environment = { }, defaultCulture: 'en-US', loginProviders: { - facebookConfiguration: { clientId: '' }, - googleConfiguration: { clientId: '' }, + enabled: [1, 2, 3, 4, 5], + facebookConfiguration: { clientId: '110586756143149' }, + googleConfiguration: { clientId: '524432312250-sc9qsmtmbvlv05r44onl6l93ia3k9deo.apps.googleusercontent.com' }, linkedInConfiguration: { - clientId: '', + clientId: '86bl8vfk77clh9', oauthUrl: 'https://www.linkedin.com/oauth/v2/authorization', - redirectUri: 'http://localhost:4200/login/linkedin', - accessTokenUri: 'https://www.linkedin.com/oauth/v2/accessToken', - clientSecret: '' + redirectUri: 'http://localhost:4200/login/linkedin' }, twitterConfiguration: { - clientId: '', + clientId: 'HiR4hQH9HNubKC5iKQy0l4mAZ', oauthUrl: 'https://api.twitter.com/oauth/authenticate' }, b2accessConfiguration: { @@ -31,5 +25,9 @@ export const environment = { oauthUrl: 'https://b2access-integration.fz-juelich.de:443/oauth2-as/oauth2-authz', redirectUri: 'http://opendmp.eu/api/oauth/authorized/b2access' } - } + }, + logging: { + enabled: true, + logLevels: ["debug", "info", "warning", "error"] + }, }; diff --git a/dmp-frontend/src/styles.scss b/dmp-frontend/src/styles.scss index 7fbe29962..042d4af51 100644 --- a/dmp-frontend/src/styles.scss +++ b/dmp-frontend/src/styles.scss @@ -13,7 +13,7 @@ $accent : mat-palette($mat-pink, A200, A100, A400); $theme: mat-light-theme($primary, $accent); // Include all theme styles for the components. @include angular-material-theme($theme); -@include covalent-theme($theme); +// @include covalent-theme($theme); .snackbar-warning { background-color: #F39010;