diff --git a/cypress/e2e/published-data/published-data.cy.js b/cypress/e2e/published-data/published-data.cy.js
index 97fc09f388..6c3be903c7 100644
--- a/cypress/e2e/published-data/published-data.cy.js
+++ b/cypress/e2e/published-data/published-data.cy.js
@@ -173,7 +173,8 @@ describe("Datasets general", () => {
cy.finishedLoading();
- cy.get('input[formcontrolname="globalSearch"]').clear().type(title);
+ cy.get('[data-cy="text-search"]').clear().type(title);
+ cy.get('[data-cy="search-button"]').click();
cy.isLoading();
@@ -192,7 +193,8 @@ describe("Datasets general", () => {
cy.finishedLoading();
- cy.get('input[formcontrolname="globalSearch"]').clear().type(title);
+ cy.get('[data-cy="text-search"]').clear().type(title);
+ cy.get('[data-cy="search-button"]').click();
cy.isLoading();
@@ -221,7 +223,8 @@ describe("Datasets general", () => {
cy.finishedLoading();
- cy.get('input[formcontrolname="globalSearch"]').clear().type(title);
+ cy.get('[data-cy="text-search"]').clear().type(title);
+ cy.get('[data-cy="search-button"]').click();
cy.isLoading();
@@ -298,7 +301,8 @@ describe("Datasets general", () => {
cy.finishedLoading();
- cy.get('input[formcontrolname="globalSearch"]').clear().type(title);
+ cy.get('[data-cy="text-search"]').clear().type(title);
+ cy.get('[data-cy="search-button"]').click();
cy.isLoading();
@@ -349,7 +353,8 @@ describe("Datasets general", () => {
cy.finishedLoading();
- cy.get('input[formcontrolname="globalSearch"]').clear().type(title);
+ cy.get('[data-cy="text-search"]').clear().type(title);
+ cy.get('[data-cy="search-button"]').click();
cy.isLoading();
@@ -374,7 +379,8 @@ describe("Datasets general", () => {
cy.finishedLoading();
- cy.get('input[formcontrolname="globalSearch"]').clear().type(title);
+ cy.get('[data-cy="text-search"]').clear().type(title);
+ cy.get('[data-cy="search-button"]').click();
cy.isLoading();
@@ -398,7 +404,8 @@ describe("Datasets general", () => {
cy.finishedLoading();
- cy.get('input[formcontrolname="globalSearch"]').clear().type(title);
+ cy.get('[data-cy="text-search"]').clear().type(title);
+ cy.get('[data-cy="search-button"]').click();
cy.isLoading();
@@ -417,7 +424,8 @@ describe("Datasets general", () => {
cy.finishedLoading();
- cy.get('input[formcontrolname="globalSearch"]').clear().type(title);
+ cy.get('[data-cy="text-search"]').clear().type(title);
+ cy.get('[data-cy="search-button"]').click();
cy.isLoading();
@@ -534,10 +542,12 @@ describe("Datasets general", () => {
cy.finishedLoading();
- cy.get('input[formcontrolname="globalSearch"]')
+ cy.get('[data-cy="text-search"]')
.clear()
.type(userPublishedDataTitle);
+ cy.get('[data-cy="search-button"]').click();
+
cy.isLoading();
cy.get("app-publisheddata-dashboard mat-table mat-row")
diff --git a/src/app/publisheddata/publisheddata-dashboard/publisheddata-dashboard.component.html b/src/app/publisheddata/publisheddata-dashboard/publisheddata-dashboard.component.html
index c5870c83e5..162ca51a1c 100644
--- a/src/app/publisheddata/publisheddata-dashboard/publisheddata-dashboard.component.html
+++ b/src/app/publisheddata/publisheddata-dashboard/publisheddata-dashboard.component.html
@@ -1,11 +1,21 @@
-
-
+
diff --git a/src/app/publisheddata/publisheddata-dashboard/publisheddata-dashboard.component.spec.ts b/src/app/publisheddata/publisheddata-dashboard/publisheddata-dashboard.component.spec.ts
index 7024155b90..792202cef3 100644
--- a/src/app/publisheddata/publisheddata-dashboard/publisheddata-dashboard.component.spec.ts
+++ b/src/app/publisheddata/publisheddata-dashboard/publisheddata-dashboard.component.spec.ts
@@ -10,18 +10,13 @@ import { MockStore, createMock, mockPublishedData } from "shared/MockStubs";
import { NO_ERRORS_SCHEMA } from "@angular/core";
import { StoreModule, Store } from "@ngrx/store";
import { Router } from "@angular/router";
-import { CheckboxEvent } from "shared/modules/table/table.component";
-import { MatCheckboxChange } from "@angular/material/checkbox";
-import { of } from "rxjs";
-import { Message, MessageType } from "state-management/models";
-import { showMessageAction } from "state-management/actions/user.actions";
import { FlexLayoutModule } from "@ngbracket/ngx-layout";
import { MatButtonModule } from "@angular/material/button";
import { MatIconModule } from "@angular/material/icon";
import { AppConfigService } from "app-config.service";
import { ScicatDataService } from "shared/services/scicat-data-service";
import { ExportExcelService } from "shared/services/export-excel.service";
-import { PublishedData } from "@scicatproject/scicat-sdk-ts-angular";
+import { RowEventType } from "shared/modules/dynamic-material-table/models/table-row.model";
const getConfig = () => ({});
@@ -83,31 +78,15 @@ describe("PublisheddataDashboardComponent", () => {
expect(component).toBeTruthy();
});
- describe("#onShareClick()", () => {
- it("should copy the selected DOI's to the users clipboard and dispatch a showMessageAction", () => {
- const commandSpy = spyOn(document, "execCommand");
- dispatchSpy = spyOn(store, "dispatch");
-
- const message = new Message(
- "The selected DOI's have been copied to your clipboard",
- MessageType.Success,
- 5000,
- );
-
- component.onShareClick();
-
- expect(commandSpy).toHaveBeenCalledTimes(1);
- expect(commandSpy).toHaveBeenCalledWith("copy");
- expect(dispatchSpy).toHaveBeenCalledTimes(1);
- expect(dispatchSpy).toHaveBeenCalledWith(showMessageAction({ message }));
- });
- });
-
- describe("#onRowClick", () => {
+ describe("#onRowEvent", () => {
it("should navigate to a Published Dataset", () => {
const published = mockPublishedData;
const id = encodeURIComponent(published.doi);
- component.onRowClick(published);
+
+ component.onRowEvent({
+ event: RowEventType.RowClick,
+ sender: { row: published },
+ } as any);
expect(router.navigateByUrl).toHaveBeenCalledTimes(1);
expect(router.navigateByUrl).toHaveBeenCalledWith(
@@ -115,86 +94,4 @@ describe("PublisheddataDashboardComponent", () => {
);
});
});
-
- describe("#onSelectAll()", () => {
- it("should add all DOI's to selectedDOIs if checked is true", () => {
- const published = createMock({
- doi: "test",
- title: "test",
- abstract: "test",
- datasetPids: [],
- createdAt: "",
- registeredTime: "",
- status: PublishedData.StatusEnum.private,
- updatedAt: "",
- metadata: {
- creators: ["test creator"],
- publisher: { name: "test" },
- publicationYear: 2021,
- resourceType: "test",
- },
- });
-
- spyOn(component.vm$, "pipe").and.returnValue(
- of({ publishedData: [published] }),
- );
-
- const event = {
- event: {
- checked: true,
- },
- selection: { selected: [published] },
- };
-
- component.onSelectAll(event as any);
-
- expect(component.selectedDOIs.length).toEqual(1);
- });
-
- it("should remove all DOI's from selectedDOIs if checked is false", () => {
- component.selectedDOIs.push(
- component.doiBaseUrl + "test1",
- component.doiBaseUrl + "test2",
- );
-
- const event = {
- event: {
- checked: false,
- },
- selection: [],
- };
-
- component.onSelectAll(event as any);
-
- expect(component.selectedDOIs.length).toEqual(0);
- });
- });
-
- describe("#onSelectOne()", () => {
- it("should add the selected DOI to selectedDOIs if checked is true", () => {
- const checkboxEvent: CheckboxEvent = {
- event: { checked: true } as MatCheckboxChange,
- row: { doi: "test" },
- };
-
- component.onSelectOne(checkboxEvent);
-
- expect(component.selectedDOIs).toContain(
- component.doiBaseUrl + checkboxEvent.row.doi,
- );
- });
-
- it("should remove the deselected DOI from selectedDOIs if checked is false", () => {
- const checkboxEvent: CheckboxEvent = {
- event: { checked: false } as MatCheckboxChange,
- row: { doi: "test" },
- };
-
- component.selectedDOIs.push(component.doiBaseUrl + checkboxEvent.row.doi);
-
- component.onSelectOne(checkboxEvent);
-
- expect(component.selectedDOIs.length).toEqual(0);
- });
- });
});
diff --git a/src/app/publisheddata/publisheddata-dashboard/publisheddata-dashboard.component.ts b/src/app/publisheddata/publisheddata-dashboard/publisheddata-dashboard.component.ts
index 57f7c7dd3e..f66ffb2ef8 100644
--- a/src/app/publisheddata/publisheddata-dashboard/publisheddata-dashboard.component.ts
+++ b/src/app/publisheddata/publisheddata-dashboard/publisheddata-dashboard.component.ts
@@ -1,21 +1,29 @@
-import { Component, OnInit, OnDestroy, Inject } from "@angular/core";
+import { Component, OnInit, OnDestroy } from "@angular/core";
import { Store } from "@ngrx/store";
import { PublishedData } from "@scicatproject/scicat-sdk-ts-angular";
import { Router } from "@angular/router";
import { selectPublishedDataDashboardPageViewModel } from "state-management/selectors/published-data.selectors";
-import { CheckboxEvent } from "shared/modules/table/table.component";
-import { Subscription } from "rxjs";
-
-import { MatCheckboxChange } from "@angular/material/checkbox";
-import { DOCUMENT } from "@angular/common";
-import { Message, MessageType } from "state-management/models";
-import { showMessageAction } from "state-management/actions/user.actions";
-import { Column } from "shared/modules/shared-table/shared-table.module";
-import { SciCatDataSource } from "shared/services/scicat.datasource";
+import { BehaviorSubject, Subscription, take } from "rxjs";
import { AppConfigService } from "app-config.service";
import { ScicatDataService } from "shared/services/scicat-data-service";
import { ExportExcelService } from "shared/services/export-excel.service";
-import { SelectionModel } from "@angular/cdk/collections";
+import { TableField } from "shared/modules/dynamic-material-table/models/table-field.model";
+import {
+ TablePagination,
+ TablePaginationMode,
+} from "shared/modules/dynamic-material-table/models/table-pagination.model";
+import {
+ ITableSetting,
+ TableSettingEventType,
+} from "shared/modules/dynamic-material-table/models/table-setting.model";
+import { actionMenu } from "shared/modules/dynamic-material-table/utilizes/default-table-settings";
+import { SciCatDataSource } from "shared/services/scicat.datasource";
+import {
+ IRowEvent,
+ RowEventType,
+} from "shared/modules/dynamic-material-table/models/table-row.model";
+import { TableConfigService } from "shared/services/table-config.service";
+import { updateUserSettingsAction } from "state-management/actions/user.actions";
@Component({
selector: "app-publisheddata-dashboard",
@@ -25,78 +33,68 @@ import { SelectionModel } from "@angular/cdk/collections";
})
export class PublisheddataDashboardComponent implements OnInit, OnDestroy {
public vm$ = this.store.select(selectPublishedDataDashboardPageViewModel);
- columns: Column[] = [
- {
- id: "doi",
- label: "DOI",
- canSort: true,
- icon: "fingerprint",
- matchMode: "contains",
- hideOrder: 0,
- },
- {
- id: "title",
- label: "Title",
- icon: "description",
- canSort: true,
- matchMode: "contains",
- hideOrder: 1,
- },
- {
- id: "creator",
- label: "Creator",
- icon: "face",
- canSort: true,
- matchMode: "contains",
- hideOrder: 2,
- },
- {
- id: "status",
- label: "Status",
- icon: "face",
- canSort: true,
- matchMode: "contains",
- hideOrder: 3,
- },
- {
- id: "createdBy",
- icon: "account_circle",
- label: "Created by",
- canSort: true,
- matchMode: "contains",
- hideOrder: 4,
- },
- {
- id: "createdAt",
- icon: "date_range",
- label: "Created at",
- format: "date",
- canSort: true,
- matchMode: "between",
- hideOrder: 5,
+
+ columns: TableField[] = [];
+ setting: ITableSetting = {};
+
+ tableName = "publishedDataTable";
+ rowSelectionMode: "single" | "multi" | "none" = "none";
+ paginationMode: TablePaginationMode = "server-side";
+ pending = false;
+ globalTextSearch = "";
+
+ tableDefaultSettingsConfig: ITableSetting = {
+ visibleActionMenu: actionMenu,
+ settingList: [
+ {
+ visibleActionMenu: actionMenu,
+ isDefaultSetting: true,
+ isCurrentSetting: true,
+ columnSetting: [
+ { name: "doi", header: "DOI", index: 0 },
+ { name: "title", header: "Title", index: 1 },
+ { name: "creator", header: "Creator", index: 2 },
+ { name: "status", header: "Status", index: 3 },
+ { name: "createdBy", header: "Created by", index: 4 },
+ { name: "createdAt", header: "Created at", index: 5 },
+ ],
+ },
+ ],
+ rowStyle: {
+ "border-bottom": "1px solid #d2d2d2",
},
- ];
+ };
+
+ pagination: TablePagination = {
+ pageSize: 5,
+ pageIndex: 0,
+ pageSizeOptions: [5, 10, 25, 100],
+ length: 0,
+ };
+
tableDefinition = {
collection: "publishedData",
columns: this.columns,
apiVersion: "v4",
};
- dataSource: SciCatDataSource;
- select = true;
- doiBaseUrl = "https://doi.org/";
- selectedDOIs: string[] = [];
- filtersSubscription: Subscription = new Subscription();
+ dataSource: BehaviorSubject = new BehaviorSubject<
+ PublishedData[]
+ >([]);
+ scicatDataSource: SciCatDataSource;
+
+ subscriptions: Subscription[] = [];
+ currentFilters: any = {};
constructor(
- @Inject(DOCUMENT) private document: Document,
private router: Router,
private store: Store,
private appConfigService: AppConfigService,
private dataService: ScicatDataService,
private exportService: ExportExcelService,
+ private tableConfigService: TableConfigService,
) {
- this.dataSource = new SciCatDataSource(
+ this.scicatDataSource = new SciCatDataSource(
this.appConfigService,
this.dataService,
this.exportService,
@@ -104,64 +102,129 @@ export class PublisheddataDashboardComponent implements OnInit, OnDestroy {
);
}
- onShareClick() {
- const selectionBox = this.document.createElement("textarea");
- selectionBox.style.position = "fixed";
- selectionBox.style.left = "0";
- selectionBox.style.top = "0";
- selectionBox.style.opacity = "0";
- selectionBox.value = this.selectedDOIs.join("\n");
- this.document.body.appendChild(selectionBox);
- selectionBox.focus();
- selectionBox.select();
- this.document.execCommand("copy");
- this.document.body.removeChild(selectionBox);
-
- const message = new Message(
- "The selected DOI's have been copied to your clipboard",
- MessageType.Success,
- 5000,
+ ngOnInit() {
+ this.subscriptions.push(
+ this.vm$.pipe(take(1)).subscribe((vm) => {
+ this.currentFilters = vm.filters;
+ const { skip, limit } = vm.filters;
+ const pageIndex = skip / limit;
+
+ this.loadData(vm.filters, pageIndex, limit);
+
+ const tableSettingsConfig =
+ this.tableConfigService.getTableSettingsConfig(
+ this.tableName,
+ this.tableDefaultSettingsConfig,
+ vm.tablesSettings?.columns || [],
+ );
+
+ const currentColumnSetting = tableSettingsConfig.settingList.find(
+ (s) => s.isCurrentSetting,
+ )?.columnSetting;
+
+ this.columns = currentColumnSetting;
+ this.setting = tableSettingsConfig;
+
+ this.pagination = {
+ ...this.pagination,
+ length: vm.count,
+ pageIndex,
+ pageSize: limit,
+ };
+ }),
+ );
+
+ this.subscriptions.push(
+ this.scicatDataSource.connect().subscribe((data) => {
+ this.dataSource.next(data);
+ }),
+ );
+
+ this.subscriptions.push(
+ this.scicatDataSource.count$.subscribe((count) => {
+ this.pagination = { ...this.pagination, length: count };
+ }),
);
- this.store.dispatch(showMessageAction({ message }));
}
- onRowClick(published: PublishedData) {
- const id = encodeURIComponent(published.doi);
- this.router.navigateByUrl("/publishedDatasets/" + id);
+ onRowEvent(event: IRowEvent) {
+ if (event?.event === RowEventType.RowClick) {
+ const id = encodeURIComponent(event.sender.row.doi);
+ this.router.navigateByUrl("/publishedDatasets/" + id);
+ }
+ }
+
+ onPaginationChange(pagination: TablePagination) {
+ const pageIndex = pagination.pageIndex;
+ const pageSize = pagination.pageSize;
+ const newFilters = {
+ ...this.currentFilters,
+ skip: pageIndex * pageSize,
+ limit: pageSize,
+ };
+
+ this.loadData(newFilters, pageIndex, pageSize);
+ }
+
+ saveTableSettings(setting: ITableSetting) {
+ const columnsSetting = setting.columnSetting.map((column, index) => {
+ const { name, display, width } = column;
+
+ return { name, display, order: index, width };
+ });
+
+ this.store.dispatch(
+ updateUserSettingsAction({
+ property: { fe_publisheddata_table_columns: columnsSetting },
+ }),
+ );
}
- onSelectAll(event: {
- event: MatCheckboxChange;
- selection: SelectionModel;
+ onSettingChange(event: {
+ type: TableSettingEventType;
+ setting: ITableSetting;
}) {
- if (event.event.checked) {
- this.selectedDOIs = event.selection.selected.map(
- ({ doi }) => this.doiBaseUrl + encodeURIComponent(doi),
- );
- } else {
- this.selectedDOIs = [];
+ if (
+ event.type === TableSettingEventType.save ||
+ event.type === TableSettingEventType.create
+ ) {
+ this.saveTableSettings(event.setting);
}
}
- onSelectOne(checkboxEvent: CheckboxEvent) {
- const { event, row } = checkboxEvent;
- const doiUrl = this.doiBaseUrl + encodeURIComponent(row.doi);
- if (event.checked) {
- this.selectedDOIs.push(doiUrl);
- } else {
- this.selectedDOIs.splice(this.selectedDOIs.indexOf(doiUrl), 1);
- }
+ onGlobalTextSearchChange(text: string) {
+ this.globalTextSearch = text;
}
- ngOnInit() {
- this.filtersSubscription = this.vm$.subscribe((vm) => {
- this.router.navigate(["/publishedDatasets"], {
- queryParams: { args: JSON.stringify(vm.filters) },
- });
- });
+ onGlobalTextSearchAction() {
+ const newFilters = {
+ ...this.currentFilters,
+ skip: 0,
+ limit: this.pagination.pageSize,
+ globalSearch: this.globalTextSearch || undefined,
+ };
+
+ this.loadData(newFilters, 0, this.pagination.pageSize);
+ this.currentFilters = newFilters;
+ }
+
+ getSort(filters: any) {
+ const sortField = filters?.sortField;
+ return sortField ? sortField.split(" ") : ["", "asc"];
+ }
+
+ loadData(filters: any, pageIndex: number, pageSize: number) {
+ const [field, direction] = this.getSort(filters);
+ this.scicatDataSource.loadAllData(
+ filters,
+ field,
+ direction,
+ pageIndex,
+ pageSize,
+ );
}
ngOnDestroy() {
- this.filtersSubscription.unsubscribe();
+ this.subscriptions.forEach((sub) => sub.unsubscribe());
}
}
diff --git a/src/app/state-management/effects/user.effects.spec.ts b/src/app/state-management/effects/user.effects.spec.ts
index 6e2df86840..95100a7983 100644
--- a/src/app/state-management/effects/user.effects.spec.ts
+++ b/src/app/state-management/effects/user.effects.spec.ts
@@ -619,6 +619,7 @@ describe("UserEffects", () => {
fe_sample_table_conditions: [],
fe_instrument_table_columns: [],
fe_file_table_columns: [],
+ fe_publisheddata_table_columns: [],
},
} as unknown as UserSettings;
const action = fromActions.fetchUserSettingsAction({ id });
diff --git a/src/app/state-management/models/index.ts b/src/app/state-management/models/index.ts
index 16ce256ff8..99b02a59b9 100644
--- a/src/app/state-management/models/index.ts
+++ b/src/app/state-management/models/index.ts
@@ -19,6 +19,7 @@ export interface Settings {
fe_sample_table_conditions?: ConditionConfig[];
fe_instrument_table_columns?: TableColumn[];
fe_file_table_columns?: TableColumn[];
+ fe_publisheddata_table_columns?: TableColumn[];
}
export interface TableColumn {
@@ -220,6 +221,11 @@ export const SETTINGS_CONFIG = [
configKey: "columns",
},
{ key: "fe_file_table_columns", scope: "file", configKey: "columns" },
+ {
+ key: "fe_publisheddata_table_columns",
+ scope: "publisheddata",
+ configKey: "columns",
+ },
];
export type SettingScope =
@@ -227,7 +233,8 @@ export type SettingScope =
| "proposal"
| "sample"
| "instrument"
- | "file";
+ | "file"
+ | "publisheddata";
export type SettingKind = "columns" | "filters" | "conditions";
export const getSettingKey = (
diff --git a/src/app/state-management/selectors/published-data.selectors.spec.ts b/src/app/state-management/selectors/published-data.selectors.spec.ts
index 0d9aa26381..00b3763aa0 100644
--- a/src/app/state-management/selectors/published-data.selectors.spec.ts
+++ b/src/app/state-management/selectors/published-data.selectors.spec.ts
@@ -3,6 +3,7 @@ import { PublishedDataState } from "state-management/state/published-data.store"
import * as fromSelectors from "./published-data.selectors";
import { createMock } from "shared/MockStubs";
import { PublishedData } from "@scicatproject/scicat-sdk-ts-angular";
+import { initialUserState } from "./user.selectors.spec";
const publishedData = createMock({
doi: "testDOI",
@@ -108,6 +109,7 @@ describe("Published Data Selectors", () => {
fromSelectors.selectPage.projector(initialPublishedDataState.filters),
initialPublishedDataState.filters.limit,
initialPublishedDataState.filters,
+ initialUserState.settings,
),
).toEqual({
publishedData: [],
@@ -119,6 +121,9 @@ describe("Published Data Selectors", () => {
skip: 0,
limit: 25,
},
+ tablesSettings: {
+ columns: initialUserState.settings.fe_publisheddata_table_columns,
+ },
});
});
});
diff --git a/src/app/state-management/selectors/published-data.selectors.ts b/src/app/state-management/selectors/published-data.selectors.ts
index cd9dc71c46..d5e9c2f0ee 100644
--- a/src/app/state-management/selectors/published-data.selectors.ts
+++ b/src/app/state-management/selectors/published-data.selectors.ts
@@ -1,5 +1,6 @@
import { createFeatureSelector, createSelector } from "@ngrx/store";
import { PublishedDataState } from "state-management/state/published-data.store";
+import { selectSettings } from "./user.selectors";
const selectPublishedDataState =
createFeatureSelector("publishedData");
@@ -45,12 +46,23 @@ export const selectPublishedDataDashboardPageViewModel = createSelector(
selectPage,
selectPublishedDataPerPage,
selectFilters,
- (publishedData, count, currentPage, publishedDataPerPage, filters) => ({
+ selectSettings,
+ (
publishedData,
count,
currentPage,
publishedDataPerPage,
filters,
+ settings,
+ ) => ({
+ publishedData,
+ count,
+ currentPage,
+ publishedDataPerPage,
+ filters,
+ tablesSettings: {
+ columns: settings.fe_publisheddata_table_columns,
+ },
}),
);
diff --git a/src/app/state-management/state/user.store.ts b/src/app/state-management/state/user.store.ts
index 9e01a3c661..a9dbdc3a67 100644
--- a/src/app/state-management/state/user.store.ts
+++ b/src/app/state-management/state/user.store.ts
@@ -79,6 +79,7 @@ export const initialUserState: UserState = {
fe_sample_table_conditions: [],
fe_instrument_table_columns: [],
fe_file_table_columns: [],
+ fe_publisheddata_table_columns: [],
}, // TODO sync with server settings?
message: undefined,