From f22e69408e6578256ec4b558777533376448b249 Mon Sep 17 00:00:00 2001 From: Nikolaus Glombiewski Date: Wed, 3 Jul 2024 13:42:37 +0200 Subject: [PATCH 1/8] Add dataset expiration option for data manager; --- projects/common/src/lib/common.module.ts | 2 + .../src/lib/datasets/datasets.service.ts | 10 ++ .../time/time-input/time-input.component.html | 0 .../time/time-input/time-input.component.scss | 0 .../time/time-input/time-input.component.ts | 0 projects/common/src/public-api.ts | 1 + projects/core/src/lib/core.module.ts | 2 - projects/core/src/public-api.ts | 1 - projects/manager/src/app/app.module.ts | 2 + .../dataset-editor.component.html | 10 +- .../dataset-editor.component.ts | 24 +---- .../expire-dataset.component.html | 28 ++++++ .../expire-dataset.component.scss | 27 ++++++ .../expire-dataset.component.ts | 91 +++++++++++++++++++ 14 files changed, 168 insertions(+), 30 deletions(-) rename projects/{core => common}/src/lib/time/time-input/time-input.component.html (100%) rename projects/{core => common}/src/lib/time/time-input/time-input.component.scss (100%) rename projects/{core => common}/src/lib/time/time-input/time-input.component.ts (100%) create mode 100644 projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.html create mode 100644 projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.scss create mode 100644 projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.ts diff --git a/projects/common/src/lib/common.module.ts b/projects/common/src/lib/common.module.ts index f72d25dc6..f6a6432d2 100644 --- a/projects/common/src/lib/common.module.ts +++ b/projects/common/src/lib/common.module.ts @@ -58,6 +58,7 @@ import {VegaViewerComponent} from './plots/vega-viewer/vega-viewer.component'; import {ConfirmationComponent} from './dialogs/confirmation/confirmation.component'; import {MeasurementComponent} from './measurement/measurement.component'; import {PercentileBreakpointSelectorComponent} from './colors/percentile-breakpoint-selector/percentile-breakpoint-selector.component'; +import {TimeInputComponent} from './time/time-input/time-input.component'; export const MATERIAL_MODULES = [ MatAutocompleteModule, @@ -110,6 +111,7 @@ const COMMON_COMPONENTS = [ RasterIconComponent, VegaViewerComponent, PercentileBreakpointSelectorComponent, + TimeInputComponent, ]; const COMMON_PIPES = [ diff --git a/projects/common/src/lib/datasets/datasets.service.ts b/projects/common/src/lib/datasets/datasets.service.ts index 2efdc1f58..720c43f2a 100644 --- a/projects/common/src/lib/datasets/datasets.service.ts +++ b/projects/common/src/lib/datasets/datasets.service.ts @@ -5,6 +5,7 @@ import { DatasetDefinition, DatasetListing, DatasetsApi, + ExpirationWithType, MetaDataDefinition, MetaDataSuggestion, OrderBy, @@ -107,4 +108,13 @@ export class DatasetsService { }) .then((response) => response.datasetName); } + + async expireDataset(datasetName: string, expirationChange: ExpirationWithType): Promise { + const datasetApi = await firstValueFrom(this.datasetApi); + + return datasetApi.setDatasetExpiration({ + dataset: datasetName, + expirationChange: expirationChange, + }); + } } diff --git a/projects/core/src/lib/time/time-input/time-input.component.html b/projects/common/src/lib/time/time-input/time-input.component.html similarity index 100% rename from projects/core/src/lib/time/time-input/time-input.component.html rename to projects/common/src/lib/time/time-input/time-input.component.html diff --git a/projects/core/src/lib/time/time-input/time-input.component.scss b/projects/common/src/lib/time/time-input/time-input.component.scss similarity index 100% rename from projects/core/src/lib/time/time-input/time-input.component.scss rename to projects/common/src/lib/time/time-input/time-input.component.scss diff --git a/projects/core/src/lib/time/time-input/time-input.component.ts b/projects/common/src/lib/time/time-input/time-input.component.ts similarity index 100% rename from projects/core/src/lib/time/time-input/time-input.component.ts rename to projects/common/src/lib/time/time-input/time-input.component.ts diff --git a/projects/common/src/public-api.ts b/projects/common/src/public-api.ts index ec3dc0ec7..4008ad174 100644 --- a/projects/common/src/public-api.ts +++ b/projects/common/src/public-api.ts @@ -32,6 +32,7 @@ export * from './lib/symbology/raster-palette-symbology-editor/raster-palette-sy export * from './lib/symbology/raster-symbology-editor/raster-symbology-editor.component'; export * from './lib/symbology/vector-symbology-editor/vector-symbology-editor.component'; export * from './lib/plots/vega-viewer/vega-viewer.component'; +export * from './lib/time/time-input/time-input.component'; // Models export * from './lib/colors/color-breakpoint.model'; diff --git a/projects/core/src/lib/core.module.ts b/projects/core/src/lib/core.module.ts index 5b8dc7ba7..f7ca97037 100644 --- a/projects/core/src/lib/core.module.ts +++ b/projects/core/src/lib/core.module.ts @@ -62,7 +62,6 @@ import { import {SafeStylePipe} from './util/pipes/safe-style.pipe'; import {SmallTimeInteractionComponent} from './time/small-time-interaction/small-time-interaction.component'; import {TimeConfigComponent} from './time/time-config/time-config.component'; -import {TimeInputComponent} from './time/time-input/time-input.component'; import {WorkspaceSettingsComponent} from './project/workspace-settings/workspace-settings.component'; import {ChangeSpatialReferenceComponent} from './project/change-spatial-reference/change-spatial-reference.component'; import {IfGuestDirective} from './util/directives/if-guest.directive'; @@ -289,7 +288,6 @@ const CORE_COMPONENTS = [ TaskListComponent, TemporalRasterAggregationComponent, TimeConfigComponent, - TimeInputComponent, TimeIntervalInputComponent, TimeShiftComponent, TimeSliderComponent, diff --git a/projects/core/src/public-api.ts b/projects/core/src/public-api.ts index 776cef347..eae940195 100644 --- a/projects/core/src/public-api.ts +++ b/projects/core/src/public-api.ts @@ -104,7 +104,6 @@ export * from './lib/tabs/tabs.component'; export * from './lib/tasks/task-list/task-list.component'; export * from './lib/time/small-time-interaction/small-time-interaction.component'; export * from './lib/time/time-config/time-config.component'; -export * from './lib/time/time-input/time-input.component'; export * from './lib/time/time-interval-input/time-interval-input.component'; export * from './lib/time/time-slider/time-slider.component'; export * from './lib/time/time-step-selector/time-step-selector.component'; diff --git a/projects/manager/src/app/app.module.ts b/projects/manager/src/app/app.module.ts index f7062fa0a..820731452 100644 --- a/projects/manager/src/app/app.module.ts +++ b/projects/manager/src/app/app.module.ts @@ -49,6 +49,7 @@ import {CommonConfig, CommonModule} from '@geoengine/common'; import {SymbologyEditorComponent} from './symbology/symbology-editor/symbology-editor.component'; import {ProvenanceComponent} from './provenance/provenance.component'; import {AddDatasetComponent} from './datasets/add-dataset/add-dataset.component'; +import {ExpireDatasetComponent} from './datasets/expire-dataset/expire-dataset.component'; export const MATERIAL_MODULES = [ MatAutocompleteModule, @@ -98,6 +99,7 @@ export const MATERIAL_MODULES = [ SymbologyEditorComponent, ProvenanceComponent, AddDatasetComponent, + ExpireDatasetComponent, ], imports: [ ...MATERIAL_MODULES, diff --git a/projects/manager/src/app/datasets/dataset-editor/dataset-editor.component.html b/projects/manager/src/app/datasets/dataset-editor/dataset-editor.component.html index 8cae1f171..134db3a4e 100644 --- a/projects/manager/src/app/datasets/dataset-editor/dataset-editor.component.html +++ b/projects/manager/src/app/datasets/dataset-editor/dataset-editor.component.html @@ -76,9 +76,9 @@ > Apply - + + + @@ -140,8 +140,6 @@ -
- -
+ } diff --git a/projects/manager/src/app/datasets/dataset-editor/dataset-editor.component.ts b/projects/manager/src/app/datasets/dataset-editor/dataset-editor.component.ts index a3e4c7ee4..16c6602d3 100644 --- a/projects/manager/src/app/datasets/dataset-editor/dataset-editor.component.ts +++ b/projects/manager/src/app/datasets/dataset-editor/dataset-editor.component.ts @@ -4,7 +4,6 @@ import {MatChipInput} from '@angular/material/chips'; import {MatDialog} from '@angular/material/dialog'; import {MatSnackBar} from '@angular/material/snack-bar'; import { - ConfirmationComponent, DatasetsService, RasterSymbology, Symbology, @@ -23,7 +22,7 @@ import { TypedResultDescriptor, VectorResultDescriptorWithType, } from '@geoengine/openapi-client'; -import {BehaviorSubject, firstValueFrom} from 'rxjs'; +import {BehaviorSubject} from 'rxjs'; import {ProvenanceComponent} from '../../provenance/provenance.component'; import {AppConfig} from '../../app-config.service'; @@ -160,25 +159,8 @@ export class DatasetEditorComponent implements OnChanges { } } - async deleteDataset(): Promise { - const dialogRef = this.dialog.open(ConfirmationComponent, { - data: {message: 'Confirm the deletion of the dataset. This cannot be undone.'}, - }); - - const confirm = await firstValueFrom(dialogRef.afterClosed()); - - if (!confirm) { - return; - } - - try { - await this.datasetsService.deleteDataset(this.datasetListing.name); - this.snackBar.open('Dataset successfully deleted.', 'Close', {duration: this.config.DEFAULTS.SNACKBAR_DURATION}); - this.datasetDeleted.emit(); - } catch (error) { - const errorMessage = await errorToText(error, 'Deleting dataset failed.'); - this.snackBar.open(errorMessage, 'Close', {panelClass: ['error-snackbar']}); - } + async emitDeleted(): Promise { + this.datasetDeleted.emit(); } private setUpColorizer(dataset: Dataset): void { diff --git a/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.html b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.html new file mode 100644 index 000000000..5b6235f2d --- /dev/null +++ b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.html @@ -0,0 +1,28 @@ + + + Deletion +
+ Advanced +
+
+ + +
+
+ Delete Meta Data +
+
+ Delete Data +
+
+ Set Expiration Time +
+
+ +
+
+
+ +
+
+
diff --git a/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.scss b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.scss new file mode 100644 index 000000000..93c0e2dcc --- /dev/null +++ b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.scss @@ -0,0 +1,27 @@ +mat-card-header { + display: flex; + justify-content: space-between; +} + +mat-card { + margin: 1rem 1rem 0rem 1rem; +} + +mat-card-content { + margin-top: 1rem; +} + +.toggle { + margin-top: 0.5rem; + text-align: right; +} + +.actions { + text-align: right; + height: 3rem; + padding: 1rem; + + button { + margin: 0.5rem; + } +} diff --git a/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.ts b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.ts new file mode 100644 index 000000000..2fb761ff6 --- /dev/null +++ b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.ts @@ -0,0 +1,91 @@ +import {Component, EventEmitter, Input, Output} from '@angular/core'; +import {MatDialog} from '@angular/material/dialog'; +import moment, {Moment} from 'moment/moment'; +import {FormControl, FormGroup, UntypedFormBuilder, Validators} from '@angular/forms'; +import {DatasetsService, ConfirmationComponent, errorToText} from '@geoengine/common'; +import {ExpirationWithType} from '@geoengine/openapi-client'; +import {firstValueFrom} from 'rxjs'; +import {MatSnackBar} from '@angular/material/snack-bar'; +import {AppConfig} from '../../app-config.service'; + +export interface ExpirationForm { + deleteRecord: FormControl; + deleteData: FormControl; + setExpire: FormControl; + expirationTime: FormControl; +} + +@Component({ + selector: 'geoengine-expire-dataset', + templateUrl: './expire-dataset.component.html', + styleUrl: './expire-dataset.component.scss', +}) +export class ExpireDatasetComponent { + @Input() datasetName!: string; + @Output() datasetDeleted = new EventEmitter(); + + advancedDeletion: boolean; + deletionForm: FormGroup; + + constructor( + private formBuilder: UntypedFormBuilder, + private readonly datasetsService: DatasetsService, + private readonly snackBar: MatSnackBar, + private readonly dialog: MatDialog, + private readonly config: AppConfig, + ) { + this.advancedDeletion = false; + this.deletionForm = this.formBuilder.group({ + deleteRecord: [false, Validators.required], + deleteData: [false, Validators.required], + setExpire: [false, Validators.required], + expirationTime: [moment.utc(), [Validators.required]], + }); + } + + async deleteDatasetFair(): Promise { + const dialogRef = this.dialog.open(ConfirmationComponent, { + data: {message: 'Confirm the deletion of the dataset. This cannot be undone.'}, + }); + + const confirm = await firstValueFrom(dialogRef.afterClosed()); + + if (!confirm) { + return; + } + + try { + let directDelete = true; + if (this.advancedDeletion) { + const formResult = this.getFormResult(); + directDelete = formResult.deletionTimestamp == undefined; + await this.datasetsService.expireDataset(this.datasetName, formResult); + } else { + await this.datasetsService.deleteDataset(this.datasetName); + } + this.snackBar.open('Dataset successfully deleted.', 'Close', {duration: this.config.DEFAULTS.SNACKBAR_DURATION}); + if (directDelete) this.datasetDeleted.emit(); + } catch (error) { + const errorMessage = await errorToText(error, 'Deleting dataset failed.'); + this.snackBar.open(errorMessage, 'Close', {panelClass: ['error-snackbar']}); + } + } + + private getFormResult(): ExpirationWithType { + const values = this.deletionForm.controls; + if (values.setExpire.value) { + return { + deleteData: values.deleteData.value, + deleteRecord: values.deleteRecord.value, + deletionTimestamp: values.expirationTime.value.toDate(), + type: 'setExpire', + }; + } else { + return { + deleteData: values.deleteData.value, + deleteRecord: values.deleteRecord.value, + type: 'setExpire', + }; + } + } +} From 3d4542de74b9072528856cb741424a8a8bb56065 Mon Sep 17 00:00:00 2001 From: Nikolaus Glombiewski Date: Wed, 3 Jul 2024 16:27:30 +0200 Subject: [PATCH 2/8] Temporarily change open api client; --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index de564600d..83033a753 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "@angular/platform-browser-dynamic": "^17.3.0", "@angular/router": "^17.3.0", "@egjs/hammerjs": "^2.0.17", - "@geoengine/openapi-client": "0.0.9", + "@geoengine/openapi-client": "https://github.com/glombiewski/openapi-client/typescript?fair-dataset-deletion", "codemirror": "~5.65.16", "d3": "~7.9.0", "dagre": "~0.8.5", From c18d295c579e9be497ad668a7151c91f15564f0f Mon Sep 17 00:00:00 2001 From: Nikolaus Glombiewski Date: Wed, 3 Jul 2024 16:30:55 +0200 Subject: [PATCH 3/8] Temporarily change open api client; --- package-lock.json | 11 +++++------ package.json | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 76ef0fdbb..02d83c208 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "@angular/platform-browser-dynamic": "^17.3.0", "@angular/router": "^17.3.0", "@egjs/hammerjs": "^2.0.17", - "@geoengine/openapi-client": "0.0.9", + "@geoengine/openapi-client": "https://gitpkg.vercel.app/glombiewski/openapi-client/typescript?fair-dataset-deletion", "codemirror": "~5.65.16", "d3": "~7.9.0", "dagre": "~0.8.5", @@ -3491,8 +3491,8 @@ }, "node_modules/@geoengine/openapi-client": { "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@geoengine/openapi-client/-/openapi-client-0.0.9.tgz", - "integrity": "sha512-wL3dBbys3wfH3e0cZh5/4QCrl+u61DmQ1s24DMrk00QH133LnoPvQcDZLTA3DQH9OD5QUiMT9N9WF5FQKK0Q1A==" + "resolved": "https://gitpkg.vercel.app/glombiewski/openapi-client/typescript?fair-dataset-deletion", + "integrity": "sha512-JLGZED06VVf7Y201039IiNfyTIVKbvB70RmRVgV49Tvb/uo/WqyApvHmlbRpTU0TeNHA0Mqw5qMCxADgwSyPBw==" }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", @@ -24011,9 +24011,8 @@ "dev": true }, "@geoengine/openapi-client": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@geoengine/openapi-client/-/openapi-client-0.0.9.tgz", - "integrity": "sha512-wL3dBbys3wfH3e0cZh5/4QCrl+u61DmQ1s24DMrk00QH133LnoPvQcDZLTA3DQH9OD5QUiMT9N9WF5FQKK0Q1A==" + "version": "https://gitpkg.vercel.app/glombiewski/openapi-client/typescript?fair-dataset-deletion", + "integrity": "sha512-JLGZED06VVf7Y201039IiNfyTIVKbvB70RmRVgV49Tvb/uo/WqyApvHmlbRpTU0TeNHA0Mqw5qMCxADgwSyPBw==" }, "@humanwhocodes/config-array": { "version": "0.11.14", diff --git a/package.json b/package.json index 83033a753..f51220676 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "@angular/platform-browser-dynamic": "^17.3.0", "@angular/router": "^17.3.0", "@egjs/hammerjs": "^2.0.17", - "@geoengine/openapi-client": "https://github.com/glombiewski/openapi-client/typescript?fair-dataset-deletion", + "@geoengine/openapi-client": "https://gitpkg.vercel.app/glombiewski/openapi-client/typescript?fair-dataset-deletion", "codemirror": "~5.65.16", "d3": "~7.9.0", "dagre": "~0.8.5", From ea00c43c5e4274445d6c3696ac48ca60f48080ba Mon Sep 17 00:00:00 2001 From: Nikolaus Glombiewski Date: Thu, 11 Jul 2024 16:45:50 +0200 Subject: [PATCH 4/8] Remove checkbox for deleting data; --- package-lock.json | 4 ++-- .../expire-dataset/expire-dataset.component.html | 3 --- .../expire-dataset/expire-dataset.component.ts | 14 ++++++-------- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index 02d83c208..c867b0d9d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3492,7 +3492,7 @@ "node_modules/@geoengine/openapi-client": { "version": "0.0.9", "resolved": "https://gitpkg.vercel.app/glombiewski/openapi-client/typescript?fair-dataset-deletion", - "integrity": "sha512-JLGZED06VVf7Y201039IiNfyTIVKbvB70RmRVgV49Tvb/uo/WqyApvHmlbRpTU0TeNHA0Mqw5qMCxADgwSyPBw==" + "integrity": "sha512-VceADGwnCL/0YgCifj5xFmYf3DTbwCHGAKyHd1dl3M6ov+gWiWlEkNabPNcEwlsJGpGyXu23WBOXdmFz2WZ/8Q==" }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", @@ -24012,7 +24012,7 @@ }, "@geoengine/openapi-client": { "version": "https://gitpkg.vercel.app/glombiewski/openapi-client/typescript?fair-dataset-deletion", - "integrity": "sha512-JLGZED06VVf7Y201039IiNfyTIVKbvB70RmRVgV49Tvb/uo/WqyApvHmlbRpTU0TeNHA0Mqw5qMCxADgwSyPBw==" + "integrity": "sha512-VceADGwnCL/0YgCifj5xFmYf3DTbwCHGAKyHd1dl3M6ov+gWiWlEkNabPNcEwlsJGpGyXu23WBOXdmFz2WZ/8Q==" }, "@humanwhocodes/config-array": { "version": "0.11.14", diff --git a/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.html b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.html index 5b6235f2d..2a6c4a330 100644 --- a/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.html +++ b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.html @@ -11,9 +11,6 @@
Delete Meta Data
-
- Delete Data -
Set Expiration Time
diff --git a/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.ts b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.ts index 2fb761ff6..71675ec83 100644 --- a/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.ts +++ b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.ts @@ -3,14 +3,13 @@ import {MatDialog} from '@angular/material/dialog'; import moment, {Moment} from 'moment/moment'; import {FormControl, FormGroup, UntypedFormBuilder, Validators} from '@angular/forms'; import {DatasetsService, ConfirmationComponent, errorToText} from '@geoengine/common'; -import {ExpirationWithType} from '@geoengine/openapi-client'; +import {DatasetDeletionType, ExpirationWithType} from '@geoengine/openapi-client'; import {firstValueFrom} from 'rxjs'; import {MatSnackBar} from '@angular/material/snack-bar'; import {AppConfig} from '../../app-config.service'; export interface ExpirationForm { deleteRecord: FormControl; - deleteData: FormControl; setExpire: FormControl; expirationTime: FormControl; } @@ -37,7 +36,6 @@ export class ExpireDatasetComponent { this.advancedDeletion = false; this.deletionForm = this.formBuilder.group({ deleteRecord: [false, Validators.required], - deleteData: [false, Validators.required], setExpire: [false, Validators.required], expirationTime: [moment.utc(), [Validators.required]], }); @@ -73,17 +71,17 @@ export class ExpireDatasetComponent { private getFormResult(): ExpirationWithType { const values = this.deletionForm.controls; + const deletionType = values.deleteRecord.value ? DatasetDeletionType.DeleteRecordAndData : DatasetDeletionType.DeleteData; + if (values.setExpire.value) { return { - deleteData: values.deleteData.value, - deleteRecord: values.deleteRecord.value, + deletionType: deletionType, deletionTimestamp: values.expirationTime.value.toDate(), - type: 'setExpire', + type: 'setExpire' }; } else { return { - deleteData: values.deleteData.value, - deleteRecord: values.deleteRecord.value, + deletionType: deletionType, type: 'setExpire', }; } From 141654f9cdb29bef0524dfa5385d84080926160d Mon Sep 17 00:00:00 2001 From: Nikolaus Glombiewski Date: Thu, 11 Jul 2024 16:51:07 +0200 Subject: [PATCH 5/8] Fix formatting; --- .../src/app/datasets/expire-dataset/expire-dataset.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.ts b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.ts index 71675ec83..c8d725216 100644 --- a/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.ts +++ b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.ts @@ -77,7 +77,7 @@ export class ExpireDatasetComponent { return { deletionType: deletionType, deletionTimestamp: values.expirationTime.value.toDate(), - type: 'setExpire' + type: 'setExpire', }; } else { return { From 8d6ce6c2361df1f1ed68e5746b9481ec12a293f6 Mon Sep 17 00:00:00 2001 From: Nikolaus Glombiewski Date: Thu, 25 Jul 2024 17:15:18 +0200 Subject: [PATCH 6/8] Add check for dataset access status; --- package-lock.json | 4 +- .../src/lib/datasets/datasets.service.ts | 11 +- .../dataset-editor.component.ts | 2 - .../expire-dataset.component.html | 63 +++++---- .../expire-dataset.component.scss | 5 +- .../expire-dataset.component.ts | 124 +++++++++++++++--- 6 files changed, 157 insertions(+), 52 deletions(-) diff --git a/package-lock.json b/package-lock.json index c867b0d9d..c789d0881 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3492,7 +3492,7 @@ "node_modules/@geoengine/openapi-client": { "version": "0.0.9", "resolved": "https://gitpkg.vercel.app/glombiewski/openapi-client/typescript?fair-dataset-deletion", - "integrity": "sha512-VceADGwnCL/0YgCifj5xFmYf3DTbwCHGAKyHd1dl3M6ov+gWiWlEkNabPNcEwlsJGpGyXu23WBOXdmFz2WZ/8Q==" + "integrity": "sha512-J9fjB5cj54FgGiTdhFGTV0aUVkAGxBPoxEJR/zK6TRHuoPBOE39h4iJl4ukTIP4aPa3+Tzcz9TU6z+EJWnE6cA==" }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", @@ -24012,7 +24012,7 @@ }, "@geoengine/openapi-client": { "version": "https://gitpkg.vercel.app/glombiewski/openapi-client/typescript?fair-dataset-deletion", - "integrity": "sha512-VceADGwnCL/0YgCifj5xFmYf3DTbwCHGAKyHd1dl3M6ov+gWiWlEkNabPNcEwlsJGpGyXu23WBOXdmFz2WZ/8Q==" + "integrity": "sha512-J9fjB5cj54FgGiTdhFGTV0aUVkAGxBPoxEJR/zK6TRHuoPBOE39h4iJl4ukTIP4aPa3+Tzcz9TU6z+EJWnE6cA==" }, "@humanwhocodes/config-array": { "version": "0.11.14", diff --git a/projects/common/src/lib/datasets/datasets.service.ts b/projects/common/src/lib/datasets/datasets.service.ts index 720c43f2a..21d302e17 100644 --- a/projects/common/src/lib/datasets/datasets.service.ts +++ b/projects/common/src/lib/datasets/datasets.service.ts @@ -2,10 +2,11 @@ import {Injectable} from '@angular/core'; import { DataPath, Dataset, + DatasetAccessStatusResponse, DatasetDefinition, DatasetListing, DatasetsApi, - ExpirationWithType, + ExpirationChange, MetaDataDefinition, MetaDataSuggestion, OrderBy, @@ -109,7 +110,13 @@ export class DatasetsService { .then((response) => response.datasetName); } - async expireDataset(datasetName: string, expirationChange: ExpirationWithType): Promise { + async getDatasetStatus(datasetName: string): Promise { + const datasetApi = await firstValueFrom(this.datasetApi); + + return datasetApi.getDatasetStatus({dataset: datasetName}); + } + + async expireDataset(datasetName: string, expirationChange: ExpirationChange): Promise { const datasetApi = await firstValueFrom(this.datasetApi); return datasetApi.setDatasetExpiration({ diff --git a/projects/manager/src/app/datasets/dataset-editor/dataset-editor.component.ts b/projects/manager/src/app/datasets/dataset-editor/dataset-editor.component.ts index 16c6602d3..1be3840cf 100644 --- a/projects/manager/src/app/datasets/dataset-editor/dataset-editor.component.ts +++ b/projects/manager/src/app/datasets/dataset-editor/dataset-editor.component.ts @@ -1,7 +1,6 @@ import {Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, ViewChild} from '@angular/core'; import {AbstractControl, FormControl, FormGroup, ValidationErrors, ValidatorFn, Validators} from '@angular/forms'; import {MatChipInput} from '@angular/material/chips'; -import {MatDialog} from '@angular/material/dialog'; import {MatSnackBar} from '@angular/material/snack-bar'; import { DatasetsService, @@ -61,7 +60,6 @@ export class DatasetEditorComponent implements OnChanges { private readonly datasetsService: DatasetsService, private readonly workflowsService: WorkflowsService, private readonly snackBar: MatSnackBar, - private readonly dialog: MatDialog, private readonly config: AppConfig, ) {} diff --git a/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.html b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.html index 2a6c4a330..aaad49f2e 100644 --- a/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.html +++ b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.html @@ -1,25 +1,42 @@ - - - Deletion -
- Advanced -
-
- - -
-
- Delete Meta Data -
-
- Set Expiration Time -
-
- -
-
+@if (canDelete()) { + @if (isUserUpload()) { + + + Deletion + + +
+

+ Status: {{ getStatusString() }} +

+
+ +
+

Current Settings:

+
+
+ Delete Meta Data +
+
+ Expiration Time +
+
+ +
+
+
+
+ + +
+
+
+ } @else {
- +
-
-
+ } +} diff --git a/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.scss b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.scss index 93c0e2dcc..4775bc417 100644 --- a/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.scss +++ b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.scss @@ -11,9 +11,8 @@ mat-card-content { margin-top: 1rem; } -.toggle { - margin-top: 0.5rem; - text-align: right; +h3 { + margin: 0.5rem 0 0.5rem 0; } .actions { diff --git a/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.ts b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.ts index c8d725216..2722ce95f 100644 --- a/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.ts +++ b/projects/manager/src/app/datasets/expire-dataset/expire-dataset.component.ts @@ -1,9 +1,9 @@ -import {Component, EventEmitter, Input, Output} from '@angular/core'; +import {AfterViewInit, Component, EventEmitter, Input, OnChanges, Output, SimpleChanges} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; import moment, {Moment} from 'moment/moment'; import {FormControl, FormGroup, UntypedFormBuilder, Validators} from '@angular/forms'; import {DatasetsService, ConfirmationComponent, errorToText} from '@geoengine/common'; -import {DatasetDeletionType, ExpirationWithType} from '@geoengine/openapi-client'; +import {DatasetAccessStatusResponse, DatasetDeletionType, ExpirationWithType, Permission} from '@geoengine/openapi-client'; import {firstValueFrom} from 'rxjs'; import {MatSnackBar} from '@angular/material/snack-bar'; import {AppConfig} from '../../app-config.service'; @@ -14,17 +14,23 @@ export interface ExpirationForm { expirationTime: FormControl; } +export enum DeletionStatus { + Available, + Expires, + Deleted, +} + @Component({ selector: 'geoengine-expire-dataset', templateUrl: './expire-dataset.component.html', styleUrl: './expire-dataset.component.scss', }) -export class ExpireDatasetComponent { - @Input() datasetName!: string; +export class ExpireDatasetComponent implements AfterViewInit, OnChanges { + @Input() datasetName?: string; @Output() datasetDeleted = new EventEmitter(); - advancedDeletion: boolean; - deletionForm: FormGroup; + datasetStatus: DatasetAccessStatusResponse | undefined; + deletionForm!: FormGroup; constructor( private formBuilder: UntypedFormBuilder, @@ -32,16 +38,93 @@ export class ExpireDatasetComponent { private readonly snackBar: MatSnackBar, private readonly dialog: MatDialog, private readonly config: AppConfig, - ) { - this.advancedDeletion = false; + ) {} + + ngAfterViewInit(): void { + this.setupStatus(); + } + + async ngOnChanges(changes: SimpleChanges): Promise { + if (changes.datasetName) { + this.datasetName = changes.datasetName.currentValue; + this.setupStatus(); + } + } + + async setupStatus(): Promise { + if (!this.datasetName) { + return; + } + + this.datasetStatus = await this.datasetsService.getDatasetStatus(this.datasetName); + const expiration = this.datasetStatus.expiration; + let deleteRecord = false; + if (expiration) { + deleteRecord = expiration.deletionType == DatasetDeletionType.DeleteRecordAndData; + } + let time = moment.utc(); + if (expiration && expiration.deletionTimestamp) { + time = moment(expiration.deletionTimestamp); + } this.deletionForm = this.formBuilder.group({ - deleteRecord: [false, Validators.required], - setExpire: [false, Validators.required], - expirationTime: [moment.utc(), [Validators.required]], + deleteRecord: [deleteRecord, Validators.required], + setExpire: [{value: expiration != null, disabled: !this.datasetStatus.isAvailable}, Validators.required], + expirationTime: [time, [Validators.required]], }); } - async deleteDatasetFair(): Promise { + canDelete(): boolean { + return this.datasetStatus != null && this.datasetStatus.permissions.includes(Permission.Owner); + } + + isUserUpload(): boolean { + return this.datasetStatus != null && this.datasetStatus.isUserUpload; + } + + expires(): boolean { + return this.datasetStatus != null && this.datasetStatus.isAvailable && this.datasetStatus.expiration != null; + } + + getStatusString(): string { + if (this.datasetStatus) { + if (this.datasetStatus.isAvailable && this.datasetStatus.expiration) { + return DeletionStatus[DeletionStatus.Expires]; + } else if (this.datasetStatus.expiration) { + return DeletionStatus[DeletionStatus.Deleted]; + } else { + return DeletionStatus[DeletionStatus.Available]; + } + } + return 'Unknown'; + } + + async deleteDatasetBasic(): Promise { + if (!this.datasetName) { + return; + } + + await this.datasetsService.deleteDataset(this.datasetName); + this.snackBar.open('Dataset successfully deleted.', 'Close', {duration: this.config.DEFAULTS.SNACKBAR_DURATION}); + this.datasetDeleted.emit(); + } + + async resetDeletion(): Promise { + if (this.datasetName && this.datasetStatus && this.datasetStatus.isAvailable) { + try { + await this.datasetsService.expireDataset(this.datasetName, {type: 'unsetExpire'}); + this.setupStatus(); + } catch (error) { + const errorMessage = await errorToText(error, 'Reset deletion failed.'); + this.snackBar.open(errorMessage, 'Close', {panelClass: ['error-snackbar']}); + } + } + } + + async deleteDatasetAdvanced(): Promise { + if (!this.datasetName) { + return; + } + const dialogRef = this.dialog.open(ConfirmationComponent, { data: {message: 'Confirm the deletion of the dataset. This cannot be undone.'}, }); @@ -54,15 +137,16 @@ export class ExpireDatasetComponent { try { let directDelete = true; - if (this.advancedDeletion) { - const formResult = this.getFormResult(); - directDelete = formResult.deletionTimestamp == undefined; - await this.datasetsService.expireDataset(this.datasetName, formResult); + const formResult = this.getFormResult(); + directDelete = formResult.deletionTimestamp == undefined && formResult.deletionType == DatasetDeletionType.DeleteRecordAndData; + await this.datasetsService.expireDataset(this.datasetName, formResult); + if (directDelete) { + this.snackBar.open('Dataset successfully deleted.', 'Close', {duration: this.config.DEFAULTS.SNACKBAR_DURATION}); + this.datasetDeleted.emit(); } else { - await this.datasetsService.deleteDataset(this.datasetName); + this.setupStatus(); + this.snackBar.open('Set dataset expiration date.', 'Close', {duration: this.config.DEFAULTS.SNACKBAR_DURATION}); } - this.snackBar.open('Dataset successfully deleted.', 'Close', {duration: this.config.DEFAULTS.SNACKBAR_DURATION}); - if (directDelete) this.datasetDeleted.emit(); } catch (error) { const errorMessage = await errorToText(error, 'Deleting dataset failed.'); this.snackBar.open(errorMessage, 'Close', {panelClass: ['error-snackbar']}); @@ -73,7 +157,7 @@ export class ExpireDatasetComponent { const values = this.deletionForm.controls; const deletionType = values.deleteRecord.value ? DatasetDeletionType.DeleteRecordAndData : DatasetDeletionType.DeleteData; - if (values.setExpire.value) { + if (!this.deletionForm.controls.setExpire.disabled && values.setExpire.value) { return { deletionType: deletionType, deletionTimestamp: values.expirationTime.value.toDate(), From b10653568df25aee36a8feae0d6c1ba236c5d37c Mon Sep 17 00:00:00 2001 From: Nikolaus Glombiewski Date: Thu, 25 Jul 2024 18:29:26 +0200 Subject: [PATCH 7/8] Temporarily change open api client; --- package-lock.json | 11 +++++------ package.json | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index eb4b0c611..fc4c4f009 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "@angular/platform-browser-dynamic": "^17.3.0", "@angular/router": "^17.3.0", "@egjs/hammerjs": "^2.0.17", - "@geoengine/openapi-client": "0.0.10", + "@geoengine/openapi-client": "https://gitpkg.vercel.app/glombiewski/openapi-client/typescript?fair-dataset-deletion", "codemirror": "~5.65.16", "d3": "~7.9.0", "dagre": "~0.8.5", @@ -3491,8 +3491,8 @@ }, "node_modules/@geoengine/openapi-client": { "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@geoengine/openapi-client/-/openapi-client-0.0.10.tgz", - "integrity": "sha512-xo9k2zlsrZfrOCSGEP7SiGoQ8UK3EQPA886L2lLnqdPHCqYBcbSbTGdhERsj3sHFfnqvVO8vMjNcW585js2PLQ==" + "resolved": "https://gitpkg.vercel.app/glombiewski/openapi-client/typescript?fair-dataset-deletion", + "integrity": "sha512-SDnGLejlH6PiecWnnwBuXGltqqU93/AyggyptqHUliVVubPm87NDKL7i9JD1cRpYX0JuLaoSorTDMNOSS7OeLA==" }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", @@ -24011,9 +24011,8 @@ "dev": true }, "@geoengine/openapi-client": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@geoengine/openapi-client/-/openapi-client-0.0.10.tgz", - "integrity": "sha512-xo9k2zlsrZfrOCSGEP7SiGoQ8UK3EQPA886L2lLnqdPHCqYBcbSbTGdhERsj3sHFfnqvVO8vMjNcW585js2PLQ==" + "version": "https://gitpkg.vercel.app/glombiewski/openapi-client/typescript?fair-dataset-deletion", + "integrity": "sha512-SDnGLejlH6PiecWnnwBuXGltqqU93/AyggyptqHUliVVubPm87NDKL7i9JD1cRpYX0JuLaoSorTDMNOSS7OeLA==" }, "@humanwhocodes/config-array": { "version": "0.11.14", diff --git a/package.json b/package.json index 290de086a..f51220676 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "@angular/platform-browser-dynamic": "^17.3.0", "@angular/router": "^17.3.0", "@egjs/hammerjs": "^2.0.17", - "@geoengine/openapi-client": "0.0.10", + "@geoengine/openapi-client": "https://gitpkg.vercel.app/glombiewski/openapi-client/typescript?fair-dataset-deletion", "codemirror": "~5.65.16", "d3": "~7.9.0", "dagre": "~0.8.5", From a176271b39123d40d2ef119aa3a82de4ab39569b Mon Sep 17 00:00:00 2001 From: Nikolaus Glombiewski Date: Fri, 26 Jul 2024 14:55:47 +0200 Subject: [PATCH 8/8] Remove duplicate import timeinterval import from previous merge; --- projects/common/src/lib/common.module.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/projects/common/src/lib/common.module.ts b/projects/common/src/lib/common.module.ts index 06f999df9..f86d780a6 100644 --- a/projects/common/src/lib/common.module.ts +++ b/projects/common/src/lib/common.module.ts @@ -60,7 +60,6 @@ import {MeasurementComponent} from './measurement/measurement.component'; import {TimeInputComponent} from './time/time-input/time-input.component'; import {TimeIntervalInputComponent} from './time/time-interval-input/time-interval-input.component'; import {PercentileBreakpointSelectorComponent} from './colors/percentile-breakpoint-selector/percentile-breakpoint-selector.component'; -import {TimeInputComponent} from './time/time-input/time-input.component'; export const MATERIAL_MODULES = [ MatAutocompleteModule, @@ -115,7 +114,6 @@ const COMMON_COMPONENTS = [ TimeInputComponent, TimeIntervalInputComponent, PercentileBreakpointSelectorComponent, - TimeInputComponent, ]; const COMMON_PIPES = [