Add delete artifact button. Refactor for updated Angular.

This commit is contained in:
Brian Hood 2024-04-29 16:05:21 -05:00
parent e4af78213d
commit a982ad6c45
5 changed files with 105 additions and 6 deletions

View File

@ -27,6 +27,11 @@ import {MAT_TOOLTIP_DEFAULT_OPTIONS, MatTooltipDefaultOptions} from '@angular/ma
import {UpdateNotifierComponent} from '@common/shared/ui-components/overlay/update-notifier/update-notifier.component';
import {ChooseColorModule} from '@common/shared/ui-components/directives/choose-color/choose-color.module';
import {SpinnerComponent} from '@common/shared/ui-components/overlay/spinner/spinner.component';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { UploadArtifactDialogComponent } from '@common/shared/ui-components/overlay/upload-artifact-dialog/upload-artifact-dialog.component';
@NgModule({
declarations : [AppComponent],
@ -61,6 +66,10 @@ import {SpinnerComponent} from '@common/shared/ui-components/overlay/spinner/spi
UpdateNotifierComponent,
ChooseColorModule,
SpinnerComponent,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
UploadArtifactDialogComponent
],
providers : [
UserPreferences,

View File

@ -18,6 +18,7 @@
</sm-labeled-row>
<sm-labeled-row label="FILE SIZE" data-id="fileSizeId">{{(artifact?.content_size | filesize : fileSizeConfigStorage) || ''}}</sm-labeled-row>
<sm-labeled-row label="HASH" data-id="hashId">{{artifact?.hash}}</sm-labeled-row>
<sm-labeled-row label="MODE" data-id="modeId">{{artifact?.mode | titlecase}}</sm-labeled-row>
<sm-labeled-row *ngFor="let data of artifact?.display_data" [label]="data[0]| uppercase">{{data[1]}}</sm-labeled-row>
</div>
</sm-editable-section>
@ -32,5 +33,5 @@
[formData]="artifact?.type_data?.preview"
></sm-scroll-textarea>
</sm-editable-section>
<button *ngIf="enableDeleteButton()" class="btn btn-neon" style="margin: auto;" (click)="deleteArtifact(artifact?.key, artifact?.mode)">DELETE ARTIFACT</button>

View File

@ -1,12 +1,27 @@
import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
import {ChangeDetectionStrategy, Component, Input, Inject} from '@angular/core';
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
import {Artifact} from '~/business-logic/model/tasks/artifact';
import {BaseClickableArtifactComponent} from '../base-clickable-artifact.component';
import {fileSizeConfigStorage} from '@common/shared/pipes/filesize.pipe';
import { ApiTasksService } from '~/business-logic/api-services/tasks.service';
import { ConfirmDialogComponent } from '@common/shared/ui-components/overlay/confirm-dialog/confirm-dialog.component';
import { take } from 'rxjs/operators';
import { addMessage } from '@common/core/actions/layout.actions';
import { Observable } from 'rxjs/internal/Observable';
import { IExperimentInfo } from '~/features/experiments/shared/experiment-info.model';
import { selectExperimentInfoData } from '~/features/experiments/reducers';
import { ArtifactId } from '~/business-logic/model/tasks/artifactId';
import { deleteS3Sources } from '@common/shared/entity-page/entity-delete/common-delete-dialog.actions';
import { EXPERIMENTS_STATUS_LABELS } from '~/features/experiments/shared/experiments.const';
@Component({
selector: 'sm-experiment-artifact-item-view',
templateUrl: './experiment-artifact-item-view.component.html',
styleUrls: ['./experiment-artifact-item-view.component.scss'],
providers: [
{ provide: MAT_DIALOG_DATA, useValue: {} },
{ provide: MatDialogRef, useValue: {} }
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ExperimentArtifactItemViewComponent extends BaseClickableArtifactComponent{
@ -14,11 +29,28 @@ export class ExperimentArtifactItemViewComponent extends BaseClickableArtifactCo
public isLinkable: boolean;
public fileSizeConfigStorage = fileSizeConfigStorage;
public inMemorySize: boolean;
public experimentInfo$: Observable<IExperimentInfo>;
private _artifact: Artifact;
private artifactId: ArtifactId;
private _experiment: any;
@Input() editable: boolean;
@Input() downloading: boolean;
constructor(
@Inject(MAT_DIALOG_DATA) public data: ConfirmDialogComponent,
public dialogRef: MatDialogRef<ConfirmDialogComponent>,
private dialog: MatDialog,
private tasksApi: ApiTasksService,
){
super();
this.experimentInfo$ = this.store.select(selectExperimentInfoData);
this.artifactId = {key: '', mode: 'output'};
this.experimentInfo$.subscribe((res) => {
this._experiment = res;
});
}
@Input() set artifact(artifact: Artifact) {
this._artifact = artifact;
if(artifact){
@ -39,6 +71,14 @@ export class ExperimentArtifactItemViewComponent extends BaseClickableArtifactCo
return this._artifact;
}
getStatusLabel() {
return EXPERIMENTS_STATUS_LABELS[this._experiment?.status] || '';
}
enableDeleteButton() {
return this.getStatusLabel() === 'Draft';
}
linkClicked(event: Event) {
this.signUrl(this.artifact.uri).subscribe(signed => {
const a = document.createElement('a');
@ -48,4 +88,34 @@ export class ExperimentArtifactItemViewComponent extends BaseClickableArtifactCo
});
event.preventDefault();
}
deleteArtifact(key, mode) {
this.artifactId = {key: key, mode: mode};
const confirmDialogRef: MatDialogRef<any, boolean> = this.dialog.open(ConfirmDialogComponent, {
data: {
title: 'Delete Artifact',
body: 'Are you sure you want to delete artifact ' + key + ' from the experiment and S3?<br /><strong>This cannot be undone.</strong>',
yes: 'Delete',
no: 'Cancel',
iconClass: 'al-icon al-ico-trash al-color blue-300',
}
});
confirmDialogRef.afterClosed().pipe(take(1)).subscribe((confirmed) => {
if (confirmed) {
this.tasksApi.tasksDeleteArtifacts({
/* eslint-disable @typescript-eslint/naming-convention */
task: this._experiment.id,
artifacts: [this.artifactId]
/* eslint-enable @typescript-eslint/naming-convention */
}, null, 'body', true).subscribe({
next: () => {
this.store.dispatch(deleteS3Sources({files: [this.artifact.uri]}))
},
error: err => this.store.dispatch(addMessage('error', `Error ${err.error?.meta?.result_msg}`)),
complete: () => this.store.dispatch(addMessage('success', 'Artifact deleted successfully.')),
});
}
});
}
}

View File

@ -242,7 +242,7 @@ export class BaseAdminService {
Bucket: bucketKeyEndpoint.Bucket,
Delete: {
Quiet: true,
Objects: files.map(file => ({Key: file} as ObjectIdentifier))
Objects: files.map(() => ({Key: bucketKeyEndpoint.Key} as ObjectIdentifier))
}
});
/* eslint-enable @typescript-eslint/naming-convention */

View File

@ -1,6 +1,6 @@
import { Component, Inject, Input, OnDestroy, OnInit, TemplateRef } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { FormsModule, ReactiveFormsModule, FormControl, FormGroup, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { addMessage } from '@common/core/actions/layout.actions';
import { UploadArtifactDialogConfig, ArtifactType } from './upload-artifact-dialog.model';
@ -15,11 +15,30 @@ import { getSignedUrl } from '@common/core/actions/common-auth.actions';
import { selectExperimentExecutionInfoData } from '@common/experiments/reducers';
import { ArtifactModeEnum } from '~/business-logic/model/tasks/artifactModeEnum';
import { ConfirmDialogComponent } from '../confirm-dialog/confirm-dialog.component';
import { DialogTemplateComponent } from '@common/shared/ui-components/overlay/dialog-template/dialog-template.component';
import { CommonModule } from '@angular/common';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { SafePipe } from '@common/shared/pipes/safe.pipe';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
@Component({
selector: 'sm-upload-artifact-dialog',
templateUrl: './upload-artifact-dialog.component.html',
styleUrls: ['./upload-artifact-dialog.component.scss']
styleUrls: ['./upload-artifact-dialog.component.scss'],
standalone: true,
imports: [
SafePipe,
FormsModule,
ReactiveFormsModule,
DialogTemplateComponent,
CommonModule,
MatInputModule,
MatFormFieldModule,
MatSelectModule,
MatRadioModule,
]
})
export class UploadArtifactDialogComponent implements OnInit, OnDestroy {
artifactType: ArtifactType[] = [
@ -216,7 +235,7 @@ export class UploadArtifactDialogComponent implements OnInit, OnDestroy {
type: this.uploadForm.controls['artType'].value,
content_size: item.size,
timestamp: ts,
hash: 'SHA256: ' + fileHash,
hash: fileHash,
uri: this.uploadUrl + item.name,
mode: this.uploadForm.controls['mode'].value as ArtifactModeEnum
});