diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DMPDaoImpl.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DMPDaoImpl.java index b6fb3c5d4..0074428eb 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DMPDaoImpl.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DMPDaoImpl.java @@ -52,13 +52,12 @@ public class DMPDaoImpl extends DatabaseAccess implements DMPDao { query.where((builder, root) -> root.get("groupId").in(criteria.getGroupIds())); if (criteria.getStatus() != null) { if (criteria.getStatus() == DMP.DMPStatus.FINALISED.getValue()) { - query.where((builder, root) -> builder.and(builder.equal(root.get("status"), DMP.DMPStatus.FINALISED.getValue()), builder.notEqual(root.get("isPublic"), true))); + query.where((builder, root) -> builder.equal(root.get("status"), DMP.DMPStatus.FINALISED.getValue())); } else if (criteria.getStatus() == DMP.DMPStatus.ACTIVE.getValue()) { query.where((builder, root) -> builder.equal(root.get("status"), DMP.DMPStatus.ACTIVE.getValue())); } } - if (criteria.getIsPublic()) - query.where(((builder, root) -> builder.equal(root.get("isPublic"), true))); + query.where(((builder, root) -> builder.equal(root.get("isPublic"), criteria.getIsPublic()))); /*if (criteria.getRole() != null) { if (criteria.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())) { query.where((builder, root) -> builder.equal(root.join("users", JoinType.LEFT).get("role"), UserDMP.UserDMPRoles.OWNER.getValue())); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DashBoardManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DashBoardManager.java index b9761b6f9..62b5fa194 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DashBoardManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DashBoardManager.java @@ -1,14 +1,18 @@ package eu.eudat.logic.managers; -import eu.eudat.criteria.RecentActivityCriteria; -import eu.eudat.data.dao.criteria.*; +import eu.eudat.data.dao.criteria.DataManagementPlanCriteria; +import eu.eudat.data.dao.criteria.DatasetCriteria; +import eu.eudat.data.dao.criteria.GrantCriteria; +import eu.eudat.data.dao.criteria.OrganisationCriteria; import eu.eudat.data.dao.entities.DMPDao; import eu.eudat.data.dao.entities.DatasetDao; -import eu.eudat.data.dao.entities.OrganisationDao; import eu.eudat.data.dao.entities.GrantDao; -import eu.eudat.data.entities.*; +import eu.eudat.data.dao.entities.OrganisationDao; +import eu.eudat.data.entities.DMP; +import eu.eudat.data.entities.Dataset; +import eu.eudat.data.entities.Grant; +import eu.eudat.data.entities.UserInfo; import eu.eudat.data.query.PaginationService; -import eu.eudat.data.query.items.table.dmp.DataManagmentPlanPublicTableRequest; import eu.eudat.elastic.entities.Dmp; import eu.eudat.logic.builders.model.models.RecentActivityDataBuilder; import eu.eudat.logic.services.ApiContext; @@ -22,8 +26,6 @@ import eu.eudat.models.data.dashboard.recent.model.RecentDmpModel; import eu.eudat.models.data.dashboard.recent.tablerequest.RecentActivityTableRequest; import eu.eudat.models.data.dashboard.searchbar.SearchBarItem; import eu.eudat.models.data.dashboard.statistics.DashBoardStatistics; -import eu.eudat.models.data.listingmodels.DataManagementPlanListingModel; -import eu.eudat.models.data.listingmodels.DatasetListingModel; import eu.eudat.models.data.security.Principal; import eu.eudat.queryable.QueryableList; import eu.eudat.types.searchbar.SearchBarItemType; @@ -47,7 +49,9 @@ public class DashBoardManager { { "modified", Comparator.comparing(o -> ((RecentActivityModel)o).getModified()).reversed()}, { "created", Comparator.comparing(o -> ((RecentActivityModel)o).getCreated()).reversed()}, { "label", Comparator.comparing(o -> ((RecentActivityModel)o).getTitle())}, - { "status", Comparator.comparing(o -> ((RecentActivityModel)o).getStatus())} + { "status", Comparator.comparing(o -> ((RecentActivityModel)o).getStatus()).reversed()}, + { "finalizedAt", Comparator.comparing(o -> ((RecentActivityModel)o).getFinalizedAt(), Comparator.nullsLast(Comparator.naturalOrder())).reversed()}, + { "publishedAt", Comparator.comparing(o -> ((RecentActivityModel)o).getPublishedAt(), Comparator.nullsLast(Comparator.naturalOrder())).reversed()} }).collect(Collectors.toMap(data -> (String) data[0], data -> (Comparator)data[1])); private ApiContext apiContext; @@ -62,17 +66,12 @@ public class DashBoardManager { public DashBoardStatistics getStatistics() { DashBoardStatistics statistics = new DashBoardStatistics(); - DataManagmentPlanPublicTableRequest publicTableRequest = new DataManagmentPlanPublicTableRequest(); - - DataManagementPlanPublicCriteria publicCriteria = new DataManagementPlanPublicCriteria(); - + DataManagementPlanCriteria publicCriteria = new DataManagementPlanCriteria(); + publicCriteria.setIsPublic(true); + publicCriteria.setOnlyPublic(true); publicCriteria.setAllVersions(false); - publicTableRequest.setCriteria(publicCriteria); - - publicTableRequest.setQuery(databaseRepository.getDmpDao().asQueryable()); - - List dmps = publicTableRequest.applyCriteria().toList(); + List dmps = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().getWithCriteria(publicCriteria).toList(); // DataManagementPlanCriteria dataManagementPlanCriteria = new DataManagementPlanCriteria(); OrganisationCriteria organisationCriteria = new OrganisationCriteria(); @@ -199,7 +198,9 @@ public class DashBoardManager { DMPDao dataManagementPlanRepository = databaseRepository.getDmpDao(); DatasetDao datasetRepository = databaseRepository.getDatasetDao(); UserInfo user = new UserInfo(); - user.setId(principal.getId()); + if (isAuthenticated) { + user.setId(principal.getId()); + } DatasetCriteria datasetCriteria = new DatasetCriteria(); datasetCriteria.setLike(tableRequest.getCriteria().getLike()); datasetCriteria.setAllVersions(false); @@ -265,6 +266,13 @@ public class DashBoardManager { } PaginationService.applyOrder(dmpList, tableRequest.getOrderings()); + for (int i = 0; i< tableRequest.getOrderings().getFields().length; i++) { + if (tableRequest.getOrderings().getFields()[i].contains("publishedAt")) { + String newField = tableRequest.getOrderings().getFields()[i].toCharArray()[0] + "dmp:publishedAt|join|"; + tableRequest.getOrderings().getFields()[i] = newField; + } + } + PaginationService.applyOrder(datasetList, tableRequest.getOrderings()); /*CompletableFuture future = CompletableFuture.runAsync(() -> */{ recentActivityModels.addAll(dmpList @@ -297,13 +305,11 @@ public class DashBoardManager { int pos = -1; for (int i = (recentActivityModels.size() / 2); i < recentActivityModels.size(); i++) { RecentActivityModel recentActivityModel = recentActivityModels.remove(i); - while (pos < recentActivityModels.size()) { pos++; if (pos % 2 != 0) { break; } - } recentActivityModels.add(pos, recentActivityModel); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java index 7603d1c64..199c4f504 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java @@ -419,6 +419,9 @@ public class DataManagementPlanManager { apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() .asQueryable().where((builder, root) -> root.get("id").in(dataManagementPlan.getDatasetsToBeFinalized())) .update(root -> root.get("status"), Dataset.Status.FINALISED.getValue()); + apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() + .asQueryable().where((builder, root) -> root.get("id").in(dataManagementPlan.getDatasetsToBeFinalized())) + .update(root -> root.get("finalizedat"), new Date()); List datasetsToBeCanceled = new LinkedList<>(); for (DatasetWizardModel dataset : dataManagementPlan.getDatasets()) { @@ -894,8 +897,15 @@ public class DataManagementPlanManager { apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeFinalized.getUuids())) .update(root -> root.get("status"), Dataset.Status.FINALISED.getValue()); + apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() + .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeFinalized.getUuids())) + .update(root -> root.get("finalizedAt"), new Date()); List finalizedDatasets = dmp.getDataset().stream().filter(dataset -> datasetsToBeFinalized.getUuids().contains(dataset.getId())).collect(Collectors.toList()); - finalizedDatasets.forEach(dataset -> dataset.setStatus(Dataset.Status.FINALISED.getValue())); + finalizedDatasets.forEach(dataset ->{ + dataset.setStatus(Dataset.Status.FINALISED.getValue()); + dataset.setFinalizedAt(new Date()); + dataset.setModified(new Date()); + } ); indexDatasets.addAll(finalizedDatasets); List datasetsToBeCanceled = new LinkedList<>(); for (Dataset dataset : dmp.getDataset()) { diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetManager.java index b97962f3b..b2242d5d2 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetManager.java @@ -180,8 +180,8 @@ public class DatasetManager { }); } String[] strings = new String[1]; - strings[0] = "-dmp:publishedAt|join|"; - datasetTableRequest.getOrderings().setFields(strings); + //strings[0] = "-dmp:publishedAt|join|"; + //datasetTableRequest.getOrderings().setFields(strings); authItems = items; pagedItems = PaginationManager.applyPaging(items, datasetTableRequest); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/components/commons/datafield/AutoCompleteData.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/components/commons/datafield/AutoCompleteData.java index 1a117bf16..e4e5fcf94 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/components/commons/datafield/AutoCompleteData.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/components/commons/datafield/AutoCompleteData.java @@ -128,7 +128,10 @@ public class AutoCompleteData extends ComboBoxData { if (data != null) { this.multiAutoComplete = (Boolean) ((Map) data).get("multiAutoComplete"); - List> dataList = (List>) ((Map) data).get("autoCompleteSingleDataList"); + List> dataList = (List>) ((Map) data).get("autocompleteSingle"); + if (dataList == null) { + dataList = (List>) ((Map) data).get("autoCompleteSingleDataList"); + } this.autoCompleteSingleDataList = new ArrayList<>(); @@ -174,19 +177,21 @@ public class AutoCompleteData extends ComboBoxData { List> autoCompletes = new ArrayList<>(); NodeList autoCompleteSingles = item.getChildNodes(); for (int i = 0; i < autoCompleteSingles.getLength(); i++) { - if (autoCompleteSingles.item(i) instanceof Element && !((Element) autoCompleteSingles.item(i)).getTagName().equals("option")) { - Element node = (Element) autoCompleteSingles.item(i); - if (!node.hasChildNodes()) { - node.appendChild(node); - } + if (autoCompleteSingles.item(i) instanceof Element) { + if (!((Element) autoCompleteSingles.item(i)).getTagName().equals("option")) { + Element node = (Element) autoCompleteSingles.item(i); + if (!node.hasChildNodes()) { + node.appendChild(node); + } - autoCompletes.add(singleToMap(node)); - } else if (((Element) autoCompleteSingles.item(i)).getTagName().equals("option")) { - Element node = item.getOwnerDocument().createElement("autocompleteSingle"); - node.appendChild(autoCompleteSingles.item(i)); - node.setAttribute("url", item.getAttribute("url")); - node.setAttribute("optionsRoot", item.getAttribute("optionsRoot")); - autoCompletes.add(singleToMap(node)); + autoCompletes.add(singleToMap(node)); + } else { + Element node = item.getOwnerDocument().createElement("autocompleteSingle"); + node.appendChild(autoCompleteSingles.item(i)); + node.setAttribute("url", item.getAttribute("url")); + node.setAttribute("optionsRoot", item.getAttribute("optionsRoot")); + autoCompletes.add(singleToMap(node)); + } } } dataMap.put("autocompleteSingle", autoCompletes); diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanOverviewModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanOverviewModel.java index 362cd510d..e90d044c1 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanOverviewModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanOverviewModel.java @@ -177,6 +177,9 @@ public class DataManagementPlanOverviewModel implements DataModel new Researcher().fromDataModel(item)).collect(Collectors.toList()); + } return this; } @@ -192,7 +195,9 @@ public class DataManagementPlanOverviewModel implements DataModel !dataset.getStatus().equals(Dataset.Status.DELETED.getValue()) && !dataset.getStatus().equals(Dataset.Status.CANCELED.getValue())).map(x-> new DatasetOverviewModel().fromDataModel(x)).collect(Collectors.toList()); this.users = entity.getUsers().stream().map(x -> new UserInfoListingModel().fromDataModel(x)).collect(Collectors.toList()); this.description = entity.getDescription(); - this.researchers = entity.getResearchers().stream().map(item -> new Researcher().fromDataModel(item)).collect(Collectors.toList()); + if (entity.getResearchers() != null) { + this.researchers = entity.getResearchers().stream().map(item -> new Researcher().fromDataModel(item)).collect(Collectors.toList()); + } if (entity.getAssociatedDmps() != null && !entity.getAssociatedDmps().isEmpty()) { this.associatedProfiles = new LinkedList<>(); diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DatasetListingModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DatasetListingModel.java index 667c7ebb2..c0bb5a74f 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DatasetListingModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DatasetListingModel.java @@ -204,7 +204,11 @@ public class DatasetListingModel implements DataModel new eu.eudat.models.data.dataset.Registry().fromDataModel(item)).collect(Collectors.toList())); this.dataRepositories = LabelBuilder.getLabel(entity.getDatasetDataRepositories().stream().map(item -> new DataRepository().fromDataModel(item.getDataRepository())).collect(Collectors.toList())); this.services = LabelBuilder.getLabel(entity.getServices().stream().map(item -> new Service().fromDataModel(item.getService())).collect(Collectors.toList())); - this.finalizedAt = entity.getFinalizedAt(); + if (entity.getFinalizedAt() == null && entity.getStatus() == Dataset.Status.FINALISED.getValue()) { + this.finalizedAt = entity.getDmp().getFinalizedAt(); + } else { + this.finalizedAt = entity.getFinalizedAt(); + } this.dmpPublishedAt = entity.getDmp().getPublishedAt(); this.version = entity.getDmp().getVersion(); this.users = entity.getDmp() != null ? entity.getDmp().getUsers().stream().map(x -> new UserInfoListingModel().fromDataModel(x)).collect(Collectors.toList()) : new ArrayList<>(); diff --git a/dmp-frontend/package.json b/dmp-frontend/package.json index 38701dc4c..07983c8b1 100644 --- a/dmp-frontend/package.json +++ b/dmp-frontend/package.json @@ -32,6 +32,7 @@ "moment-timezone": "^0.5.26", "ngx-cookie-service": "^2.2.0", "ngx-cookieconsent": "^2.2.3", + "ngx-guided-tour": "^1.1.10", "rxjs": "^6.3.2", "tinymce": "^5.1.6", "tslib": "^1.10.0", diff --git a/dmp-frontend/src/app/app.component.html b/dmp-frontend/src/app/app.component.html index 6243a45e8..3e7595fa7 100644 --- a/dmp-frontend/src/app/app.component.html +++ b/dmp-frontend/src/app/app.component.html @@ -24,3 +24,5 @@ + + \ No newline at end of file diff --git a/dmp-frontend/src/app/app.component.ts b/dmp-frontend/src/app/app.component.ts index 999752643..7fd33fb2d 100644 --- a/dmp-frontend/src/app/app.component.ts +++ b/dmp-frontend/src/app/app.component.ts @@ -100,17 +100,8 @@ export class AppComponent implements OnInit { return appTitle; }) ).subscribe((ttl: string) => { - if (ttl.length > 0) { - this.translate.get(ttl).subscribe((translated: string) => { - this.translate.get('GENERAL.TITLES.PREFIX').subscribe((titlePrefix: string) => { - this.titleService.setTitle(titlePrefix + translated); - }); - }); - } else { - this.translate.get('GENERAL.TITLES.GENERAL').subscribe((translated: string) => { - this.titleService.setTitle(translated); - }); - } + this.translateTitle(ttl); + this.translate.onLangChange.subscribe(() => this.translateTitle(ttl)); }); this.statusChangeSubscription = this.ccService.statusChange$.subscribe((event: NgcStatusChangeEvent) => { @@ -140,6 +131,20 @@ export class AppComponent implements OnInit { }) } + translateTitle(ttl: string) { + if (ttl.length > 0) { + this.translate.get(ttl).subscribe((translated: string) => { + this.translate.get('GENERAL.TITLES.PREFIX').subscribe((titlePrefix: string) => { + this.titleService.setTitle(titlePrefix + translated); + }); + }); + } else { + this.translate.get('GENERAL.TITLES.GENERAL').subscribe((translated: string) => { + this.titleService.setTitle(translated); + }); + } + } + ngOnDestroy() { this.statusChangeSubscription.unsubscribe(); } diff --git a/dmp-frontend/src/app/app.module.ts b/dmp-frontend/src/app/app.module.ts index f8575729f..a460a2e19 100644 --- a/dmp-frontend/src/app/app.module.ts +++ b/dmp-frontend/src/app/app.module.ts @@ -32,6 +32,7 @@ import { BaseHttpService } from './core/services/http/base-http.service'; import { ConfigurationService } from './core/services/configuration/configuration.service'; import { Oauth2DialogModule } from './ui/misc/oauth2-dialog/oauth2-dialog.module'; import { MAT_FORM_FIELD_DEFAULT_OPTIONS, MatFormFieldDefaultOptions } from '@angular/material'; +import { GuidedTourModule } from './library/guided-tour/guided-tour.module'; // AoT requires an exported function for factories export function HttpLoaderFactory(http: HttpClient, appConfig: ConfigurationService) { @@ -105,7 +106,8 @@ const appearance: MatFormFieldDefaultOptions = { NavbarModule, SidebarModule, NgcCookieConsentModule.forRoot(cookieConfig), - Oauth2DialogModule + Oauth2DialogModule, + GuidedTourModule.forRoot() ], declarations: [ AppComponent, diff --git a/dmp-frontend/src/app/core/common/enum/recent-activity-order.ts b/dmp-frontend/src/app/core/common/enum/recent-activity-order.ts index 792ede63c..bfed5fac8 100644 --- a/dmp-frontend/src/app/core/common/enum/recent-activity-order.ts +++ b/dmp-frontend/src/app/core/common/enum/recent-activity-order.ts @@ -2,5 +2,8 @@ export enum RecentActivityOrder { LABEL = "label", CREATED = "created", MODIFIED = "modified", + FINALIZED = "finalizedAt", + PUBLISHED = "publishedAt", + DATASETPUBLISHED = "dmp:publishedAt|join|", STATUS = "status" } diff --git a/dmp-frontend/src/app/core/model/dataset/dataset-listing.ts b/dmp-frontend/src/app/core/model/dataset/dataset-listing.ts index c4aa19530..377c8a2bf 100644 --- a/dmp-frontend/src/app/core/model/dataset/dataset-listing.ts +++ b/dmp-frontend/src/app/core/model/dataset/dataset-listing.ts @@ -2,7 +2,7 @@ import { DatasetProfileModel } from './dataset-profile'; export interface DatasetListingModel { id: string; - label: String; + label: string; dmp: String; dmpId: String; grant: String; diff --git a/dmp-frontend/src/app/core/model/dmp/dmp-listing.ts b/dmp-frontend/src/app/core/model/dmp/dmp-listing.ts index 0461ddeb6..3425e0ce1 100644 --- a/dmp-frontend/src/app/core/model/dmp/dmp-listing.ts +++ b/dmp-frontend/src/app/core/model/dmp/dmp-listing.ts @@ -3,7 +3,7 @@ import { DmpAssociatedProfileModel } from '../dmp-profile/dmp-associated-profile export interface DmpListingModel { id: string; - label: String; + label: string; description: String; status: DmpStatus; grant: String; diff --git a/dmp-frontend/src/app/core/model/recent-activity/recent-activity.model.ts b/dmp-frontend/src/app/core/model/recent-activity/recent-activity.model.ts index b1cf43c60..2102171e2 100644 --- a/dmp-frontend/src/app/core/model/recent-activity/recent-activity.model.ts +++ b/dmp-frontend/src/app/core/model/recent-activity/recent-activity.model.ts @@ -4,7 +4,7 @@ import { DatasetProfileModel } from '../dataset/dataset-profile'; export class RecentActivityModel { id: string; - title: String; + title: string; description: String; created: Date; modified: Date; diff --git a/dmp-frontend/src/app/core/model/recent-activity/recent-dmp-activity.model.ts b/dmp-frontend/src/app/core/model/recent-activity/recent-dmp-activity.model.ts index a74d0bd79..b416e4cb0 100644 --- a/dmp-frontend/src/app/core/model/recent-activity/recent-dmp-activity.model.ts +++ b/dmp-frontend/src/app/core/model/recent-activity/recent-dmp-activity.model.ts @@ -2,11 +2,12 @@ import { RecentActivityModel } from './recent-activity.model'; import { RecentDatasetModel } from './recent-dataset-activity.model'; import { DmpAssociatedProfileModel } from '../dmp-profile/dmp-associated-profile'; import { UserInfoListingModel } from '../user/user-info-listing'; +import { DatasetUrlListing } from '../dataset/dataset-url-listing'; export class RecentDmpModel extends RecentActivityModel { doi: String; extraProperties: Map; - datasets: any[]; + datasets: DatasetUrlListing[]; associatedProfiles: DmpAssociatedProfileModel[]; organisations: String; groupId: string; 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 index 0e7e3d09f..54d821ead 100644 --- a/dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts +++ b/dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts @@ -109,6 +109,9 @@ export class EnumUtils { case RecentActivityOrder.CREATED: return this.language.instant('TYPES.RECENT-ACTIVITY-ORDER.CREATED'); case RecentActivityOrder.LABEL: return this.language.instant('TYPES.RECENT-ACTIVITY-ORDER.LABEL'); case RecentActivityOrder.MODIFIED: return this.language.instant('TYPES.RECENT-ACTIVITY-ORDER.MODIFIED'); + case RecentActivityOrder.FINALIZED: return this.language.instant('TYPES.RECENT-ACTIVITY-ORDER.FINALIZED'); + case RecentActivityOrder.PUBLISHED: return this.language.instant('TYPES.RECENT-ACTIVITY-ORDER.PUBLISHED'); + case RecentActivityOrder.DATASETPUBLISHED: return this.language.instant('TYPES.RECENT-ACTIVITY-ORDER.PUBLISHED'); case RecentActivityOrder.STATUS: return this.language.instant('TYPES.RECENT-ACTIVITY-ORDER.STATUS'); } } diff --git a/dmp-frontend/src/app/library/guided-tour/guided-tour.component.html b/dmp-frontend/src/app/library/guided-tour/guided-tour.component.html new file mode 100644 index 000000000..3f8e8dc89 --- /dev/null +++ b/dmp-frontend/src/app/library/guided-tour/guided-tour.component.html @@ -0,0 +1,42 @@ + +
+
+
+
+
+
+
+
+
+
+

+ {{currentTourStep.title}} +

+

+ {{ currentTourStep.title }} +

+
+ + +
+
+
+
+
+
\ No newline at end of file diff --git a/dmp-frontend/src/app/library/guided-tour/guided-tour.component.scss b/dmp-frontend/src/app/library/guided-tour/guided-tour.component.scss new file mode 100644 index 000000000..a39ea2aaf --- /dev/null +++ b/dmp-frontend/src/app/library/guided-tour/guided-tour.component.scss @@ -0,0 +1,246 @@ +ngx-guided-tour { + .guided-tour-user-input-mask { + position: fixed; + top: 0; + left: 0; + display: block; + height: 100%; + width: 100%; + max-height: 100vh; + text-align: center; + opacity: 0; + } + + .guided-tour-spotlight-overlay { + position: fixed; + box-shadow: 0 0 0 9999px rgba(0,0,0,.7), 0 0 1.5rem rgba(0,0,0,.5); + border-radius: 44px; /*custom add*/ + } + + .tour-orb { + position: fixed; + width: 20px; + height: 20px; + border-radius: 50%; + + .tour-orb-ring { + width: 35px; + height: 35px; + position: relative; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + animation: pulse 2s linear infinite; + + &:after { + content: ''; + display: inline-block; + height: 100%; + width: 100%; + border-radius: 50%; + } + } + + @keyframes pulse { + from { + transform: translate(-50%, -50%) scale(0.45); + opacity: 1.0; + } + to { + transform: translate(-50%, -50%) scale(1); + opacity: 0.0; + } + } + } + + .tour-step { + position: fixed; + &.page-tour-step { + // max-width: 400px; + max-width: 1043px; /*custom add*/ + width: 50%; + left: 50%; + top: 50%; + border-radius: 5px; + transform: translate(-50%, -50%) + } + &.tour-bottom, &.tour-bottom-right, &.tour-bottom-left { + .tour-arrow::before { + position: absolute; + } + .tour-block { + margin-top: 10px; + } + } + + &.tour-top, &.tour-top-right, &.tour-top-left { + margin-bottom: 10px; + + .tour-arrow::before { + position: absolute; + bottom: 0; + } + .tour-block { + margin-bottom: 10px; + } + } + + &.tour-bottom , &.tour-top { + .tour-arrow::before { + // transform: translateX(-50%); + // left: 50%; + /*custom add*/ + transform: scale(2); + left: 494px; + } + /*custom add*/ + margin-top: 20px; + margin-left: 10px; + } + + &.tour-bottom-right, &.tour-top-right { + .tour-arrow::before { + transform: translateX(-100%); + left: calc(100% - 5px); + } + } + + &.tour-bottom-left, &.tour-top-left { + .tour-arrow::before { + left: 5px; + } + } + + &.tour-left { + .tour-arrow::before { + position: absolute; + left: 100%; + transform: translateX(-100%); + top: 5px; + } + .tour-block { + margin-right: 10px; + } + } + + &.tour-right { + margin-left: 10px; /*custom add*/ + .tour-arrow::before { + transform: scale(1.5); /*custom add*/ + position: absolute; + left: 0; + top: 5px; + } + .tour-block { + margin-top: -15px; /*custom add*/ + margin-left: 10px; + } + } + + .tour-block { + // padding: 15px 25px; + + /*custom add*/ + padding: 15px 25px 15px 0px; + max-height: 348px; + border-radius: 5px; + } + + .tour-title { + // font-weight: bold !important; + // padding-bottom: 20px; + + /*custom add*/ + font-weight: lighter !important; + font-size: 16px !important; + padding: 28px 74px 0px 65px; + overflow: auto; + text-align: left; + color: #212121; + line-height: 26px; + white-space:pre-line; + height: 210px; + } + + h3.tour-title { + font-size: 20px; + } + h2.tour-title { + font-size: 30px; + } + + .tour-buttons { + overflow: hidden; // clearfix + padding: 10px 70px 30px 65px; /*custom add*/ + + button.link-button { + padding-left: 0; + font-size: 15px; + font-weight: bold; + max-width: none !important; + cursor: pointer; + text-align: center; + white-space: nowrap; + vertical-align: middle; + border: 1px solid transparent; + line-height: 1.5; + background-color: transparent; + position: relative; + outline: none; + padding: 0 15px; + -webkit-appearance: button; + } + + button.skip-button.link-button { + // padding-left: 0; + border-left: 0; + + /*custom add*/ + padding: 0; + float: right; + width: 133px; + height: 40px; + border: 1px solid #129D99; + background: #FFFFFF 0% 0% no-repeat padding-box; + color: #129D99; + } + + .next-button { + cursor: pointer; + // border-radius: 1px; + // float: right; + border: none; + outline: none; + // padding-left: 10px; + // padding-right: 10px; + + /*custom add*/ + float: left; + padding: 10px 0px;; + width: 101px; + background: #129D99 0% 0% no-repeat padding-box; + } + + /*custom add*/ + button.skip-button.link-button, .next-button { + font-size: 14px; + font-weight: bold; + letter-spacing: 0.35px; + height: 40px; + box-shadow: 0px 3px 6px #1E202029; + border-radius: 30px; + } + } + + /*custom add*/ + .argos-present-img { + background: url("../../../assets/splash/assets/img/argos\ present.png") no-repeat; + min-width: 176px; + height: 220px; + position: relative; + top: 110px; + left: -85px; + border-top: none; + } + } +} diff --git a/dmp-frontend/src/app/library/guided-tour/guided-tour.component.ts b/dmp-frontend/src/app/library/guided-tour/guided-tour.component.ts new file mode 100644 index 000000000..913ab6d1b --- /dev/null +++ b/dmp-frontend/src/app/library/guided-tour/guided-tour.component.ts @@ -0,0 +1,399 @@ +import { AfterViewInit, Component, ElementRef, Input, OnDestroy, ViewChild, ViewEncapsulation, TemplateRef, Inject, ChangeDetectorRef } from '@angular/core'; +import { fromEvent, Subscription } from 'rxjs'; +import { DOCUMENT } from '@angular/common'; +import { Orientation, TourStep } from './guided-tour.constants'; +import { GuidedTourService } from './guided-tour.service'; +import { WindowRefService } from "./windowref.service"; + +@Component({ + selector: 'ngx-guided-tour', + templateUrl: './guided-tour.component.html', + styleUrls: ['./guided-tour.component.scss'], + encapsulation: ViewEncapsulation.None +}) +export class GuidedTourComponent implements AfterViewInit, OnDestroy { + @Input() public topOfPageAdjustment?= 0; + @Input() public tourStepWidth?= 1043; + @Input() public minimalTourStepWidth?= 500; + @Input() public skipText?= 'Leave Tour'; + @Input() public nextText?= 'Got it!'; + @ViewChild('tourStep', { static: false }) public tourStep: ElementRef; + public highlightPadding = 4; + public currentTourStep: TourStep = null; + public selectedElementRect: DOMRect = null; + public isOrbShowing = false; + + private resizeSubscription: Subscription; + private scrollSubscription: Subscription; + + constructor( + public guidedTourService: GuidedTourService, + private windowRef: WindowRefService, + private changeDetectorRef: ChangeDetectorRef, /*custom add*/ + @Inject(DOCUMENT) private dom: any + ) { } + + private get maxWidthAdjustmentForTourStep(): number { + return this.tourStepWidth - this.minimalTourStepWidth; + } + + private get widthAdjustmentForScreenBound(): number { + if (!this.tourStep) { + return 0; + } + let adjustment = 0; + if (this.calculatedLeftPosition < 0) { + adjustment = -this.calculatedLeftPosition; + } + if (this.calculatedLeftPosition > this.windowRef.nativeWindow.innerWidth - this.tourStepWidth) { + adjustment = this.calculatedLeftPosition - (this.windowRef.nativeWindow.innerWidth - this.tourStepWidth); + } + + return Math.min(this.maxWidthAdjustmentForTourStep, adjustment); + } + + public get calculatedTourStepWidth() { + return this.tourStepWidth - this.widthAdjustmentForScreenBound; + } + + public ngAfterViewInit(): void { + this.guidedTourService.guidedTourCurrentStepStream.subscribe((step: TourStep) => { + this.currentTourStep = step; + if (step && step.selector) { + const selectedElement = this.dom.querySelector(step.selector); + if (selectedElement) { + this.handleOrb(); /*custom add*/ + this.scrollToAndSetElement(); + } else { + this.selectedElementRect = null; + } + } else { + this.selectedElementRect = null; + } + }); + + this.guidedTourService.guidedTourOrbShowingStream.subscribe((value: boolean) => { + this.isOrbShowing = value; + }); + + this.resizeSubscription = fromEvent(this.windowRef.nativeWindow, 'resize').subscribe(() => { + this.updateStepLocation(); + }); + + this.scrollSubscription = fromEvent(this.windowRef.nativeWindow, 'scroll').subscribe(() => { + this.updateStepLocation(); + }); + } + + /*custom add*/ + ngAfterContentChecked() { + this.changeDetectorRef.detectChanges(); + } + + public ngOnDestroy(): void { + this.resizeSubscription.unsubscribe(); + this.scrollSubscription.unsubscribe(); + } + + public scrollToAndSetElement(): void { + this.updateStepLocation(); + // Allow things to render to scroll to the correct location + setTimeout(() => { + if (!this.isOrbShowing && !this.isTourOnScreen()) { + if (this.selectedElementRect && this.isBottom()) { + // Scroll so the element is on the top of the screen. + const topPos = ((this.windowRef.nativeWindow.scrollY + this.selectedElementRect.top) - this.topOfPageAdjustment) + - (this.currentTourStep.scrollAdjustment ? this.currentTourStep.scrollAdjustment : 0) + + this.getStepScreenAdjustment(); + try { + this.windowRef.nativeWindow.scrollTo({ + left: null, + top: topPos, + behavior: 'smooth' + }); + } catch (err) { + if (err instanceof TypeError) { + this.windowRef.nativeWindow.scroll(0, topPos); + } else { + throw err; + } + } + } else { + // Scroll so the element is on the bottom of the screen. + const topPos = (this.windowRef.nativeWindow.scrollY + this.selectedElementRect.top + this.selectedElementRect.height) + - this.windowRef.nativeWindow.innerHeight + + (this.currentTourStep.scrollAdjustment ? this.currentTourStep.scrollAdjustment : 0) + - this.getStepScreenAdjustment(); + try { + this.windowRef.nativeWindow.scrollTo({ + left: null, + top: topPos, + behavior: 'smooth' + }); + } catch (err) { + if (err instanceof TypeError) { + this.windowRef.nativeWindow.scroll(0, topPos); + } else { + throw err; + } + } + } + } + }); + } + + public handleOrb(): void { + this.guidedTourService.activateOrb(); + if (this.currentTourStep && this.currentTourStep.selector) { + this.scrollToAndSetElement(); + } + } + + private isTourOnScreen(): boolean { + return this.tourStep + && this.elementInViewport(this.dom.querySelector(this.currentTourStep.selector)) + && this.elementInViewport(this.tourStep.nativeElement); + } + + private elementInViewport(element: HTMLElement): boolean { + let top = element.offsetTop; + const height = element.offsetHeight; + + while (element.offsetParent) { + element = (element.offsetParent as HTMLElement); + top += element.offsetTop; + } + if (this.isBottom()) { + return ( + top >= (this.windowRef.nativeWindow.pageYOffset + + this.topOfPageAdjustment + + (this.currentTourStep.scrollAdjustment ? this.currentTourStep.scrollAdjustment : 0) + + this.getStepScreenAdjustment()) + && (top + height) <= (this.windowRef.nativeWindow.pageYOffset + this.windowRef.nativeWindow.innerHeight) + ); + } else { + return ( + top >= (this.windowRef.nativeWindow.pageYOffset + this.topOfPageAdjustment - this.getStepScreenAdjustment()) + && (top + height + (this.currentTourStep.scrollAdjustment ? this.currentTourStep.scrollAdjustment : 0)) <= (this.windowRef.nativeWindow.pageYOffset + this.windowRef.nativeWindow.innerHeight) + ); + } + } + + public backdropClick(event: Event): void { + if (this.guidedTourService.preventBackdropFromAdvancing) { + event.stopPropagation(); + } else { + this.guidedTourService.nextStep(); + } + } + + public updateStepLocation(): void { + if (this.currentTourStep && this.currentTourStep.selector) { + const selectedElement = this.dom.querySelector(this.currentTourStep.selector); + if (selectedElement && typeof selectedElement.getBoundingClientRect === 'function') { + this.selectedElementRect = (selectedElement.getBoundingClientRect() as DOMRect); + } else { + this.selectedElementRect = null; + } + } else { + this.selectedElementRect = null; + } + } + + private isBottom(): boolean { + return this.currentTourStep.orientation + && (this.currentTourStep.orientation === Orientation.Bottom + || this.currentTourStep.orientation === Orientation.BottomLeft + || this.currentTourStep.orientation === Orientation.BottomRight); + } + + public get topPosition(): number { + const paddingAdjustment = this.getHighlightPadding(); + + if (this.isBottom()) { + return this.selectedElementRect.top + this.selectedElementRect.height + paddingAdjustment; + } + + return this.selectedElementRect.top - this.getHighlightPadding(); + } + + public get orbTopPosition(): number { + if (this.isBottom()) { + return this.selectedElementRect.top + this.selectedElementRect.height; + } + + if ( + this.currentTourStep.orientation === Orientation.Right + || this.currentTourStep.orientation === Orientation.Left + ) { + return (this.selectedElementRect.top + (this.selectedElementRect.height / 2)); + } + + return this.selectedElementRect.top; + } + + private get calculatedLeftPosition(): number { + const paddingAdjustment = this.getHighlightPadding(); + + if ( + this.currentTourStep.orientation === Orientation.TopRight + || this.currentTourStep.orientation === Orientation.BottomRight + ) { + return (this.selectedElementRect.right - this.tourStepWidth); + } + + if ( + this.currentTourStep.orientation === Orientation.TopLeft + || this.currentTourStep.orientation === Orientation.BottomLeft + ) { + return (this.selectedElementRect.left); + } + + if (this.currentTourStep.orientation === Orientation.Left) { + return this.selectedElementRect.left - this.tourStepWidth - paddingAdjustment; + } + + if (this.currentTourStep.orientation === Orientation.Right) { + return (this.selectedElementRect.left + this.selectedElementRect.width + paddingAdjustment); + } + + return (this.selectedElementRect.right - (this.selectedElementRect.width / 2) - (this.tourStepWidth / 2)); + } + + public get leftPosition(): number { + if (this.calculatedLeftPosition >= 0) { + return this.calculatedLeftPosition; + } + const adjustment = Math.max(0, -this.calculatedLeftPosition) + const maxAdjustment = Math.min(this.maxWidthAdjustmentForTourStep, adjustment); + return this.calculatedLeftPosition + maxAdjustment; + } + + public get orbLeftPosition(): number { + if ( + this.currentTourStep.orientation === Orientation.TopRight + || this.currentTourStep.orientation === Orientation.BottomRight + ) { + return this.selectedElementRect.right; + } + + if ( + this.currentTourStep.orientation === Orientation.TopLeft + || this.currentTourStep.orientation === Orientation.BottomLeft + ) { + return this.selectedElementRect.left; + } + + if (this.currentTourStep.orientation === Orientation.Left) { + return this.selectedElementRect.left; + } + + if (this.currentTourStep.orientation === Orientation.Right) { + return (this.selectedElementRect.left + this.selectedElementRect.width); + } + + return (this.selectedElementRect.right - (this.selectedElementRect.width / 2)); + } + + public get transform(): string { + if ( + !this.currentTourStep.orientation + || this.currentTourStep.orientation === Orientation.Top + || this.currentTourStep.orientation === Orientation.TopRight + || this.currentTourStep.orientation === Orientation.TopLeft + ) { + return 'translateY(-100%)'; + } + return null; + } + + public get orbTransform(): string { + if ( + !this.currentTourStep.orientation + || this.currentTourStep.orientation === Orientation.Top + || this.currentTourStep.orientation === Orientation.Bottom + || this.currentTourStep.orientation === Orientation.TopLeft + || this.currentTourStep.orientation === Orientation.BottomLeft + ) { + return 'translateY(-50%)'; + } + + if ( + this.currentTourStep.orientation === Orientation.TopRight + || this.currentTourStep.orientation === Orientation.BottomRight + ) { + return 'translate(-100%, -50%)'; + } + + if ( + this.currentTourStep.orientation === Orientation.Right + || this.currentTourStep.orientation === Orientation.Left + ) { + return 'translate(-50%, -50%)'; + } + + return null; + } + + public get overlayTop(): number { + if (this.selectedElementRect) { + // return this.selectedElementRect.top - this.getHighlightPadding(); + + /*custom add*/ + let customTopOffset = 0; + if (this.currentTourStep.customTopOffset) { + customTopOffset = this.currentTourStep.customTopOffset; + } + return this.selectedElementRect.top - this.getHighlightPadding() - customTopOffset; + } + return 0; + } + + public get overlayLeft(): number { + if (this.selectedElementRect) { + return this.selectedElementRect.left - this.getHighlightPadding(); + } + return 0; + } + + public get overlayHeight(): number { + if (this.selectedElementRect) { + return this.selectedElementRect.height + (this.getHighlightPadding() * 2); + } + return 0; + } + + public get overlayWidth(): number { + if (this.selectedElementRect) { + return (this.selectedElementRect.width + (this.getHighlightPadding() * 2)) * 0.95; + } + return 0; + } + + private getHighlightPadding(): number { + let paddingAdjustment = this.currentTourStep.useHighlightPadding ? this.highlightPadding : 0; + if (this.currentTourStep.highlightPadding) { + paddingAdjustment = this.currentTourStep.highlightPadding; + } + return paddingAdjustment; + } + + // This calculates a value to add or subtract so the step should not be off screen. + private getStepScreenAdjustment(): number { + if ( + this.currentTourStep.orientation === Orientation.Left + || this.currentTourStep.orientation === Orientation.Right + ) { + return 0; + } + + const scrollAdjustment = this.currentTourStep.scrollAdjustment ? this.currentTourStep.scrollAdjustment : 0; + const tourStepHeight = typeof this.tourStep.nativeElement.getBoundingClientRect === 'function' ? this.tourStep.nativeElement.getBoundingClientRect().height : 0; + const elementHeight = this.selectedElementRect.height + scrollAdjustment + tourStepHeight; + + if ((this.windowRef.nativeWindow.innerHeight - this.topOfPageAdjustment) < elementHeight) { + return elementHeight - (this.windowRef.nativeWindow.innerHeight - this.topOfPageAdjustment); + } + return 0; + } +} diff --git a/dmp-frontend/src/app/library/guided-tour/guided-tour.constants.ts b/dmp-frontend/src/app/library/guided-tour/guided-tour.constants.ts new file mode 100644 index 000000000..04838b521 --- /dev/null +++ b/dmp-frontend/src/app/library/guided-tour/guided-tour.constants.ts @@ -0,0 +1,74 @@ + +export interface TourStep { + /** Selector for element that will be highlighted */ + selector?: string; + /** Tour title text */ + title?: string; + /** Tour step text */ + content: string; + /** Where the tour step will appear next to the selected element */ + orientation?: Orientation | OrientationConfiguration[]; + /** Action that happens when the step is opened */ + action?: () => void; + /** Action that happens when the step is closed */ + closeAction?: () => void; + /** Skips this step, this is so you do not have create multiple tour configurations based on user settings/configuration */ + skipStep?: boolean; + /** Adds some padding for things like sticky headers when scrolling to an element */ + scrollAdjustment?: number; + /** Adds default padding around tour highlighting. Does not need to be true for highlightPadding to work */ + useHighlightPadding?: boolean; + /** Adds padding around tour highlighting in pixels, this overwrites the default for this step. Is not dependent on useHighlightPadding being true */ + highlightPadding?: number; + + /** CUSTOM ADD: True if the tour has no other step */ + isStepUnique?: boolean; + /** CUSTOM ADD: Adds offset in pixels to the calculated overlayTop */ + customTopOffset?: number; +} + +export interface GuidedTour { + /** Identifier for tour */ + tourId: string; + /** Use orb to start tour */ + useOrb?: boolean; + /** Steps fo the tour */ + steps: TourStep[]; + /** Function will be called when tour is skipped */ + skipCallback?: (stepSkippedOn: number) => void; + /** Function will be called when tour is completed */ + completeCallback?: () => void; + /** Minimum size of screen in pixels before the tour is run, if the tour is resized below this value the user will be told to resize */ + minimumScreenSize?: number; + /** Dialog shown if the window width is smaller than the defined minimum screen size. */ + resizeDialog?: { + /** Resize dialog title text */ + title?: string; + /** Resize dialog text */ + content: string; + } + /** + * Prevents the tour from advancing by clicking the backdrop. + * This should only be set if you are completely sure your tour is displaying correctly on all screen sizes otherwise a user can get stuck. + */ + preventBackdropFromAdvancing?: boolean; +} + +export interface OrientationConfiguration { + /** Where the tour step will appear next to the selected element */ + orientationDirection: Orientation; + /** When this orientation configuration starts in pixels */ + maximumSize?: number; +} + +export class Orientation { + public static readonly Bottom = 'bottom'; + public static readonly BottomLeft = 'bottom-left'; + public static readonly BottomRight = 'bottom-right'; + public static readonly Center = 'center'; + public static readonly Left = 'left'; + public static readonly Right = 'right'; + public static readonly Top = 'top'; + public static readonly TopLeft = 'top-left'; + public static readonly TopRight = 'top-right'; +} diff --git a/dmp-frontend/src/app/library/guided-tour/guided-tour.module.ts b/dmp-frontend/src/app/library/guided-tour/guided-tour.module.ts new file mode 100644 index 000000000..d51266431 --- /dev/null +++ b/dmp-frontend/src/app/library/guided-tour/guided-tour.module.ts @@ -0,0 +1,21 @@ +import { GuidedTourService } from './guided-tour.service'; +import { GuidedTourComponent } from './guided-tour.component'; +import { NgModule, ErrorHandler, ModuleWithProviders } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { WindowRefService } from './windowref.service'; + +@NgModule({ + declarations: [GuidedTourComponent], + imports: [CommonModule], + providers: [WindowRefService], + exports: [GuidedTourComponent], + entryComponents: [GuidedTourComponent], +}) +export class GuidedTourModule { + public static forRoot(): ModuleWithProviders { + return { + ngModule: GuidedTourModule, + providers: [ErrorHandler, GuidedTourService], + }; + } +} diff --git a/dmp-frontend/src/app/library/guided-tour/guided-tour.service.ts b/dmp-frontend/src/app/library/guided-tour/guided-tour.service.ts new file mode 100644 index 000000000..2823f24d0 --- /dev/null +++ b/dmp-frontend/src/app/library/guided-tour/guided-tour.service.ts @@ -0,0 +1,229 @@ +import { debounceTime } from 'rxjs/operators'; +import { ErrorHandler, Inject, Injectable } from '@angular/core'; +import { Observable, Subject, fromEvent } from 'rxjs'; +import { GuidedTour, TourStep, Orientation, OrientationConfiguration } from './guided-tour.constants'; +import { cloneDeep } from 'lodash'; +import { DOCUMENT } from "@angular/common"; +import { WindowRefService } from "./windowref.service"; + +@Injectable() +export class GuidedTourService { + public guidedTourCurrentStepStream: Observable; + public guidedTourOrbShowingStream: Observable; + + private _guidedTourCurrentStepSubject = new Subject(); + private _guidedTourOrbShowingSubject = new Subject(); + private _currentTourStepIndex = 0; + private _currentTour: GuidedTour = null; + private _onFirstStep = true; + private _onLastStep = true; + private _onResizeMessage = false; + + constructor( + public errorHandler: ErrorHandler, + private windowRef: WindowRefService, + @Inject(DOCUMENT) private dom + ) { + this.guidedTourCurrentStepStream = this._guidedTourCurrentStepSubject.asObservable(); + this.guidedTourOrbShowingStream = this._guidedTourOrbShowingSubject.asObservable(); + + fromEvent(this.windowRef.nativeWindow, 'resize').pipe(debounceTime(200)).subscribe(() => { + if (this._currentTour && this._currentTourStepIndex > -1) { + if (this._currentTour.minimumScreenSize && this._currentTour.minimumScreenSize >= this.windowRef.nativeWindow.innerWidth) { + this._onResizeMessage = true; + const dialog = this._currentTour.resizeDialog || { + title: 'Please resize', + content: 'You have resized the tour to a size that is too small to continue. Please resize the browser to a larger size to continue the tour or close the tour.' + }; + + this._guidedTourCurrentStepSubject.next(dialog); + } else { + this._onResizeMessage = false; + this._guidedTourCurrentStepSubject.next(this.getPreparedTourStep(this._currentTourStepIndex)); + } + } + }); + } + + public nextStep(): void { + if (this._currentTour.steps[this._currentTourStepIndex].closeAction) { + this._currentTour.steps[this._currentTourStepIndex].closeAction(); + } + if (this._currentTour.steps[this._currentTourStepIndex + 1]) { + this._currentTourStepIndex++; + this._setFirstAndLast(); + if (this._currentTour.steps[this._currentTourStepIndex].action) { + this._currentTour.steps[this._currentTourStepIndex].action(); + // Usually an action is opening something so we need to give it time to render. + setTimeout(() => { + if (this._checkSelectorValidity()) { + this._guidedTourCurrentStepSubject.next(this.getPreparedTourStep(this._currentTourStepIndex)); + } else { + this.nextStep(); + } + }); + } else { + if (this._checkSelectorValidity()) { + this._guidedTourCurrentStepSubject.next(this.getPreparedTourStep(this._currentTourStepIndex)); + } else { + this.nextStep(); + } + } + } else { + if (this._currentTour.completeCallback) { + this._currentTour.completeCallback(); + } + this.resetTour(); + } + } + + public backStep(): void { + if (this._currentTour.steps[this._currentTourStepIndex].closeAction) { + this._currentTour.steps[this._currentTourStepIndex].closeAction(); + } + if (this._currentTour.steps[this._currentTourStepIndex - 1]) { + this._currentTourStepIndex--; + this._setFirstAndLast(); + if (this._currentTour.steps[this._currentTourStepIndex].action) { + this._currentTour.steps[this._currentTourStepIndex].action(); + setTimeout(() => { + if (this._checkSelectorValidity()) { + this._guidedTourCurrentStepSubject.next(this.getPreparedTourStep(this._currentTourStepIndex)); + } else { + this.backStep(); + } + }); + } else { + if (this._checkSelectorValidity()) { + this._guidedTourCurrentStepSubject.next(this.getPreparedTourStep(this._currentTourStepIndex)); + } else { + this.backStep(); + } + } + } else { + this.resetTour(); + } + } + + public skipTour(): void { + if (this._currentTour.skipCallback) { + this._currentTour.skipCallback(this._currentTourStepIndex); + } + this.resetTour(); + } + + public resetTour(): void { + this.dom.body.classList.remove('tour-open'); + this._currentTour = null; + this._currentTourStepIndex = 0; + this._guidedTourCurrentStepSubject.next(null); + } + + public startTour(tour: GuidedTour): void { + this._currentTour = cloneDeep(tour); + this._currentTour.steps = this._currentTour.steps.filter(step => !step.skipStep); + this._currentTourStepIndex = 0; + this._setFirstAndLast(); + this._guidedTourOrbShowingSubject.next(this._currentTour.useOrb); + if ( + this._currentTour.steps.length > 0 + && (!this._currentTour.minimumScreenSize + || (this.windowRef.nativeWindow.innerWidth >= this._currentTour.minimumScreenSize)) + ) { + if (!this._currentTour.useOrb) { + this.dom.body.classList.add('tour-open'); + } + if (this._currentTour.steps[this._currentTourStepIndex].action) { + this._currentTour.steps[this._currentTourStepIndex].action(); + } + if (this._checkSelectorValidity()) { + this._guidedTourCurrentStepSubject.next(this.getPreparedTourStep(this._currentTourStepIndex)); + } else { + this.nextStep(); + } + } + } + + public activateOrb(): void { + this._guidedTourOrbShowingSubject.next(false); + this.dom.body.classList.add('tour-open'); + } + + private _setFirstAndLast(): void { + this._onLastStep = (this._currentTour.steps.length - 1) === this._currentTourStepIndex; + this._onFirstStep = this._currentTourStepIndex === 0; + } + + private _checkSelectorValidity(): boolean { + if (this._currentTour.steps[this._currentTourStepIndex].selector) { + const selectedElement = this.dom.querySelector(this._currentTour.steps[this._currentTourStepIndex].selector); + if (!selectedElement) { + this.errorHandler.handleError( + // If error handler is configured this should not block the browser. + new Error(`Error finding selector ${this._currentTour.steps[this._currentTourStepIndex].selector} on step ${this._currentTourStepIndex + 1} during guided tour: ${this._currentTour.tourId}`) + ); + return false; + } + } + return true; + } + + public get onLastStep(): boolean { + return this._onLastStep; + } + + public get onFirstStep(): boolean { + return this._onFirstStep; + } + + public get onResizeMessage(): boolean { + return this._onResizeMessage; + } + + public get currentTourStepDisplay(): number { + return this._currentTourStepIndex + 1; + } + + public get currentTourStepCount(): number { + return this._currentTour && this._currentTour.steps ? this._currentTour.steps.length : 0; + } + + public get preventBackdropFromAdvancing(): boolean { + return this._currentTour && this._currentTour.preventBackdropFromAdvancing; + } + + private getPreparedTourStep(index: number): TourStep { + return this.setTourOrientation(this._currentTour.steps[index]); + } + + private setTourOrientation(step: TourStep): TourStep { + const convertedStep = cloneDeep(step); + if ( + convertedStep.orientation + && !(typeof convertedStep.orientation === 'string') + && (convertedStep.orientation as OrientationConfiguration[]).length + ) { + (convertedStep.orientation as OrientationConfiguration[]).sort((a: OrientationConfiguration, b: OrientationConfiguration) => { + if (!b.maximumSize) { + return 1; + } + if (!a.maximumSize) { + return -1; + } + return b.maximumSize - a.maximumSize; + }); + + let currentOrientation: Orientation = Orientation.Top; + (convertedStep.orientation as OrientationConfiguration[]).forEach( + (orientationConfig: OrientationConfiguration) => { + if (!orientationConfig.maximumSize || this.windowRef.nativeWindow.innerWidth <= orientationConfig.maximumSize) { + currentOrientation = orientationConfig.orientationDirection; + } + } + ); + + convertedStep.orientation = currentOrientation; + } + return convertedStep; + } +} diff --git a/dmp-frontend/src/app/library/guided-tour/windowref.service.ts b/dmp-frontend/src/app/library/guided-tour/windowref.service.ts new file mode 100644 index 000000000..f5ef09652 --- /dev/null +++ b/dmp-frontend/src/app/library/guided-tour/windowref.service.ts @@ -0,0 +1,38 @@ +import { Inject, Injectable, PLATFORM_ID } from "@angular/core"; +import { isPlatformBrowser } from "@angular/common"; + +function getWindow(): any { + return window; +} + +function getMockWindow(): any { + return { + innerWidth: 0, + innerHeight: 0, + scrollY: 0, + scrollX: 0, + pageYOffset: 0, + pageXOffset: 0, + scroll: () => {}, + scrollTo: () => {}, + addEventListener: () => {}, + removeEventListener: () => {}, + } +} + +@Injectable() +export class WindowRefService { + private readonly isBrowser: boolean = false; + + get nativeWindow(): any { + if (this.isBrowser) { + return getWindow(); + } else { + return getMockWindow(); + } + } + + constructor(@Inject(PLATFORM_ID) platformId) { + this.isBrowser = isPlatformBrowser(platformId); + } +} 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 index f34dc1eee..c1f35e67a 100644 --- 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 @@ -54,7 +54,7 @@ {{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 index 55e9eae24..cdba2f1cc 100644 --- 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 @@ -3,3 +3,7 @@ width: 100%; } } + +.deleteBtn{ + margin-right:2em; +} diff --git a/dmp-frontend/src/app/ui/dashboard/dashboard.component.html b/dmp-frontend/src/app/ui/dashboard/dashboard.component.html index defc195ae..c6e33f086 100644 --- a/dmp-frontend/src/app/ui/dashboard/dashboard.component.html +++ b/dmp-frontend/src/app/ui/dashboard/dashboard.component.html @@ -1,106 +1,173 @@
-
-
-
-
- -

{{'DASHBOARD.DMP-QUESTION' | translate}}

-

{{'DASHBOARD.INFO-DMP-TEXT' | translate}}

-

- {{'DASHBOARD.NEW-QUESTION' | translate}} {{'DASHBOARD.OPEN-AIR-GUIDE' | translate}} {{'DASHBOARD.LEARN-MORE' | translate}} -

-
- - +
+
+
+
+
+ +

{{'DASHBOARD.DMP-QUESTION' | translate}}

+

{{'DASHBOARD.INFO-DMP-TEXT' | translate}}

+

+ {{'DASHBOARD.NEW-QUESTION' | translate}} {{'DASHBOARD.OPEN-AIR-GUIDE' | translate}} {{'DASHBOARD.LEARN-MORE' | translate}} +

+
+ + +
+
- +
+
+
+
+ clear +

+ {{'DASHBOARD.DMP-ABOUT-BEG' | translate}} + {{'DASHBOARD.DATASET-DESCRIPTIONS' | translate}} + {{'DASHBOARD.DMP-ABOUT-END' | translate}}

+
+ +
+
+
{{'DASHBOARD.LATEST-ACTIVITY' | translate}}
+ + + +
{{'DASHBOARD.EMPTY-LIST' | translate}}
+
+ + +
{{'DASHBOARD.EMPTY-LIST' | translate}}
+
+ + +
{{'DASHBOARD.EMPTY-LIST' | translate}}
+
+ + +
{{'DASHBOARD.EMPTY-LIST' | translate}}
+
+ +
+
+
+
+
+
{{'DASHBOARD.PERSONAL-USAGE' | translate}}
+
+ {{dashboardStatisticsData?.totalDataManagementPlanCount}}
+ {{'DASHBOARD.DMPS' | translate}} +
+ {{dashboardStatisticsData?.totalDataSetCount}}
+ {{'DASHBOARD.DATASET-DESCRIPTIONS' | translate}} +
+ {{dashboardStatisticsData?.totalGrantCount}}
+ {{'DASHBOARD.GRANTS' | translate}} +
+ {{dashboardStatisticsData?.totalOrganisationCount}}
+ {{'DASHBOARD.RELATED-ORGANISATIONS' | translate}} +
-
-
-
-
- clear -

- {{'DASHBOARD.DMP-ABOUT-BEG' | translate}} - {{'DASHBOARD.DATASET-DESCRIPTIONS' | translate}} - {{'DASHBOARD.DMP-ABOUT-END' | translate}}

-
- -
-
-
{{'DASHBOARD.LATEST-ACTIVITY' | translate}}
- - - -
{{'DASHBOARD.EMPTY-LIST' | translate}}
-
- - -
{{'DASHBOARD.EMPTY-LIST' | translate}}
-
- - -
{{'DASHBOARD.EMPTY-LIST' | translate}}
-
- - -
{{'DASHBOARD.EMPTY-LIST' | translate}}
-
- -
-
-
-
-
-
{{'DASHBOARD.PERSONAL-USAGE' | translate}}
-
- {{dashboardStatisticsData?.totalDataManagementPlanCount}}
- {{'DASHBOARD.DMPS' | translate}} -
- {{dashboardStatisticsData?.totalDataSetCount}}
- {{'DASHBOARD.DATASET-DESCRIPTIONS' | translate}} -
- {{dashboardStatisticsData?.totalGrantCount}}
- {{'DASHBOARD.GRANTS' | translate}} -
- {{dashboardStatisticsData?.totalOrganisationCount}}
- {{'DASHBOARD.RELATED-ORGANISATIONS' | translate}} +
+ + +
+
+
+
+

{{ 'ABOUT.WELCOME' | translate }}

+

{{ 'ABOUT.WELCOME-MESSAGE' | translate }}

+
+
+
+
+
+
+
+ clear +
+

{{'DASHBOARD.TITLE' | translate}}

+

{{'DASHBOARD.INFO-TEXT' | translate}}

+
+
+
+
{{'DASHBOARD.LATEST-ACTIVITY' | translate}}
+ + + +
{{'DASHBOARD.EMPTY-LIST' | translate}}
+
+ + +
{{'DASHBOARD.EMPTY-LIST' | translate}}
+
+ + +
{{'DASHBOARD.EMPTY-LIST' | translate}}
+ +
+
+
+
+
+ +
+
{{'DASHBOARD.PERSONAL-USAGE' | translate}}
+
+ {{dashboardStatisticsData?.totalDataManagementPlanCount}}
+ {{'DASHBOARD.PUBLIC-DMPS' | translate}} +
+ {{dashboardStatisticsData?.totalDataSetCount}}
+ {{'DASHBOARD.PUBLIC-DATASETS' | translate}} +
+ {{dashboardStatisticsData?.totalGrantCount}}
+ {{'DASHBOARD.GRANTS' | translate}} +
+ {{dashboardStatisticsData?.totalOrganisationCount}}
+ {{'DASHBOARD.RELATED-ORGANISATIONS' | translate}} +
+
+
-
- - - - - {{'DMP-LISTING.SORT-BY' | translate}}: - {{enumUtils.toRecentActivityOrderString(order.MODIFIED)}} + {{enumUtils.toRecentActivityOrderString(order.MODIFIED)}} + {{enumUtils.toRecentActivityOrderString(order.PUBLISHED)}} {{enumUtils.toRecentActivityOrderString(order.LABEL)}} - {{enumUtils.toRecentActivityOrderString(order.STATUS)}} + {{enumUtils.toRecentActivityOrderString(order.STATUS)}} {{enumUtils.toRecentActivityOrderString(order.CREATED)}} @@ -22,10 +26,12 @@
- {{'GENERAL.ACTIONS.SHOW-MORE' | translate}} + + {{'GENERAL.ACTIONS.SHOW-MORE' | translate}}
- + +
{{'DATASET-LISTING.DATASET-DESCRIPTION' | translate}}
-
{{'DATASET-LISTING.STATES.EDITED' | translate}}: {{activity.modified | date:"longDate"}}
+
{{'DATASET-LISTING.STATES.EDITED' | translate}}: {{activity.modified | date:"longDate"}}
+
{{'DATASET-LISTING.STATES.PUBLISHED' | translate}}: {{activity.publishedAt | date:"longDate"}}
-
{{'DATASET-LISTING.DATASET-DESCRIPTION' | translate}}: {{activity.title}}
+
{{activity.title}}
{{ roleDisplay(activity.users) }} . diff --git a/dmp-frontend/src/app/ui/dashboard/recent-edited-activity/recent-edited-activity.component.ts b/dmp-frontend/src/app/ui/dashboard/recent-edited-activity/recent-edited-activity.component.ts index 6192039f0..45133875e 100644 --- a/dmp-frontend/src/app/ui/dashboard/recent-edited-activity/recent-edited-activity.component.ts +++ b/dmp-frontend/src/app/ui/dashboard/recent-edited-activity/recent-edited-activity.component.ts @@ -32,6 +32,7 @@ import { DatasetCopyDialogueComponent } from '@app/ui/dataset/dataset-wizard/dat import { RecentActivityOrder } from '@app/core/common/enum/recent-activity-order'; import { Location } from '@angular/common'; import { LockService } from '@app/core/services/lock/lock.service'; +import { DatasetUrlListing } from '@app/core/model/dataset/dataset-url-listing'; @Component({ selector: 'app-recent-edited-activity', @@ -54,6 +55,7 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn like: new FormControl(), order: new FormControl() }); + publicMode = false; order = RecentActivityOrder; @@ -76,8 +78,7 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn ngOnInit() { if (this.isAuthenticated()) { this.formGroup.get('order').setValue(this.order.MODIFIED); - const fields: Array = [(this.formGroup.get('order').value === 'status' ? '+' : "-") + this.formGroup.get('order').value]; - // const fields: Array = ["-modified"]; + const fields: Array = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value]; const allDataTableRequest: DataTableMultiTypeRequest = new DataTableMultiTypeRequest(0, 0, 5, { fields: fields }); allDataTableRequest.criteria = new RecentActivityCriteria(); allDataTableRequest.criteria.like = ""; @@ -101,10 +102,33 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn this.formGroup.get('order').valueChanges .pipe(takeUntil(this._destroyed)) .subscribe(x => this.refresh()); + } else { + this.publicMode = true; + this.formGroup.get('order').setValue(this.order.PUBLISHED); + const allDataTableRequest = this.setPublicDataTableRequest(); + this.dashboardService + .getRecentActivity(allDataTableRequest) + .subscribe(response => { + this.allRecentActivities = response; + this.allRecentActivities.forEach(recentActivity => { + if (recentActivity.type === RecentActivityType.Dataset) { + this.datasetOffset = this.datasetOffset + 1; + } else if (recentActivity.type === RecentActivityType.Dmp) { + this.dmpOffset = this.dmpOffset + 1; + } + }); + this.totalCountRecentEdited.emit(this.allRecentActivities.length); + }); + this.formGroup.get('like').valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => this.refresh()); + this.formGroup.get('order').valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => this.refresh()); } } - getDatasets(activity: RecentDmpModel): RecentDatasetModel[] { + getDatasets(activity: RecentDmpModel): DatasetUrlListing[] { return activity.datasets; } @@ -120,6 +144,17 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn return activity.dmpId; } + private setPublicDataTableRequest(fields?: Array): DataTableMultiTypeRequest { + const criteria = new RecentActivityCriteria(); + criteria.like = this.formGroup.get("like").value ? this.formGroup.get("like").value : ""; + if (!fields) { + fields = new Array('-publishedAt'); + } + const dataTableRequest: DataTableMultiTypeRequest = new DataTableMultiTypeRequest(this.dmpOffset, this.datasetOffset, this.pageSize, { fields: fields }); + dataTableRequest.criteria = criteria; + return dataTableRequest; + } + // getPublic(activity: RecentDmpModel): boolean { // return activity.isPublic; // } @@ -229,11 +264,19 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn return; } case RecentActivityType.Dataset: { - this.router.navigate(["datasets/edit/" + id]); + if (this.isAuthenticated()) { + this.router.navigate(['../datasets/overview/' + id]); + } else { + this.router.navigate(['../explore/publicOverview', id]); + } return; } case RecentActivityType.Dmp: { - this.router.navigate(["plans/overview/" + id]); + if (this.isAuthenticated()) { + this.router.navigate(['../plans/overview/' + id]); + } else { + this.router.navigate(['../explore-plans/publicOverview', id]); + } return; } default: @@ -241,9 +284,29 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn } } - // navigateToUrl() { - // this.router.navigate(["plans/"]); - // } + navigateToUrl(id: string, type: RecentActivityType): string[] { + switch (type) { + case RecentActivityType.Grant: { + return ["grants/edit/" + id]; + } + case RecentActivityType.Dataset: { + if (this.isAuthenticated()) { + return ['../datasets/overview/' + id]; + } else { + return ['../explore/publicOverview', id]; + } + } + case RecentActivityType.Dmp: { + if (this.isAuthenticated()) { + return ['../plans/overview/' + id]; + } else { + return ['../explore-plans/publicOverview', id]; + } + } + default: + throw new Error("Unsupported Activity Type "); + } + } roleDisplay(value: any) { const principal: Principal = this.authentication.current(); @@ -458,7 +521,7 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn } refresh(): void { - const fields: Array = [(this.formGroup.get('order').value === 'status' ? '+' : "-") + this.formGroup.get('order').value]; + const fields: Array = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value]; // const fields: Array = ["-modified"]; this.startIndex = 0; const allDataTableRequest: DataTableMultiTypeRequest = new DataTableMultiTypeRequest(0, 0, this.pageSize, { fields: fields }); @@ -481,7 +544,7 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn } public loadMore() { - const fields: Array = [(this.formGroup.get('order').value === 'status' ? '+' : "-") + this.formGroup.get('order').value]; + const fields: Array = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value]; // const fields: Array = ["-modified"]; const request = new DataTableMultiTypeRequest(this.dmpOffset, this.datasetOffset, this.pageSize, { fields: fields }); request.criteria = new RecentActivityCriteria(); @@ -532,7 +595,7 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn index2++; } } else if (order === 'label') { - if (!isArr1Depleted && (isArr2Depleted || (arr1[index1].title < arr2[index2].title))) { + if (!isArr1Depleted && (isArr2Depleted || (arr1[index1].title.localeCompare(arr2[index2].title)))) { merged[current] = arr1[index1]; index1++; } else { @@ -547,6 +610,14 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn merged[current] = arr2[index2]; index2++; } + } else if (order === "publishedAt") { + if (!isArr1Depleted && (isArr2Depleted || (new Date(arr1[index1].publishedAt) > new Date(arr2[index2].publishedAt)))) { + merged[current] = arr1[index1]; + index1++; + } else { + merged[current] = arr2[index2]; + index2++; + } } current++; } diff --git a/dmp-frontend/src/app/ui/dashboard/recent-edited-dataset-activity/recent-edited-dataset-activity.component.html b/dmp-frontend/src/app/ui/dashboard/recent-edited-dataset-activity/recent-edited-dataset-activity.component.html index 0d8902156..725a12afb 100644 --- a/dmp-frontend/src/app/ui/dashboard/recent-edited-dataset-activity/recent-edited-dataset-activity.component.html +++ b/dmp-frontend/src/app/ui/dashboard/recent-edited-dataset-activity/recent-edited-dataset-activity.component.html @@ -4,9 +4,10 @@ {{'DMP-LISTING.SORT-BY' | translate}}: - {{enumUtils.toRecentActivityOrderString(order.MODIFIED)}} + {{enumUtils.toRecentActivityOrderString(order.MODIFIED)}} + {{enumUtils.toRecentActivityOrderString(order.DATASETPUBLISHED)}} {{enumUtils.toRecentActivityOrderString(order.LABEL)}} - {{enumUtils.toRecentActivityOrderString(order.STATUS)}} + {{enumUtils.toRecentActivityOrderString(order.STATUS)}} {{enumUtils.toRecentActivityOrderString(order.CREATED)}} @@ -21,12 +22,13 @@
- +
{{'DATASET-LISTING.DATASET-DESCRIPTION' | translate}}
-
{{'DATASET-LISTING.STATES.EDITED' | translate}}: {{activity.modified | date:"longDate"}}
+
{{'DATASET-LISTING.STATES.EDITED' | translate}}: {{activity.modified | date:"longDate"}}
+
{{'DATASET-LISTING.STATES.PUBLISHED' | translate}}: {{activity.dmpPublishedAt | date:"longDate"}}
-
{{'DATASET-LISTING.DATASET-DESCRIPTION' | translate}}: {{activity.label}}
+
{{activity.label}}
{{ roleDisplay(activity.users) }} . diff --git a/dmp-frontend/src/app/ui/dashboard/recent-edited-dataset-activity/recent-edited-dataset-activity.component.ts b/dmp-frontend/src/app/ui/dashboard/recent-edited-dataset-activity/recent-edited-dataset-activity.component.ts index c6406a645..7c008836a 100644 --- a/dmp-frontend/src/app/ui/dashboard/recent-edited-dataset-activity/recent-edited-dataset-activity.component.ts +++ b/dmp-frontend/src/app/ui/dashboard/recent-edited-dataset-activity/recent-edited-dataset-activity.component.ts @@ -43,7 +43,7 @@ export class RecentEditedDatasetActivityComponent extends BaseComponent implemen like: new FormControl(), order: new FormControl() }); - // publicMode = false; + publicMode = false; order = RecentActivityOrder; @@ -66,7 +66,7 @@ export class RecentEditedDatasetActivityComponent extends BaseComponent implemen if (this.isAuthenticated()) { // const fields: Array = ["-modified"]; this.formGroup.get('order').setValue(this.order.MODIFIED); - const fields: Array = [(this.formGroup.get('order').value === 'status' ? '+' : "-") + this.formGroup.get('order').value]; + const fields: Array = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value]; const datasetDataTableRequest: DataTableRequest = new DataTableRequest(0, this.pageSize, { fields: fields }); datasetDataTableRequest.criteria = new DatasetCriteria(); datasetDataTableRequest.criteria.like = ""; @@ -77,6 +77,21 @@ export class RecentEditedDatasetActivityComponent extends BaseComponent implemen this.totalCount = response.totalCount; this.totalCountDatasets.emit(this.datasetActivities.length); }); + this.formGroup.get('like').valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => this.refresh()); + this.formGroup.get('order').valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => this.refresh()); + } else { + this.publicMode = true; + this.formGroup.get('order').setValue(this.order.DATASETPUBLISHED); + const dataTableRequest = this.setPublicDataTableRequest(); + this.datasetService.getPaged(dataTableRequest).pipe(takeUntil(this._destroyed)).subscribe(response => { + this.datasetActivities = response.data; + this.totalCount = response.totalCount; + this.totalCountDatasets.emit(this.datasetActivities.length); + }); this.formGroup.get('like').valueChanges .pipe(takeUntil(this._destroyed)) .subscribe(x => this.refresh()); @@ -86,13 +101,28 @@ export class RecentEditedDatasetActivityComponent extends BaseComponent implemen } } + setPublicDataTableRequest(fields?: Array): DataTableRequest { + const datasetCriteria = new DatasetCriteria(); + datasetCriteria.allVersions = false; + datasetCriteria.isPublic = true; + datasetCriteria.like = this.formGroup.get("like").value ? this.formGroup.get("like").value : ""; + if (!fields) { + fields = new Array('-dmp:publishedAt|join|'); + } + const dataTableRequest: DataTableRequest = new DataTableRequest(this.startIndex, this.pageSize, { fields: fields }); + dataTableRequest.criteria = datasetCriteria; + return dataTableRequest; + } + refresh(): void { - // const fields: Array = ["-modified"]; - const fields: Array = [(this.formGroup.get('order').value === 'status' ? '+' : "-") + this.formGroup.get('order').value]; this.startIndex = 0; - const datasetDataTableRequest: DataTableRequest = new DataTableRequest(0, this.pageSize, { fields: fields }); - datasetDataTableRequest.criteria = new DatasetCriteria(); - datasetDataTableRequest.criteria.like = this.formGroup.get("like").value; + + const fields: Array = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value]; + const datasetDataTableRequest = this.isAuthenticated() ? new DataTableRequest(this.startIndex, this.pageSize, { fields: fields }) : this.setPublicDataTableRequest(fields); + if (this.isAuthenticated()) { + datasetDataTableRequest.criteria = new DatasetCriteria(); + datasetDataTableRequest.criteria.like = this.formGroup.get("like").value ? this.formGroup.get("like").value : ""; + } this.datasetService .getPaged(datasetDataTableRequest) .subscribe(response => { @@ -104,12 +134,13 @@ export class RecentEditedDatasetActivityComponent extends BaseComponent implemen public loadMore() { this.startIndex = this.startIndex + this.pageSize; - // const fields: Array = ["-modified"]; - const fields: Array = [(this.formGroup.get('order').value === 'status' ? '+' : "-") + this.formGroup.get('order').value]; - const request = new DataTableRequest(this.startIndex, this.pageSize, { fields: fields }); - request.criteria = new DatasetCriteria(); - request.criteria.like = this.formGroup.get("like").value ? this.formGroup.get("like").value : ""; + const fields: Array = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value]; + const request = this.isAuthenticated() ? new DataTableRequest(this.startIndex, this.pageSize, { fields: fields }) : this.setPublicDataTableRequest(fields); + if (this.isAuthenticated()) { + request.criteria = new DatasetCriteria(); + request.criteria.like = this.formGroup.get("like").value ? this.formGroup.get("like").value : ""; + } this.datasetService.getPaged(request).pipe(takeUntil(this._destroyed)).subscribe(result => { if (!result) { return []; } @@ -128,6 +159,14 @@ export class RecentEditedDatasetActivityComponent extends BaseComponent implemen if (principal) return principal.id === activity.users.find(x => x.role === Role.Owner).id; } + goToOverview(id: string): string[] { + if (this.isAuthenticated()) { + return ['../datasets/overview/' + id]; + } else { + return ['../explore/publicOverview', id]; + } + } + roleDisplay(value: any) { const principal: Principal = this.authentication.current(); let role: number; @@ -168,8 +207,8 @@ export class RecentEditedDatasetActivityComponent extends BaseComponent implemen .subscribe(result => { if (result && result.datasetProfileExist) { const newDmpId = result.formControl.value.id; - let url = this.router.createUrlTree(['/datasets/copy/', result.datasetId, { newDmpId: newDmpId } ]); - window.open(url.toString(), '_blank'); + let url = this.router.createUrlTree(['/datasets/copy/', result.datasetId, { newDmpId: newDmpId }]); + window.open(url.toString(), '_blank'); } }); } @@ -345,10 +384,8 @@ export class RecentEditedDatasetActivityComponent extends BaseComponent implemen let current = 0; while (current < (arr1.length + arr2.length)) { - let isArr1Depleted = index1 >= arr1.length; let isArr2Depleted = index2 >= arr2.length; - if (order === 'modified') { if (!isArr1Depleted && (isArr2Depleted || (new Date(arr1[index1].modified) > new Date(arr2[index2].modified)))) { merged[current] = arr1[index1]; @@ -366,7 +403,7 @@ export class RecentEditedDatasetActivityComponent extends BaseComponent implemen index2++; } } else if (order === 'label') { - if (!isArr1Depleted && (isArr2Depleted || (arr1[index1].label < arr2[index2].label))) { + if (!isArr1Depleted && (isArr2Depleted || (arr1[index1].label.localeCompare(arr2[index2].label)))) { merged[current] = arr1[index1]; index1++; } else { @@ -381,6 +418,14 @@ export class RecentEditedDatasetActivityComponent extends BaseComponent implemen merged[current] = arr2[index2]; index2++; } + } else if (order === 'dmp:publishedAt|join|') { + if (!isArr1Depleted && (isArr2Depleted || (new Date(arr1[index1].dmpPublishedAt) > new Date(arr2[index2].dmpPublishedAt)))) { + merged[current] = arr1[index1]; + index1++; + } else { + merged[current] = arr2[index2]; + index2++; + } } current++; } diff --git a/dmp-frontend/src/app/ui/dashboard/recent-edited-dmp-activity/recent-edited-dmp-activity.component.html b/dmp-frontend/src/app/ui/dashboard/recent-edited-dmp-activity/recent-edited-dmp-activity.component.html index 77a0cfb0e..72ef1cadf 100644 --- a/dmp-frontend/src/app/ui/dashboard/recent-edited-dmp-activity/recent-edited-dmp-activity.component.html +++ b/dmp-frontend/src/app/ui/dashboard/recent-edited-dmp-activity/recent-edited-dmp-activity.component.html @@ -4,9 +4,10 @@ {{'DMP-LISTING.SORT-BY' | translate}}: - {{enumUtils.toRecentActivityOrderString(order.MODIFIED)}} + {{enumUtils.toRecentActivityOrderString(order.MODIFIED)}} + {{enumUtils.toRecentActivityOrderString(order.PUBLISHED)}} {{enumUtils.toRecentActivityOrderString(order.LABEL)}} - {{enumUtils.toRecentActivityOrderString(order.STATUS)}} + {{enumUtils.toRecentActivityOrderString(order.STATUS)}} {{enumUtils.toRecentActivityOrderString(order.CREATED)}} @@ -21,10 +22,11 @@
- {{'GENERAL.ACTIONS.SHOW-MORE' | translate}} + {{'GENERAL.ACTIONS.SHOW-MORE' | translate}}
open_in_new{{'DMP-LISTING.ACTIONS.EXPORT' | translate}} diff --git a/dmp-frontend/src/app/ui/dashboard/recent-edited-dmp-activity/recent-edited-dmp-activity.component.ts b/dmp-frontend/src/app/ui/dashboard/recent-edited-dmp-activity/recent-edited-dmp-activity.component.ts index 670df71fa..952686fba 100644 --- a/dmp-frontend/src/app/ui/dashboard/recent-edited-dmp-activity/recent-edited-dmp-activity.component.ts +++ b/dmp-frontend/src/app/ui/dashboard/recent-edited-dmp-activity/recent-edited-dmp-activity.component.ts @@ -24,6 +24,7 @@ import { FormBuilder, FormControl } from '@angular/forms'; import { RecentActivityOrder } from '@app/core/common/enum/recent-activity-order'; import { Location } from '@angular/common'; import { LockService } from '@app/core/services/lock/lock.service'; +import { ExploreDmpCriteriaModel } from '@app/core/query/explore-dmp/explore-dmp-criteria'; @Component({ selector: 'app-recent-edited-dmp-activity', @@ -46,6 +47,7 @@ export class RecentEditedDmpActivityComponent extends BaseComponent implements O like: new FormControl(), order: new FormControl() }); + publicMode = false; order = RecentActivityOrder; @@ -68,7 +70,7 @@ export class RecentEditedDmpActivityComponent extends BaseComponent implements O if (this.isAuthenticated()) { // const fields: Array = ["-modified"]; this.formGroup.get('order').setValue(this.order.MODIFIED); - const fields: Array = [(this.formGroup.get('order').value === 'status' ? '+' : "-") + this.formGroup.get('order').value]; + const fields: Array = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value]; const dmpDataTableRequest: DataTableRequest = new DataTableRequest(0, 5, { fields: fields }); dmpDataTableRequest.criteria = new DmpCriteria(); dmpDataTableRequest.criteria.like = ""; @@ -94,7 +96,6 @@ export class RecentEditedDmpActivityComponent extends BaseComponent implements O this.formGroup.get('order').valueChanges .pipe(takeUntil(this._destroyed)) .subscribe(x => this.refresh()); - // const datasetDataTableRequest: DataTableRequest = new DataTableRequest(0, 5, { fields: fields }); // datasetDataTableRequest.criteria = new DatasetCriteria(); // datasetDataTableRequest.criteria.like = ""; @@ -110,6 +111,22 @@ export class RecentEditedDmpActivityComponent extends BaseComponent implements O // this.allRecentActivities.push(recentActivity) // }) // }); + } else { + this.publicMode = true; + this.formGroup.get('order').setValue(this.order.PUBLISHED); + const dataTableRequest = this.setPublicDataTableRequest(); + this.dmpService.getPaged(dataTableRequest, "listing").pipe(takeUntil(this._destroyed)).subscribe(response => { + if (!response) { return []; } + this.dmpActivities = response.data; + this.totalCount = response.totalCount; + this.totalCountDmps.emit(this.dmpActivities.length); + }); + this.formGroup.get('like').valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => this.refresh()); + this.formGroup.get('order').valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => this.refresh()); } } @@ -117,6 +134,20 @@ export class RecentEditedDmpActivityComponent extends BaseComponent implements O return !!this.authentication.current(); } + private setPublicDataTableRequest(fields?: Array): DataTableRequest { + const dmpCriteria = new DmpCriteria(); + dmpCriteria.allVersions = false; + dmpCriteria.isPublic = true; + dmpCriteria.onlyPublic = true; + dmpCriteria.like = this.formGroup.get("like").value ? this.formGroup.get("like").value : ""; + if (!fields) { + fields = new Array('-publishedAt'); + } + const dataTableRequest: DataTableRequest = new DataTableRequest(this.startIndex, this.pageSize, { fields: fields }); + dataTableRequest.criteria = dmpCriteria; + return dataTableRequest; + } + isUserOwner(activity: DmpListingModel): boolean { const principal: Principal = this.authentication.current(); if (principal) return principal.id === activity.users.find(x => x.role === Role.Owner).id; @@ -212,28 +243,21 @@ export class RecentEditedDmpActivityComponent extends BaseComponent implements O this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error); } - redirect(id: string, type: RecentActivityType) { - switch (type) { - case RecentActivityType.Grant: { - this.router.navigate(["grants/edit/" + id]); - return; - } - case RecentActivityType.Dataset: { - this.router.navigate(["datasets/edit/" + id]); - return; - } - case RecentActivityType.Dmp: { - this.router.navigate(["plans/overview/" + id]); - return; - } - default: - throw new Error("Unsupported Activity Type "); + redirect(id: string) { + if (this.isAuthenticated()) { + this.router.navigate(['../plans/overview/' + id]); + } else { + this.router.navigate(['../explore-plans/publicOverview', id]); } } - // navigateToUrl() { - // this.router.navigate(["plans/"]); - // } + navigateToUrl(id: string): string[] { + if (this.isAuthenticated()) { + return ['../plans/overview/' + id]; + } else { + return ['../explore-plans/publicOverview', id]; + } + } roleDisplay(value: any) { const principal: Principal = this.authentication.current(); @@ -344,12 +368,13 @@ export class RecentEditedDmpActivityComponent extends BaseComponent implements O } refresh(): void { - // const fields: Array = ["-modified"]; - const fields: Array = [(this.formGroup.get('order').value === 'status' ? '+' : "-") + this.formGroup.get('order').value]; + const fields: Array = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value]; this.startIndex = 0; - const dmpDataTableRequest: DataTableRequest = new DataTableRequest(this.startIndex, this.pageSize, { fields: fields }); - dmpDataTableRequest.criteria = new DmpCriteria(); - dmpDataTableRequest.criteria.like = this.formGroup.get("like").value; + const dmpDataTableRequest = this.isAuthenticated() ? new DataTableRequest(this.startIndex, this.pageSize, { fields: fields }) : this.setPublicDataTableRequest(fields); + if (this.isAuthenticated()) { + dmpDataTableRequest.criteria = new DmpCriteria(); + dmpDataTableRequest.criteria.like = this.formGroup.get("like").value ? this.formGroup.get("like").value : ""; + } this.dmpService .getPaged(dmpDataTableRequest, "listing") .subscribe(response => { @@ -361,12 +386,13 @@ export class RecentEditedDmpActivityComponent extends BaseComponent implements O public loadMore() { this.startIndex = this.startIndex + this.pageSize; - // const fields: Array = ["-modified"]; - const fields: Array = [(this.formGroup.get('order').value === 'status' ? '+' : "-") + this.formGroup.get('order').value]; - const request = new DataTableRequest(this.startIndex, this.pageSize, { fields: fields }); - request.criteria = new DmpCriteria(); - request.criteria.like = this.formGroup.get("like").value ? this.formGroup.get("like").value : ""; + const fields: Array = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value]; + const request = this.isAuthenticated() ? new DataTableRequest(this.startIndex, this.pageSize, { fields: fields }) : this.setPublicDataTableRequest(fields); + if (this.isAuthenticated()) { + request.criteria = new DmpCriteria(); + request.criteria.like = this.formGroup.get("like").value ? this.formGroup.get("like").value : ""; + } this.dmpService.getPaged(request, "listing").pipe(takeUntil(this._destroyed)).subscribe(result => { if (!result) { return []; } @@ -405,7 +431,7 @@ export class RecentEditedDmpActivityComponent extends BaseComponent implements O index2++; } } else if (order === 'label') { - if (!isArr1Depleted && (isArr2Depleted || (arr1[index1].label < arr2[index2].label))) { + if (!isArr1Depleted && (isArr2Depleted || (arr1[index1].label.localeCompare(arr2[index2].label)))) { merged[current] = arr1[index1]; index1++; } else { @@ -420,6 +446,14 @@ export class RecentEditedDmpActivityComponent extends BaseComponent implements O merged[current] = arr2[index2]; index2++; } + } else if (order === "publishedAt") { + if (!isArr1Depleted && (isArr2Depleted || (new Date(arr1[index1].publishedAt) > new Date(arr2[index2].publishedAt)))) { + merged[current] = arr1[index1]; + index1++; + } else { + merged[current] = arr2[index2]; + index2++; + } } current++; } diff --git a/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria-dialogue/dataset-criteria-dialog.component.scss b/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria-dialogue/dataset-criteria-dialog.component.scss new file mode 100644 index 000000000..1d5108761 --- /dev/null +++ b/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria-dialogue/dataset-criteria-dialog.component.scss @@ -0,0 +1,8 @@ +::ng-deep .mat-form-field-wrapper { + background-color: white !important; + padding-bottom: 0 !important; +} + +::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix { + padding: 0.3rem 0rem 0.6rem 0rem !important; +} diff --git a/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria-dialogue/dataset-criteria-dialog.component.ts b/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria-dialogue/dataset-criteria-dialog.component.ts index 29f9f212b..13d01f247 100644 --- a/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria-dialogue/dataset-criteria-dialog.component.ts +++ b/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria-dialogue/dataset-criteria-dialog.component.ts @@ -7,6 +7,7 @@ import { DatasetCriteria } from '@app/core/query/dataset/dataset-criteria'; @Component({ selector: 'dataset-criteria-dialog-component', templateUrl: './dataset-criteria-dialog.component.html', + styleUrls: ['./dataset-criteria-dialog.component.scss'] }) export class DatasetCriteriaDialogComponent implements OnInit { diff --git a/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria.component.scss b/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria.component.scss index 9154b4ca5..e94acdcec 100644 --- a/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria.component.scss +++ b/dmp-frontend/src/app/ui/dataset/listing/criteria/dataset-criteria.component.scss @@ -21,7 +21,8 @@ .filters-title { width: 93px; - color: #089dbb; + // color: #089dbb; + color: #23bcba; background-color: white; padding: 0px 20px; margin-top: -10px; @@ -32,3 +33,12 @@ .style-icon { color: #adadad; } + +::ng-deep .search-form .mat-form-field-wrapper { + background-color: white !important; + padding-bottom: 0 !important; +} + +::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix { + padding: 0.3rem 0rem 0.6rem 0rem !important; +} 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 index 473a0d08e..afae52531 100644 --- a/dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.html +++ b/dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.html @@ -27,20 +27,28 @@ {{'DMP-LISTING.SORT-BY' | translate}}: - {{enumUtils.toRecentActivityOrderString(order.MODIFIED)}} + {{enumUtils.toRecentActivityOrderString(order.MODIFIED)}} + {{enumUtils.toRecentActivityOrderString(order.DATASETPUBLISHED)}} {{enumUtils.toRecentActivityOrderString(order.LABEL)}} - {{enumUtils.toRecentActivityOrderString(order.STATUS)}} + {{enumUtils.toRecentActivityOrderString(order.STATUS)}} {{enumUtils.toRecentActivityOrderString(order.CREATED)}} - - - search - - {{formGroup.get('like').getError('backendError').message}} - - +
+ +
+ {{ 'GENERAL.ACTIONS.TAKE-A-TOUR'| translate }} +
+ + + + search + + {{formGroup.get('like').getError('backendError').message}} + + +
diff --git a/dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.scss b/dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.scss index 656256f4d..0f3d9beb9 100644 --- a/dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.scss +++ b/dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.scss @@ -137,6 +137,19 @@ height: 45px; } +.center-content { + width: 100%; + min-width: 10rem; + margin: auto; + padding: 0 15px; + text-align: right; + font-size: 0.875rem; + font-weight: 600; + letter-spacing: 0.02rem; + color: #2D72D6; + cursor: pointer; +} + .search-form { // font-size: 12px; text-align: left; 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 index cbd17941c..0c34377c0 100644 --- a/dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.ts +++ b/dmp-frontend/src/app/ui/dataset/listing/dataset-listing.component.ts @@ -24,6 +24,8 @@ import { MatDialog } from '@angular/material'; import { FormGroup, FormBuilder, FormControl } from '@angular/forms'; import { RecentActivityOrder } from '@app/core/common/enum/recent-activity-order'; import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { GuidedTourService } from '@app/library/guided-tour/guided-tour.service'; +import { GuidedTour, Orientation } from '@app/library/guided-tour/guided-tour.constants'; @Component({ selector: 'app-dataset-listing-component', @@ -59,6 +61,8 @@ export class DatasetListingComponent extends BaseComponent implements OnInit, IB scrollbar: boolean; order = RecentActivityOrder; + dmpText: string; + datasetText: string; constructor( private datasetService: DatasetService, @@ -68,14 +72,20 @@ export class DatasetListingComponent extends BaseComponent implements OnInit, IB private dmpService: DmpService, private language: TranslateService, private authService: AuthService, - public enumUtils: EnumUtils + public enumUtils: EnumUtils, + private authentication: AuthService, + private guidedTourService: GuidedTourService ) { super(); } ngOnInit() { this.isPublic = this.router.url === '/explore'; - this.formGroup.get('order').setValue(this.order.MODIFIED); + if (this.isPublic) { + this.formGroup.get('order').setValue(this.order.DATASETPUBLISHED); + } else { + this.formGroup.get('order').setValue(this.order.MODIFIED); + } if (!this.isPublic && isNullOrUndefined(this.authService.current())) { this.router.navigateByUrl("/explore"); } @@ -133,6 +143,29 @@ export class DatasetListingComponent extends BaseComponent implements OnInit, IB this.scrollbar = this.hasScrollbar(); } + public dashboardTour: GuidedTour = { + tourId: 'dmp-dataset-tour', + useOrb: true, + steps: [ + { + selector: '.dmp-tour', + content: 'Step 1', + orientation: Orientation.Right, + isStepUnique: false + }, + { + selector: '.dataset-tour', + content: 'Step 2', + orientation: Orientation.Right, + isStepUnique: false + } + ] + }; + + public isAuthenticated(): boolean { + return !(!this.authentication.current()); + } + controlModified(): void { // this.clearErrorModel(); // if (this.refreshCallback != null && @@ -152,7 +185,7 @@ export class DatasetListingComponent extends BaseComponent implements OnInit, IB // let fields: Array = new Array(); // fields.push('-modified'); //if (this.sort && this.sort.active) { fields = this.sort.direction === 'asc' ? ['+' + this.sort.active] : ['-' + this.sort.active]; } - const fields: Array = [(this.formGroup.get('order').value === 'status' ? '+' : "-") + this.formGroup.get('order').value]; + const fields: Array = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value]; const request = new DataTableRequest(this.startIndex, this.pageSize, { fields: fields }); this.criteria.isPublic = this.isPublic; request.criteria = this.criteria; @@ -168,7 +201,7 @@ export class DatasetListingComponent extends BaseComponent implements OnInit, IB public loadMore() { this.startIndex = this.startIndex + this.pageSize; // const fields: Array = ["-modified"]; - const fields: Array = [(this.formGroup.get('order').value === 'status' ? '+' : "-") + this.formGroup.get('order').value]; + const fields: Array = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value]; const request = new DataTableRequest(this.startIndex, this.pageSize, { fields: fields }); this.criteria.isPublic = this.isPublic; request.criteria = this.criteria; @@ -306,7 +339,7 @@ export class DatasetListingComponent extends BaseComponent implements OnInit, IB index2++; } } else if (order === 'label') { - if (!isArr1Depleted && (isArr2Depleted || (arr1[index1].label < arr2[index2].label))) { + if (!isArr1Depleted && (isArr2Depleted || (arr1[index1].label.localeCompare(arr2[index2].label)))) { merged[current] = arr1[index1]; index1++; } else { @@ -321,12 +354,42 @@ export class DatasetListingComponent extends BaseComponent implements OnInit, IB merged[current] = arr2[index2]; index2++; } + } else if (order === 'dmp:publishedAt|join|') { + if (!isArr1Depleted && (isArr2Depleted || (new Date(arr1[index1].dmpPublishedAt) > new Date(arr2[index2].dmpPublishedAt)))) { + merged[current] = arr1[index1]; + index1++; + } else { + merged[current] = arr2[index2]; + index2++; + } } current++; } return merged; } + public setDashboardTourDmpText(): void { + this.dmpText = this.language.instant('DMP-LISTING.TEXT-INFO') + '\n\n' + + this.language.instant('DMP-LISTING.TEXT-INFO-QUESTION') + ' ' + + this.language.instant('DMP-LISTING.LINK-ZENODO') + ' ' + + this.language.instant('DMP-LISTING.GET-IDEA'); + this.dashboardTour.steps[0].title = this.dmpText; + } + + public setDashboardTourDatasetText(): void { + this.datasetText = this.language.instant('DATASET-LISTING.TEXT-INFO') + + this.language.instant('DATASET-LISTING.LINK-PUBLIC-DATASETS') + ' ' + + this.language.instant('DATASET-LISTING.TEXT-INFO-REST') + '\n\n' + + this.language.instant('DATASET-LISTING.TEXT-INFO-PAR'); + this.dashboardTour.steps[1].title = this.datasetText; + } + + public restartTour(): void { + this.setDashboardTourDmpText(); + this.setDashboardTourDatasetText(); + this.guidedTourService.startTour(this.dashboardTour); + } + // rowClicked(dataset: DatasetListingModel) { // this.router.navigate(['/datasets/edit/' + dataset.id]); // } diff --git a/dmp-frontend/src/app/ui/dataset/listing/listing-item/dataset-listing-item.component.html b/dmp-frontend/src/app/ui/dataset/listing/listing-item/dataset-listing-item.component.html index 2c0ffa8b2..72ec41e3c 100644 --- a/dmp-frontend/src/app/ui/dataset/listing/listing-item/dataset-listing-item.component.html +++ b/dmp-frontend/src/app/ui/dataset/listing/listing-item/dataset-listing-item.component.html @@ -1,10 +1,11 @@
- +
{{'DATASET-LISTING.DATASET-DESCRIPTION' | translate}}
-
{{'DATASET-LISTING.STATES.EDITED' | translate}}: {{dataset.modified | date:"longDate"}}
+
{{'DATASET-LISTING.STATES.EDITED' | translate}}: {{dataset.modified | date:"longDate"}}
+
{{'DATASET-LISTING.STATES.PUBLISHED' | translate}}: {{dataset.dmpPublishedAt | date:"longDate"}}
-
{{'DATASET-LISTING.DATASET-DESCRIPTION' | translate}}: {{dataset.label}}
+
{{dataset.label}}
{{ roleDisplay(dataset.users) }} . diff --git a/dmp-frontend/src/app/ui/dataset/listing/listing-item/dataset-listing-item.component.ts b/dmp-frontend/src/app/ui/dataset/listing/listing-item/dataset-listing-item.component.ts index 6d6c48ddf..11c561495 100644 --- a/dmp-frontend/src/app/ui/dataset/listing/listing-item/dataset-listing-item.component.ts +++ b/dmp-frontend/src/app/ui/dataset/listing/listing-item/dataset-listing-item.component.ts @@ -78,7 +78,8 @@ export class DatasetListingItemComponent extends BaseComponent implements OnInit } getItemLink(): string[] { - return this.isPublic ? [`/datasets/publicEdit/${this.dataset.id}`] : [`/datasets/edit/${this.dataset.id}`]; + // return this.isPublic ? [`/datasets/publicEdit/${this.dataset.id}`] : [`/datasets/edit/${this.dataset.id}`]; + return this.isPublic ? ['/datasets/publicOverview/' + this.dataset.id] : ['/datasets/overview/' + this.dataset.id]; } getDmpLink(): string[] { diff --git a/dmp-frontend/src/app/ui/dataset/overview/dataset-overview.component.html b/dmp-frontend/src/app/ui/dataset/overview/dataset-overview.component.html index e178cd073..2787116db 100644 --- a/dmp-frontend/src/app/ui/dataset/overview/dataset-overview.component.html +++ b/dmp-frontend/src/app/ui/dataset/overview/dataset-overview.component.html @@ -65,7 +65,7 @@
{{'DATASET-LISTING.TOOLTIP.PART-OF' | translate}}
-
+
-
-
+
+
-
+
{{'DMP-EDITOR.TITLE.EDIT-DATASET' | translate}}
{{ dataset.get('label').value }} ({{'DMP-EDITOR.CHANGES' | translate}})
{{'DATASET-LISTING.TOOLTIP.PART-OF' | translate}}
{{'DATASET-LISTING.TOOLTIP.DMP' | translate}}
-
{{'DATASET-LISTING.TOOLTIP.DMP-FOR' | translate}}: {{ formGroup.get('label').value }}
+
{{ formGroup.get('label').value }}
+
+
{{'DMP-EDITOR.TITLE.CREATE-DATASET' | translate}}
+
- + + @@ -63,17 +68,23 @@
-
+
{{'DMP-EDITOR.STEPPER.USER-GUIDE' | translate}}
    -
  1. {{'DMP-EDITOR.STEPPER.MAIN-INFO' | translate}} (4)
  2. -
  3. {{'DMP-EDITOR.STEPPER.FUNDING-INFO' | translate}} (3)
  4. -
  5. {{'DMP-EDITOR.STEPPER.DATASET-INFO' | translate}}
  6. -
  7. +
  8. {{'DMP-EDITOR.STEPPER.MAIN-INFO' | translate}} (4)
  9. +
  10. {{'DMP-EDITOR.STEPPER.MAIN-INFO' | translate}} (1)
  11. + +
  12. {{'DMP-EDITOR.STEPPER.FUNDING-INFO' | translate}} (3)
  13. +
  14. {{'DMP-EDITOR.STEPPER.DATASET-INFO' | translate}}
  15. + +
  16. {{'DMP-EDITOR.STEPPER.DATASET-INFO' | translate}}
  17. + +
  18. {{'DMP-EDITOR.STEPPER.DATASET' | translate}}
    + check{{'TYPES.DATASET-STATUS.FINALISED' | translate}}
      -
    • {{ dataset.get('label').value }} (8)
    • +
    • {{ dataset.get('label').value }} (8)
@@ -83,17 +94,25 @@ chevron_left
{{'DMP-EDITOR.STEPPER.PREVIOUS' | translate}}
-
+
+ chevron_right +
{{'DMP-EDITOR.STEPPER.NEXT' | translate}}
+
+
chevron_right
{{'DMP-EDITOR.STEPPER.NEXT' | translate}}
- - - -
+ + + + + + + +
diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.scss b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.scss index 1f0247692..f99a170e4 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.scss +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.scss @@ -219,7 +219,7 @@ a:hover { color: #000000; } -.stepper { +.dataset-stepper { position: fixed; // height: 100%; display: flex; @@ -228,6 +228,15 @@ a:hover { overflow-y: auto; } +.dmp-stepper { + position: fixed; + // height: 100%; + display: flex; + flex-direction: column; + height: calc(100vh - 190px); + overflow-y: auto; +} + .stepper-title { text-align: left; font-weight: 300; @@ -367,14 +376,29 @@ a:hover { white-space: nowrap; } -::ng-deep .mat-tab-labels { - justify-content: space-between; +.status-icon { + font-size: 1.2em; + color: #a7a7a7; + vertical-align: text-top; } -::ng-deep .mat-tab-label-content { - text-transform: uppercase; +.cursor-default { + cursor: default; } +.finalized-label { + font-weight: 400; + font-size: 0.875rem; +} + +// ::ng-deep .mat-tab-labels { +// justify-content: space-between; +// } + +// ::ng-deep .mat-tab-label-content { +// text-transform: uppercase; +// } + ::ng-deep .mat-ink-bar { background-color: #00b29f !important; // background-color: #0070c0 !important; 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 index 041a301a3..02dd03184 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts @@ -41,6 +41,10 @@ import { LockModel } from '@app/core/model/lock/lock.model'; import { Guid } from '@common/types/guid'; import { ConfigurationService } from '@app/core/services/configuration/configuration.service'; import { ExtraPropertiesFormModel } from './general-tab/extra-properties-form.model'; +import { DatasetWizardEditorModel } from '@app/ui/dataset/dataset-wizard/dataset-wizard-editor.model'; +import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; +import { DmpListingModel } from '@app/core/model/dmp/dmp-listing'; +import { DmpCriteria } from '@app/core/query/dmp/dmp-criteria'; @Component({ selector: 'app-dmp-editor-component', @@ -56,22 +60,29 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC isNew = true; isPublic = false; isFinalized = false; + hasChanges = false; + isNewDataset = false; + isUserOwner: boolean = true; + dmp: DmpEditorModel; formGroup: FormGroup = null; formGroupRawValue: any; - hasChanges = false; - - selectedTab = 0; + datasetId: string = null; + datasets = new FormArray([]); createNewVersion; + associatedUsers: Array; people: Array; filteredOptions: DmpProfileListing[]; selectedDmpProfileDefinition: DmpProfileDefinition; + DynamicDmpFieldResolverComponent: any; - isUserOwner: boolean = true; lock: LockModel; lockStatus: Boolean; + + selectedTab = 0; step: number = 0; + stepsBeforeDatasets: number = 3; maxStep: number = 3; constructor( @@ -92,6 +103,11 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC } ngOnInit() { + if (this.router.url.toString().localeCompare('/new/dataset') === 0) { + this.isNewDataset = true; + this.stepsBeforeDatasets = 2; + this.maxStep = 2; + }; this.route.params .pipe(takeUntil(this._destroyed)) .subscribe((params: Params) => { @@ -99,6 +115,8 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC const publicId = params['publicId']; const queryParams = this.route.snapshot.queryParams; const tabToNav = queryParams['tab']; + this.datasetId = queryParams['dataset']; + // if (queryParams['step']) { this.step = queryParams['step']; } const grantRequestItem: RequestItem = new RequestItem(); grantRequestItem.criteria = new GrantCriteria(); @@ -111,6 +129,7 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC // displayFn: (item) => item['label'], // titleFn: (item) => item['label'] // }; + switch (tabToNav) { case 'general': this.selectedTab = 0; @@ -139,6 +158,8 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC this.dmp.extraProperties = new ExtraPropertiesFormModel(); this.dmp.fromModel(data); this.formGroup = this.dmp.buildForm(); + + this.datasets = this.formGroup.get('datasets') as FormArray; this.formGroupRawValue = JSON.parse(JSON.stringify(this.formGroup.getRawValue())); this.maxStep = this.formGroup.get('datasets') ? this.maxStep + this.formGroup.get('datasets').value.length - 1 : this.maxStep; @@ -148,6 +169,10 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC this.formGroup.disable(); } + if (this.datasetId) { + this.step = this.formGroup.get('datasets')['controls'].findIndex((dataset) => { return this.datasetId === dataset.get('id').value; }) + this.stepsBeforeDatasets; + } + //this.registerFormEventsForDmpProfile(this.dmp.definition); if (!this.editMode || this.dmp.status === DmpStatus.Finalized || lockStatus) { this.isFinalized = true; @@ -200,6 +225,10 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC this.dmp.fromModel(data); this.formGroup = this.dmp.buildForm(); + // this.formGroup.get('datasets')['controls'].forEach(element => { + // this.datasets.push(element); + // }); + this.datasets = this.formGroup.get('datasets') as FormArray; this.formGroupRawValue = JSON.parse(JSON.stringify(this.formGroup.getRawValue())); this.maxStep = this.formGroup.get('datasets') ? this.maxStep + this.formGroup.get('datasets').value.length - 1 : this.maxStep; @@ -230,6 +259,24 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC // } // }) }); + } else if (this.isNewDataset) { + this.dmp = new DmpEditorModel(); + this.dmp.grant = new GrantTabModel(); + this.dmp.project = new ProjectFormModel(); + this.dmp.funder = new FunderFormModel(); + this.dmp.extraProperties = new ExtraPropertiesFormModel(); + this.dmp.extraProperties.visible = false; + this.dmp.extraProperties.contact = this.authService.current().id; + const datasetWizardEditorModel = new DatasetWizardEditorModel(); + this.dmp.datasets.push(datasetWizardEditorModel); + this.formGroup = this.dmp.buildForm(); + + this.datasets = this.formGroup.get('datasets') as FormArray; + + this.formGroupRawValue = JSON.parse(JSON.stringify(this.formGroup.getRawValue())); + this.maxStep = this.formGroup.get('datasets') ? this.maxStep + this.formGroup.get('datasets').value.length - 1 : this.maxStep; + + this.registerFormEventsForNewItem(); } else { this.dmp = new DmpEditorModel(); this.dmp.grant = new GrantTabModel(); @@ -374,7 +421,8 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC if (showAddDatasetDialog) { this.addDatasetOpenDialog(complete); } - else { this.onCallbackSuccess(complete) } + else if (this.step < this.stepsBeforeDatasets) { this.onCallbackSuccess(complete) } + else { this.onCallbackSuccess(complete, this.datasetId) } }, error => { this.formGroup.get('status').setValue(DmpStatus.Draft); @@ -398,9 +446,13 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC } - onCallbackSuccess(id?: String): void { + onCallbackSuccess(id?: String, datasetId?: string): void { this.uiNotificationService.snackBarNotification(this.isNew ? this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-CREATION') : this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success); - id != null ? this.router.navigate(['/reload']).then(() => { this.router.navigate(['/plans', 'edit', id]); }) : this.router.navigate(['/reload']).then(() => { this.router.navigate(['/plans']); }); + if (id != null) { + datasetId ? this.router.navigate(['/reload']).then(() => { this.router.navigate(['/plans', 'edit', id], { queryParams: { dataset: datasetId } }); }) : this.router.navigate(['/reload']).then(() => { this.router.navigate(['/plans', 'edit', id]); }) + } else { + this.router.navigate(['/reload']).then(() => { this.router.navigate(['/plans']); }); + } } onCallbackError(error: any) { @@ -629,16 +681,23 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC this.lockService.createOrUpdate(this.lock).pipe(takeUntil(this._destroyed)).subscribe(async result => this.lock.id = Guid.parse(result)); } - public changeStep(index: number) { + public changeStep(index: number, dataset?: FormControl) { this.step = index; + if (dataset) { this.datasetId = dataset.get('id').value }; } public nextStep() { this.step = this.step < this.maxStep ? this.step + 1 : this.step; + if (this.step >= this.stepsBeforeDatasets) { + this.datasetId = this.datasets.at(this.step - this.stepsBeforeDatasets).get('id').value; + } } public previousStep() { this.step = this.step !== 0 ? this.step - 1 : this.step; + if (this.step >= this.stepsBeforeDatasets) { + this.datasetId = this.datasets.at(this.step - this.stepsBeforeDatasets).get('id').value; + } } public isDirty(): boolean { diff --git a/dmp-frontend/src/app/ui/dmp/editor/main-info/main-info.component.html b/dmp-frontend/src/app/ui/dmp/editor/main-info/main-info.component.html index 664c6057b..0d2d84188 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/main-info/main-info.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/main-info/main-info.component.html @@ -9,30 +9,35 @@
1.1 {{'DMP-EDITOR.FIELDS.NAME' | translate}}*
{{'DMP-EDITOR.MAIN-INFO.HINT' | translate}}
- + {{formGroup.get('label').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + +
-
+
1.2 {{'DMP-EDITOR.FIELDS.DESCRIPTION' | translate}}
{{'DMP-EDITOR.MAIN-INFO.HINT' | translate}}
- +
-
+
1.3 {{'DMP-EDITOR.FIELDS.RESEARCHERS' | translate}}
@@ -40,7 +45,7 @@
info {{'DMP-EDITOR.MAIN-INFO.TYPING' | translate}}
- + @@ -55,7 +60,7 @@
-
+
1.4 {{'DMP-EDITOR.FIELDS.ORGANISATIONS' | translate}}
@@ -63,7 +68,7 @@
info {{'DMP-EDITOR.MAIN-INFO.TYPING' | translate}}
- + diff --git a/dmp-frontend/src/app/ui/dmp/editor/main-info/main-info.component.ts b/dmp-frontend/src/app/ui/dmp/editor/main-info/main-info.component.ts index d3209d786..4267d94a2 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/main-info/main-info.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/main-info/main-info.component.ts @@ -12,6 +12,12 @@ import { isNullOrUndefined } from 'util'; import { MatDialog } from '@angular/material'; import { AddOrganizationComponent } from '../add-organization/add-organization.component'; import { AddResearcherComponent } from '../add-researcher/add-researcher.component'; +import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; +import { DmpListingModel } from '@app/core/model/dmp/dmp-listing'; +import { DataTableRequest } from '@app/core/model/data-table/data-table-request'; +import { DmpCriteria } from '@app/core/query/dmp/dmp-criteria'; +import { DmpStatus } from '@app/core/common/enum/dmp-status'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; @Component({ selector: 'main-info', @@ -22,6 +28,7 @@ export class MainInfoComponent extends BaseComponent implements OnInit { @Input() formGroup: FormGroup = null; @Input() isNewVersion: boolean; + @Input() isNewDataset: boolean; @Input() isUserOwner: boolean; @Input() isClone: boolean; @Output() onFormChanged: EventEmitter = new EventEmitter(); @@ -41,10 +48,19 @@ export class MainInfoComponent extends BaseComponent implements OnInit { subtitleFn: (item) => item['tag'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['tag'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')) }; + dmpAutoCompleteConfiguration: SingleAutoCompleteConfiguration = { + filterFn: this.searchDmp.bind(this), + initialItems: (extraData) => this.searchDmp(''), + displayFn: (item) => this.getDatasetDisplay(item), + titleFn: (item) => item['label'], + subtitleFn: (item) => this.language.instant('DATASET-WIZARD.FIRST-STEP.SUB-TITLE') + new Date(item['creationTime']).toISOString() + }; + constructor( private language: TranslateService, private configurationService: ConfigurationService, private externalSourcesService: ExternalSourcesService, + private dmpService: DmpService, private dialog: MatDialog ) { super(); @@ -136,4 +152,22 @@ export class MainInfoComponent extends BaseComponent implements OnInit { } }); } + + searchDmp(query: string): Observable { + const fields: Array = new Array(); + fields.push('-created'); + const dmpDataTableRequest: DataTableRequest = new DataTableRequest(0, null, { fields: fields }); + dmpDataTableRequest.criteria = new DmpCriteria(); + dmpDataTableRequest.criteria.like = query; + dmpDataTableRequest.criteria.status = DmpStatus.Draft; + return this.dmpService.getPaged(dmpDataTableRequest, "autocomplete").pipe(map(x => x.data)); + } + + getDatasetDisplay(item: any): string { + // if (!this.isPublic) { + // return (item['status'] ? this.language.instant('TYPES.DATASET-STATUS.FINALISED').toUpperCase() : this.language.instant('TYPES.DATASET-STATUS.DRAFT').toUpperCase()) + ': ' + item['label']; + // } + // else { return item['label']; } + return item['label'] ? item['label'] : null; + } } diff --git a/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation-dialog.component.html b/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation-dialog.component.html index c6faefb3f..863259f59 100644 --- a/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation-dialog.component.html +++ b/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation-dialog.component.html @@ -7,7 +7,7 @@

{{'DMP-LISTING.ACTIONS.INVITE-AUTHORS' | translate}}

- + diff --git a/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation-dialog.component.scss b/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation-dialog.component.scss index 315ec3063..e82edc6cf 100644 --- a/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation-dialog.component.scss +++ b/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation-dialog.component.scss @@ -28,24 +28,38 @@ border-radius: 4px; } -::ng-deep .mat-dialog-container { - border-radius: 8px; + +.search { + ::ng-deep { + .mat-dialog-container { + border-radius: 8px; + } + .mat-form-field-underline { + display: none; + } + .mat-form-field-wrapper { + padding: 0em !important; + } + .mat-form-field-infix { + border: none; + } + .align-arrow-right { + display: none; + } + } } -::ng-deep .mat-form-field-underline { - display: none; -} - -::ng-deep .mat-form-field-wrapper { - padding: 0em !important; -} - -::ng-deep .mat-form-field-infix { - border: none; -} - -::ng-deep .align-arrow-right { - display: none; +.select-role { + ::ng-deep { + .mat-form-field-outline-start, + .mat-form-field-outline-gap, + .mat-form-field-outline-end { + border: none !important; + } + .mat-form-field-wrapper { + padding: 0em !important; + } + } } .invite-btn { @@ -61,7 +75,7 @@ } .select-role { - width: 16% !important; + width: 20% !important; font-size: 14px; color: #848484; height: min-content; diff --git a/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.scss b/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.scss index 7d2c18ab2..8198a3f04 100644 --- a/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.scss +++ b/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.scss @@ -28,8 +28,6 @@ margin-bottom: 12px; } - - .filters { border: 1px solid #e4e4e4; border-radius: 5px; @@ -37,7 +35,8 @@ .filters-title { width: 93px; - color: #089dbb; + // color: #089dbb; + color: #23bcba; background-color: white; padding: 0px 20px; margin-top: -10px; @@ -110,3 +109,12 @@ .mat-radio-button.mat-accent .mat-radio-ripple .mat-ripple-element { background-color: #2e74b649; } + +::ng-deep .mat-form-field-wrapper { + background-color: white !important; + padding-bottom: 0 !important; +} + +::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix { + padding: 0.3rem 0rem 0.6rem 0rem !important; +} 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 index 06fed8dee..93abc1d2e 100644 --- a/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.html +++ b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.html @@ -22,20 +22,32 @@ {{'DMP-LISTING.SORT-BY' | translate}}: - {{enumUtils.toRecentActivityOrderString(order.MODIFIED)}} + {{enumUtils.toRecentActivityOrderString(order.MODIFIED)}} + {{enumUtils.toRecentActivityOrderString(order.PUBLISHED)}} {{enumUtils.toRecentActivityOrderString(order.LABEL)}} - {{enumUtils.toRecentActivityOrderString(order.STATUS)}} + {{enumUtils.toRecentActivityOrderString(order.STATUS)}} {{enumUtils.toRecentActivityOrderString(order.CREATED)}} - - - search - - {{formGroup.get('like').getError('backendError').message}} - - +
+ +
+ {{ 'GENERAL.ACTIONS.TAKE-A-TOUR'| translate }} +
+ + + + search + + + {{formGroup.get('like').getError('backendError').message}} + + +
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 index d3541c7dc..ba7fc9fc9 100644 --- a/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.scss +++ b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.scss @@ -241,6 +241,19 @@ padding: 0.3rem 0rem 0.6rem 0rem !important; } +.center-content { + width: 100%; + min-width: 10rem; + margin: auto; + padding: 0 15px; + text-align: right; + font-size: 0.875rem; + font-weight: 600; + letter-spacing: 0.02rem; + color: #2D72D6; + cursor: pointer; +} + // .bot-paginator { // margin-top: auto; // } 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 index 9cbd9283f..3730aa365 100644 --- a/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts +++ b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts @@ -26,7 +26,8 @@ import { AuthService } from '@app/core/services/auth/auth.service'; import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; import { DmpCriteriaDialogComponent } from './criteria/dmp-criteria-dialog.component'; import { RecentActivityOrder } from '@app/core/common/enum/recent-activity-order'; - +import { GuidedTourService } from '@app/library/guided-tour/guided-tour.service'; +import { GuidedTour, Orientation } from '@app/library/guided-tour/guided-tour.constants'; @Component({ selector: 'app-dmp-listing-component', @@ -63,6 +64,8 @@ export class DmpListingComponent extends BaseComponent implements OnInit, IBread scrollbar: boolean; order = RecentActivityOrder; + dmpText: string; + datasetText: string; constructor( private dmpService: DmpService, @@ -73,14 +76,19 @@ export class DmpListingComponent extends BaseComponent implements OnInit, IBread private language: TranslateService, private grantService: GrantService, private uiNotificationService: UiNotificationService, - private authService: AuthService + private authService: AuthService, + private guidedTourService: GuidedTourService ) { super(); } ngOnInit() { this.isPublic = this.router.url.startsWith('/explore-plans'); - this.formGroup.get('order').setValue(this.order.MODIFIED); + if (this.isPublic) { + this.formGroup.get('order').setValue(this.order.PUBLISHED); + } else { + this.formGroup.get('order').setValue(this.order.MODIFIED); + } if (!this.isPublic && isNullOrUndefined(this.authService.current())) { this.router.navigateByUrl("/explore-plans"); } @@ -173,6 +181,29 @@ export class DmpListingComponent extends BaseComponent implements OnInit, IBread .subscribe(x => this.refresh()); } + public dashboardTour: GuidedTour = { + tourId: 'dmp-dataset-tour', + useOrb: true, + steps: [ + { + selector: '.dmp-tour', + content: 'Step 1', + orientation: Orientation.Right, + isStepUnique: false + }, + { + selector: '.dataset-tour', + content: 'Step 2', + orientation: Orientation.Right, + isStepUnique: false + } + ] + }; + + public isAuthenticated(): boolean { + return !(!this.authService.current()); + } + ngAfterContentChecked(): void { this.scrollbar = this.hasScrollbar(); } @@ -185,7 +216,8 @@ export class DmpListingComponent extends BaseComponent implements OnInit, IBread // let fields: Array = new Array(); // if (this.sort && this.sort.active) { fields = this.sort.direction === 'asc' ? ['+' + this.sort.active] : ['-' + this.sort.active]; } // fields.push('-modified'); - const fields: Array = [(this.formGroup.get('order').value === 'status' ? '+' : "-") + this.formGroup.get('order').value]; + const fields: Array = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value]; + this.startIndex = 0; const request = new DataTableRequest(this.startIndex, this.pageSize, { fields: fields }); this.setPublicCriteria(); @@ -209,7 +241,7 @@ export class DmpListingComponent extends BaseComponent implements OnInit, IBread public loadMore() { this.startIndex = this.startIndex + this.pageSize; // const fields: Array = ["-modified"]; - const fields: Array = [(this.formGroup.get('order').value === 'status' ? '+' : "-") + this.formGroup.get('order').value]; + const fields: Array = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value]; const request = new DataTableRequest(this.startIndex, this.pageSize, { fields: fields }); this.setPublicCriteria(); request.criteria = this.criteria; @@ -362,16 +394,22 @@ export class DmpListingComponent extends BaseComponent implements OnInit, IBread } setPublicCriteria(formGroup?: FormGroup): void { - if (formGroup && formGroup.get('status').value == 2) { - this.criteria.isPublic = true; + if (!isNullOrUndefined(formGroup)) { + if (formGroup.get('status').value == 2) { + this.criteria.status = 1; + this.criteria.isPublic = true; + } else { + this.criteria.isPublic = false; + } } this.criteria.onlyPublic = this.isPublic; if (this.isPublic) { this.criteria.isPublic = true; - } else { - this.criteria.isPublic = false; } + // } else { + // this.criteria.isPublic = false; + // } } hasScrollbar(): boolean { @@ -406,7 +444,7 @@ export class DmpListingComponent extends BaseComponent implements OnInit, IBread index2++; } } else if (order === 'label') { - if (!isArr1Depleted && (isArr2Depleted || (arr1[index1].label < arr2[index2].label))) { + if (!isArr1Depleted && (isArr2Depleted || (arr1[index1].label.localeCompare(arr2[index2].label)))) { merged[current] = arr1[index1]; index1++; } else { @@ -421,11 +459,41 @@ export class DmpListingComponent extends BaseComponent implements OnInit, IBread merged[current] = arr2[index2]; index2++; } + } else if (order === "publishedAt") { + if (!isArr1Depleted && (isArr2Depleted || (new Date(arr1[index1].publishedAt) > new Date(arr2[index2].publishedAt)))) { + merged[current] = arr1[index1]; + index1++; + } else { + merged[current] = arr2[index2]; + index2++; + } } current++; } return merged; } + + public setDashboardTourDmpText(): void { + this.dmpText = this.language.instant('DMP-LISTING.TEXT-INFO') + '\n\n' + + this.language.instant('DMP-LISTING.TEXT-INFO-QUESTION') + ' ' + + this.language.instant('DMP-LISTING.LINK-ZENODO') + ' ' + + this.language.instant('DMP-LISTING.GET-IDEA'); + this.dashboardTour.steps[0].title = this.dmpText; + } + + public setDashboardTourDatasetText(): void { + this.datasetText = this.language.instant('DATASET-LISTING.TEXT-INFO') + + this.language.instant('DATASET-LISTING.LINK-PUBLIC-DATASETS') + ' ' + + this.language.instant('DATASET-LISTING.TEXT-INFO-REST') + '\n\n' + + this.language.instant('DATASET-LISTING.TEXT-INFO-PAR'); + this.dashboardTour.steps[1].title = this.datasetText; + } + + public restartTour(): void { + this.setDashboardTourDmpText(); + this.setDashboardTourDatasetText(); + this.guidedTourService.startTour(this.dashboardTour); + } } // export class DmpDataSource extends DataSource { diff --git a/dmp-frontend/src/app/ui/dmp/listing/listing-item/dmp-listing-item.component.html b/dmp-frontend/src/app/ui/dmp/listing/listing-item/dmp-listing-item.component.html index 4af83d5d0..044eb1ccc 100644 --- a/dmp-frontend/src/app/ui/dmp/listing/listing-item/dmp-listing-item.component.html +++ b/dmp-frontend/src/app/ui/dmp/listing/listing-item/dmp-listing-item.component.html @@ -2,7 +2,8 @@
{{ 'DMP-LISTING.DMP' | translate }}
-
{{ 'DMP-LISTING.EDITED' | translate }}: {{ dmp.modifiedTime | date: "longDate" }}
+
{{ 'DMP-LISTING.EDITED' | translate }}: {{ dmp.modifiedTime | date: "longDate" }}
+
{{ 'DMP-LISTING.PUBLISHED' | translate }}: {{ dmp.publishedAt | date: "longDate" }}
{{dmp.label}}
diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html index acd3b4987..47be2775c 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html @@ -52,7 +52,7 @@
-
---> \ No newline at end of file +--> diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts index 4e8e20359..943bc71cd 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts @@ -119,8 +119,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { .pipe(takeUntil(this._destroyed)) .subscribe(data => { this.dmp = data; - this.checkLockStatus(this.dmp.id); - this.setIsUserOwner(); + // this.checkLockStatus(this.dmp.id); this.getAllVersions(this.dmp); const breadCrumbs = []; breadCrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.PUBLIC-DMPS'), url: "/explore-plans" }); @@ -156,8 +155,10 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { } isUserAuthor(userId: string): boolean { - const principal: Principal = this.authentication.current(); - return userId === principal.id; + if (this.isAuthenticated()) { + const principal: Principal = this.authentication.current(); + return userId === principal.id; + } else return false; } editClicked(dmp: DmpOverviewModel) { diff --git a/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.scss b/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.scss index b3f5e80d5..d59ca2f65 100644 --- a/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.scss +++ b/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.scss @@ -31,7 +31,8 @@ .filters-title { width: 90px; - color: #089dbb; + // color: #089dbb; + color: #23bcba; background-color: white; padding: 0px 20px; margin-top: -10px; diff --git a/dmp-frontend/src/app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filters.component.scss b/dmp-frontend/src/app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filters.component.scss index 0bceec0ed..c1cd0df9a 100644 --- a/dmp-frontend/src/app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filters.component.scss +++ b/dmp-frontend/src/app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filters.component.scss @@ -31,7 +31,8 @@ .filters-title { width: 93px; - color: #089dbb; + // color: #089dbb; + color: #23bcba; background-color: white; padding: 0px 20px; margin-top: -10px; diff --git a/dmp-frontend/src/app/ui/grant/listing/criteria/grant-criteria.component.scss b/dmp-frontend/src/app/ui/grant/listing/criteria/grant-criteria.component.scss index 107230090..d4e4c18ab 100644 --- a/dmp-frontend/src/app/ui/grant/listing/criteria/grant-criteria.component.scss +++ b/dmp-frontend/src/app/ui/grant/listing/criteria/grant-criteria.component.scss @@ -1,61 +1,62 @@ .dmp-criteria { - mat-form-field { - padding-bottom: 5px; - width: 100%; - } - - mat-card { - padding-bottom: 0px; - } - - .hidden { - display: none; - } - - .uploadButton { - float: right; - } + mat-form-field { + padding-bottom: 5px; + width: 100%; } - .search ::ng-deep.mat-form-field-infix { - margin-left: 1em; + mat-card { + padding-bottom: 0px; } - .filter-category { - background-color: #f6f6f6; - margin: 5px 0px; + .hidden { + display: none; } - .category-title { - color: black; - // color: #089dbb; - margin-top: 8px; - margin-bottom: 12px; + .uploadButton { + float: right; } +} - .import { - margin: 10px; - padding: 0px; - } +.search ::ng-deep.mat-form-field-infix { + margin-left: 1em; +} - .filters { - border: 1px solid #e4e4e4; - border-radius: 5px; - } +.filter-category { + background-color: #f6f6f6; + margin: 5px 0px; +} - .filters-title { - width: 90px; - color: #089dbb; - background-color: white; - padding: 0px 20px; - margin-top: -10px; - margin-left: 20px; - text-transform: uppercase; - } +.category-title { + color: black; + // color: #089dbb; + margin-top: 8px; + margin-bottom: 12px; +} - .style-icon { - color: #adadad; - } +.import { + margin: 10px; + padding: 0px; +} + +.filters { + border: 1px solid #e4e4e4; + border-radius: 5px; +} + +.filters-title { + width: 90px; + // color: #089dbb; + color: #23bcba; + background-color: white; + padding: 0px 20px; + margin-top: -10px; + margin-left: 20px; + text-transform: uppercase; +} + +.style-icon { + color: #adadad; +} // ::ng-deep .mat-checkbox-inner-container { // background: white; @@ -73,48 +74,57 @@ // background-color: #00b29f !important; // } - ::ng-deep .mat-checkbox { - background-color: #f6f6f6 !important; - } +::ng-deep .mat-checkbox { + background-color: #f6f6f6 !important; +} - ::ng-deep .mat-checkbox .mat-checkbox-frame { - border: 1px solid #aaaaaa; - } +::ng-deep .mat-checkbox .mat-checkbox-frame { + border: 1px solid #aaaaaa; +} - ::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background, - .mat-checkbox-indeterminate.mat-accent .mat-checkbox-background, - .mat-accent .mat-pseudo-checkbox-checked, - .mat-accent .mat-pseudo-checkbox-indeterminate, - .mat-pseudo-checkbox-checked, - .mat-pseudo-checkbox-indeterminate { - background-color: #00b29f; - } +::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background, +.mat-checkbox-indeterminate.mat-accent .mat-checkbox-background, +.mat-accent .mat-pseudo-checkbox-checked, +.mat-accent .mat-pseudo-checkbox-indeterminate, +.mat-pseudo-checkbox-checked, +.mat-pseudo-checkbox-indeterminate { + background-color: #00b29f; +} - ::ng-deep .mat-ripple-element { - background-color: #2e74b649 !important; - } +::ng-deep .mat-ripple-element { + background-color: #2e74b649 !important; +} - ::ng-deep .mat-radio-container { - border-radius: 1em; - background: white; - } +::ng-deep .mat-radio-container { + border-radius: 1em; + background: white; +} - ::ng-deep .mat-radio-button .mat-radio-outer-circle { - border: 1px solid #aaaaaa; - } +::ng-deep .mat-radio-button .mat-radio-outer-circle { + border: 1px solid #aaaaaa; +} - ::ng-deep .mat-radio-button.mat-accent.mat-radio-checked .mat-radio-outer-circle { - border-color: #777777; - // border-color: #00b29f; - } +::ng-deep .mat-radio-button.mat-accent.mat-radio-checked .mat-radio-outer-circle { + border-color: #777777; + // border-color: #00b29f; +} - ::ng-deep .mat-radio-button.mat-accent .mat-radio-inner-circle { - color: #777777; - background-color: #777777; - // color: #00b29f; - // background-color: #00b29f; - } +::ng-deep .mat-radio-button.mat-accent .mat-radio-inner-circle { + color: #777777; + background-color: #777777; + // color: #00b29f; + // background-color: #00b29f; +} - .mat-radio-button.mat-accent .mat-radio-ripple .mat-ripple-element { - background-color: #2e74b649; - } +.mat-radio-button.mat-accent .mat-radio-ripple .mat-ripple-element { + background-color: #2e74b649; +} + +::ng-deep .search-form .mat-form-field-wrapper { + background-color: white !important; + padding-bottom: 0 !important; +} + +::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix { + padding: 0.3rem 0rem 0.6rem 0rem !important; +} diff --git a/dmp-frontend/src/app/ui/navbar/navbar.component.html b/dmp-frontend/src/app/ui/navbar/navbar.component.html index bb8674107..8056b8715 100644 --- a/dmp-frontend/src/app/ui/navbar/navbar.component.html +++ b/dmp-frontend/src/app/ui/navbar/navbar.component.html @@ -7,21 +7,19 @@
- +
@@ -144,4 +144,4 @@ - \ No newline at end of file + diff --git a/dmp-frontend/src/assets/splash/assets/img/argos present.png b/dmp-frontend/src/assets/splash/assets/img/argos present.png new file mode 100644 index 000000000..9e167acc3 Binary files /dev/null and b/dmp-frontend/src/assets/splash/assets/img/argos present.png differ diff --git a/dmp-frontend/src/assets/splash/assets/img/argos present@2x.png b/dmp-frontend/src/assets/splash/assets/img/argos present@2x.png new file mode 100644 index 000000000..1b99808ea Binary files /dev/null and b/dmp-frontend/src/assets/splash/assets/img/argos present@2x.png differ diff --git a/dmp-frontend/src/assets/splash/assets/img/argos-logo-2.svg b/dmp-frontend/src/assets/splash/assets/img/argos-logo-2.svg new file mode 100644 index 000000000..559d53513 --- /dev/null +++ b/dmp-frontend/src/assets/splash/assets/img/argos-logo-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dmp-frontend/src/assets/splash/assets/img/flag-of-austria.png b/dmp-frontend/src/assets/splash/assets/img/flag-of-austria.png new file mode 100644 index 000000000..09b15db05 Binary files /dev/null and b/dmp-frontend/src/assets/splash/assets/img/flag-of-austria.png differ diff --git a/dmp-frontend/src/styles.scss b/dmp-frontend/src/styles.scss index 5452616c1..32cca66b9 100644 --- a/dmp-frontend/src/styles.scss +++ b/dmp-frontend/src/styles.scss @@ -5,6 +5,9 @@ // Material-Bootstrap configuration @import "~bootstrap/scss/bootstrap"; +// Guided Tour style +@import '../node_modules/ngx-guided-tour/scss/guided-tour-base-theme.scss'; + // Custom Theme // @import "./assets/scss/blue-theme.scss"; @@ -171,13 +174,11 @@ flex-grow: 1; } +::ng-deep .mat-form-field-wrapper { + background-color: white !important; + padding-bottom: 0 !important; +} -// ::ng-deep .mat-form-field-flex > .mat-form-field-infix { padding: 0.4em 0px !important; } -// ::ng-deep .mat-form-field-label-wrapper { top: -1.5em; } - -// ::ng-deep .mat-form-field-appearance-outline.mat-form-field-can-float.mat-form-field-should-float .mat-form-field-label { -// transform: translateY(-1.1em) scale(.75); -// width: 133.33333%; -// } - -// ::ng-deep .mat-form-field-appearance-outline .mat-form-field-outline {background: #fafafa !important;} +::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix { + padding: 0.3rem 0rem 0.6rem 0rem !important; +}