diff --git a/src/app/app.module.ts b/src/app/app.module.ts index b6fe4e0..5489021 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -86,6 +86,7 @@ import { ExperimentWorkspaceDetailComponent } from './components/experiment-work import { PluginFilterNodeComponent } from './components-small/plugin-filter-node/plugin-filter-node.component'; import { PluginFilterEditorComponent } from './components-small/plugin-filter-editor/plugin-filter-editor.component'; import { TabGroupListComponent } from './components/tab-group-list/tab-group-list.component'; +import { ChooseTemplateComponent } from './dialogs/choose-template/choose-template.component'; @NgModule({ declarations: [ @@ -131,6 +132,7 @@ import { TabGroupListComponent } from './components/tab-group-list/tab-group-lis PluginFilterNodeComponent, PluginFilterEditorComponent, TabGroupListComponent, + ChooseTemplateComponent, ], imports: [ BrowserModule, diff --git a/src/app/components/experiment/experiment.component.html b/src/app/components/experiment/experiment.component.html index 6bf7aea..f832857 100644 --- a/src/app/components/experiment/experiment.component.html +++ b/src/app/components/experiment/experiment.component.html @@ -31,26 +31,24 @@

Experiment

cancel - - - Default Template - - - - - - -- none -- - - - {{uiTemplateName}} - - - - {{template.value}} - - - + +
+ + Default Template: + + + {{uiTemplate?.name ?? 'All Plugins'}} + + + + +
diff --git a/src/app/components/experiment/experiment.component.sass b/src/app/components/experiment/experiment.component.sass index edfdfeb..723a618 100644 --- a/src/app/components/experiment/experiment.component.sass +++ b/src/app/components/experiment/experiment.component.sass @@ -36,3 +36,15 @@ display: inline-flex align-items: center gap: 0.5em + +.experiment-settings + display: flex + flex-direction: column + gap: 1rem + +.default-template-selection + display: flex + flex-direction: row + justify-content: flex-start + align-items: center + gap: 1rem \ No newline at end of file diff --git a/src/app/components/experiment/experiment.component.ts b/src/app/components/experiment/experiment.component.ts index 8d4e22a..ff4d709 100644 --- a/src/app/components/experiment/experiment.component.ts +++ b/src/app/components/experiment/experiment.component.ts @@ -1,15 +1,13 @@ -import { KeyValue } from '@angular/common'; import { Component, OnDestroy, OnInit } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; import { BehaviorSubject, Subscription } from 'rxjs'; import { debounceTime, filter, map } from 'rxjs/operators'; import { ExportExperimentDialog } from 'src/app/dialogs/export-experiment/export-experiment.component'; -import { PageApiObject } from 'src/app/services/api-data-types'; +import { ChooseTemplateComponent } from 'src/app/dialogs/choose-template/choose-template.component'; import { CurrentExperimentService } from 'src/app/services/current-experiment.service'; import { ExperimentApiObject, QhanaBackendService } from 'src/app/services/qhana-backend.service'; -import { PluginRegistryBaseService } from 'src/app/services/registry.service'; -import { TemplatesService } from 'src/app/services/templates.service'; +import { TemplateApiObject, TemplatesService } from 'src/app/services/templates.service'; @Component({ selector: 'qhana-experiment', @@ -38,15 +36,9 @@ export class ExperimentComponent implements OnInit, OnDestroy { experimentDescription: string = ""; // only updated on initial experiment load currentExperimentDescription: string = ""; - readonly itemCount: number = 10; - uiTemplatePageIndex: number = 0; + uiTemplate: TemplateApiObject | null = null; - uiTemplates: Map = new Map(); - uiTemplateId: string | null = null; - uiTemplateName: string | null = null; - uiTemplateCollectionSize: number = 0; - - constructor(private route: ActivatedRoute, private router: Router, private experimentService: CurrentExperimentService, private backend: QhanaBackendService, private registry: PluginRegistryBaseService, private templates: TemplatesService, public dialog: MatDialog) { } + constructor(private route: ActivatedRoute, private router: Router, private experimentService: CurrentExperimentService, private backend: QhanaBackendService, private templates: TemplatesService, public dialog: MatDialog) { } ngOnInit(): void { this.routeSubscription = this.route.params.pipe(map(params => params.experimentId)).subscribe(experimentId => { @@ -60,16 +52,14 @@ export class ExperimentComponent implements OnInit, OnDestroy { this.lastSavedDescription = experiment?.description ?? ""; this.experimentDescription = experiment?.description ?? ""; this.currentExperimentDescription = experiment?.description ?? ""; - this.uiTemplateId = experiment?.templateId?.toString() ?? null; }); this.uiTemplateIdSubscription = this.experimentService.experimentTemplateId.subscribe(templateId => { - this.uiTemplateId = templateId?.toString() ?? null; - this.getTemplatePage(); - if (this.uiTemplateId == null) { + if (templateId == null) { + this.uiTemplate = null; return; } - this.templates.getTemplate(this.uiTemplateId).then(template => { - this.uiTemplateName = template?.data.name ?? null; + this.templates.getTemplate(templateId.toString()).then(templateResponse => { + this.uiTemplate = templateResponse?.data ?? null; }); }); this.autoSaveTitleSubscription = this.titleUpdates.pipe( @@ -180,39 +170,23 @@ export class ExperimentComponent implements OnInit, OnDestroy { }); } - async changeDefaultTemplate(templateId: string | null) { + showSelectDefaultTemplateDialog() { + const dialogRef = this.dialog.open(ChooseTemplateComponent, { + minWidth: "20rem", maxWidth: "40rem", width: "60%", + }); + dialogRef.afterClosed().subscribe(templateId => { + if (templateId != null) { + this.updateExperimentDefaultTemplate(templateId); + } + }); + } + + async updateExperimentDefaultTemplate(templateId: string | null) { if (this.experimentId == null) { - this.uiTemplatePageIndex = 0; - this.uiTemplateId = null; - this.uiTemplateName = null; + console.warn("Experiment ID is null!"); return; } - this.uiTemplateName = this.uiTemplates.get(templateId ?? "") ?? null; await this.templates.setExperimentDefaultTemplate(this.experimentId, templateId); this.experimentService.reloadExperiment(); } - - async getTemplatePage(pageIndex: number = 0) { - const uiTemplates = new Map(); - const params = new URLSearchParams(); - params.set("sort", "name"); - params.set("item-count", this.itemCount.toString()); - params.set("cursor", (pageIndex + 1).toString()); - await this.registry.getByRel([["ui-template", "collection"]], params).then(result => { - this.uiTemplateCollectionSize = result?.data.collectionSize ?? 0; - result?.data.items.forEach(item => { - const templateId = item.resourceKey?.uiTemplateId; - const name = item.name; - if (templateId != null && name != null) { - uiTemplates.set(templateId, name); - } - }); - }); - this.uiTemplates = uiTemplates; - this.uiTemplatePageIndex = pageIndex; - } - - originalOrder = (a: KeyValue, b: KeyValue): number => { - return 0; - } } diff --git a/src/app/dialogs/choose-template/choose-template.component.html b/src/app/dialogs/choose-template/choose-template.component.html new file mode 100644 index 0000000..ae2bf39 --- /dev/null +++ b/src/app/dialogs/choose-template/choose-template.component.html @@ -0,0 +1,15 @@ +

Choose Template

+
+
+ + +
+
+
+ + +
\ No newline at end of file diff --git a/src/app/dialogs/choose-template/choose-template.component.sass b/src/app/dialogs/choose-template/choose-template.component.sass new file mode 100644 index 0000000..e69de29 diff --git a/src/app/dialogs/choose-template/choose-template.component.spec.ts b/src/app/dialogs/choose-template/choose-template.component.spec.ts new file mode 100644 index 0000000..a71f02d --- /dev/null +++ b/src/app/dialogs/choose-template/choose-template.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ChooseTemplateComponent } from './choose-template.component'; + +describe('ChooseTemplateDialog', () => { + let component: ChooseTemplateComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ChooseTemplateComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ChooseTemplateComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/dialogs/choose-template/choose-template.component.ts b/src/app/dialogs/choose-template/choose-template.component.ts new file mode 100644 index 0000000..4edb63f --- /dev/null +++ b/src/app/dialogs/choose-template/choose-template.component.ts @@ -0,0 +1,40 @@ +import { Component, OnInit } from '@angular/core'; +import { TemplateApiObject } from 'src/app/services/qhana-backend.service'; +import { MatDialogRef } from '@angular/material/dialog'; +import { ApiLink } from 'src/app/services/api-data-types'; +import { PluginRegistryBaseService } from 'src/app/services/registry.service'; + +@Component({ + selector: 'qhana-choose-template', + templateUrl: './choose-template.component.html', + styleUrls: ['./choose-template.component.sass'] +}) +export class ChooseTemplateComponent implements OnInit { + highlightedTemplateSet: Set = new Set(); + templateId: string | null = null; + + constructor(public dialogRef: MatDialogRef) { } + + ngOnInit(): void { + } + + async selectTemplate(templateLink: ApiLink) { + const templateId = templateLink.resourceKey?.uiTemplateId ?? null; + if (templateId == null) { + return; + } + if (this.highlightedTemplateSet.has(templateId)) { + // double click deselects template + this.highlightedTemplateSet.clear(); + this.templateId = null; + return; + } + this.highlightedTemplateSet.clear(); + this.highlightedTemplateSet = new Set([templateId]); + this.templateId = templateId; + } + + onCancel(): void { + this.dialogRef.close(); + } +}