diff --git a/src/app/shared/entry/info-tab-topic/display-topic/display-topic.component.spec.ts b/src/app/shared/entry/info-tab-topic/display-topic/display-topic.component.spec.ts
new file mode 100644
index 0000000000..2d4bfe6f39
--- /dev/null
+++ b/src/app/shared/entry/info-tab-topic/display-topic/display-topic.component.spec.ts
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2024 OICR and UCSC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { DisplayTopicComponent } from './display-topic.component';
+import { EntryTypeMetadataStubService } from 'app/test/service-stubs';
+import { MatLegacyDialogModule } from '@angular/material/legacy-dialog';
+import { EntryTypeMetadataService } from 'app/entry/type-metadata/entry-type-metadata.service';
+import { sampleWorkflow1 } from 'app/test/mocked-objects';
+
+describe('DisplayTopicComponent', () => {
+ let component: DisplayTopicComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(
+ waitForAsync(() => {
+ TestBed.configureTestingModule({
+ providers: [{ provide: EntryTypeMetadataService, useClass: EntryTypeMetadataStubService }],
+ imports: [MatLegacyDialogModule, DisplayTopicComponent],
+ }).compileComponents();
+ })
+ );
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DisplayTopicComponent);
+ component = fixture.componentInstance;
+ component.entry = sampleWorkflow1;
+ component.disableEditing = false;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/shared/entry/info-tab-topic/display-topic/display-topic.component.ts b/src/app/shared/entry/info-tab-topic/display-topic/display-topic.component.ts
new file mode 100644
index 0000000000..afe061932e
--- /dev/null
+++ b/src/app/shared/entry/info-tab-topic/display-topic/display-topic.component.ts
@@ -0,0 +1,61 @@
+import { AsyncPipe, NgIf, TitleCasePipe } from '@angular/common';
+import { Component, Input, OnDestroy, OnInit } from '@angular/core';
+import { MatIconModule } from '@angular/material/icon';
+import { MatLegacyButtonModule } from '@angular/material/legacy-button';
+import { MatLegacyDialog } from '@angular/material/legacy-dialog';
+import { MatLegacyTooltipModule } from '@angular/material/legacy-tooltip';
+import { Base } from 'app/shared/base';
+import { DockstoreTool, Entry, EntryTypeMetadata, Workflow } from 'app/shared/openapi';
+import { SessionQuery } from 'app/shared/session/session.query';
+import { Observable } from 'rxjs';
+import { EditTopicDialogComponent } from '../edit-topic/edit-topic-dialog.component';
+import { bootstrap4largeModalSize } from 'app/shared/constants';
+import { AiBubbleComponent } from 'app/shared/ai-bubble/ai-bubble.component';
+import { FlexModule } from '@ngbracket/ngx-layout';
+
+@Component({
+ selector: 'app-display-topic',
+ templateUrl: './display-topic.component.html',
+ styleUrls: ['../../../styles/info-tab.component.scss'],
+ standalone: true,
+ imports: [NgIf, MatLegacyTooltipModule, MatLegacyButtonModule, MatIconModule, AsyncPipe, AiBubbleComponent, FlexModule, TitleCasePipe],
+})
+export class DisplayTopicComponent extends Base implements OnInit, OnDestroy {
+ TopicSelectionEnum = Entry.TopicSelectionEnum;
+ isPublic$: Observable;
+ isGitHubAppEntry: boolean;
+ entryTypeMetadata: EntryTypeMetadata;
+ selectedTopic: string;
+ @Input() entry: DockstoreTool | Workflow;
+ @Input() disableEditing: boolean;
+ constructor(private sessionQuery: SessionQuery, private dialog: MatLegacyDialog) {
+ super();
+ }
+
+ ngOnInit(): void {
+ this.isPublic$ = this.sessionQuery.isPublic$;
+ this.entryTypeMetadata = this.entry.entryTypeMetadata;
+ this.isGitHubAppEntry = (this.entry as Workflow).mode === Workflow.ModeEnum.DOCKSTOREYML; // Only Workflow has DOCKSTOREYML ModeEnum
+ }
+
+ ngOnChanges(): void {
+ this.selectedTopic = this.getSelectedTopic();
+ }
+
+ editTopic() {
+ this.dialog.open(EditTopicDialogComponent, { width: bootstrap4largeModalSize, data: { entry: this.entry } });
+ }
+
+ private getSelectedTopic(): string | null {
+ switch (this.entry.topicSelection) {
+ case this.TopicSelectionEnum.MANUAL:
+ return this.entry.topicManual;
+ case this.TopicSelectionEnum.AUTOMATIC:
+ return this.entry.topicAutomatic;
+ case this.TopicSelectionEnum.AI:
+ return this.entry.topicAI;
+ default:
+ return null;
+ }
+ }
+}
diff --git a/src/app/shared/entry/info-tab-topic/edit-topic/edit-topic-dialog.component.html b/src/app/shared/entry/info-tab-topic/edit-topic/edit-topic-dialog.component.html
new file mode 100644
index 0000000000..141fccc903
--- /dev/null
+++ b/src/app/shared/entry/info-tab-topic/edit-topic/edit-topic-dialog.component.html
@@ -0,0 +1,78 @@
+
Select a Topic
+
+
+ A topic is a short description of your {{ entryTypeMetadata.term }}. There are {{ isHostedEntry ? 'two' : 'three' }} types of topics
+ that you can choose from:
+
+
+
+
+
+
+ edit
+ Manual
+
+
+ Entered manually by the user{{ isGitHubAppEntry ? ' in the .dockstore.yml file on GitHub' : '' }}.
+
+
+ {{ entry.topicManual || 'Not Available' }}
+
+
+
+
+
+
+
+
+
+ sync
+ Automatic
+
+
Retrieved automatically from the GitHub repository description.
+
+ {{ entry.topicAutomatic || 'Not Available' }}
+
+
+
+
+
+
+
+ AI
+
+
Generated by AI using the content of your {{ entryTypeMetadata.term }}.
+
{{ entry.topicAI || 'Not Available' }}
+
+
+
+
+
+
+
+
+
diff --git a/src/app/shared/entry/info-tab-topic/edit-topic/edit-topic-dialog.component.scss b/src/app/shared/entry/info-tab-topic/edit-topic/edit-topic-dialog.component.scss
new file mode 100644
index 0000000000..7a9b2dbddd
--- /dev/null
+++ b/src/app/shared/entry/info-tab-topic/edit-topic/edit-topic-dialog.component.scss
@@ -0,0 +1,9 @@
+// This style ensures that the mat radio content text fills up the whole mat-card
+:host ::ng-deep .mat-radio-label-content {
+ width: 100%;
+}
+
+// Wraps the text because by default, mat-radio-label doesn't wrap
+:host ::ng-deep .mat-radio-label {
+ white-space: normal;
+}
diff --git a/src/app/shared/entry/info-tab-topic/edit-topic/edit-topic-dialog.component.spec.ts b/src/app/shared/entry/info-tab-topic/edit-topic/edit-topic-dialog.component.spec.ts
new file mode 100644
index 0000000000..ad5efac85e
--- /dev/null
+++ b/src/app/shared/entry/info-tab-topic/edit-topic/edit-topic-dialog.component.spec.ts
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2024 OICR and UCSC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { EditTopicDialogStubService, EntryActionsStubService, EntryTypeMetadataStubService } from 'app/test/service-stubs';
+import { MAT_LEGACY_DIALOG_DATA, MatLegacyDialogModule, MatLegacyDialogRef } from '@angular/material/legacy-dialog';
+import { EntryTypeMetadataService } from 'app/entry/type-metadata/entry-type-metadata.service';
+import { sampleWorkflow1 } from 'app/test/mocked-objects';
+import { EditTopicDialogComponent } from './edit-topic-dialog.component';
+import { EditTopicDialogService } from './edit-topic-dialog.service';
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { EntryActionsService } from 'app/shared/entry-actions/entry-actions.service';
+
+describe('EditTopicDialogComponent', () => {
+ let component: EditTopicDialogComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(
+ waitForAsync(() => {
+ TestBed.configureTestingModule({
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ { provide: EntryTypeMetadataService, useClass: EntryTypeMetadataStubService },
+ { provide: EditTopicDialogService, useClass: EditTopicDialogStubService },
+ { provide: EntryActionsService, useClass: EntryActionsStubService },
+ {
+ provide: MatLegacyDialogRef,
+ useValue: {
+ close: (dialogResult: any) => {},
+ },
+ },
+ {
+ provide: MAT_LEGACY_DIALOG_DATA,
+ useValue: { entry: sampleWorkflow1 },
+ },
+ ],
+ imports: [EditTopicDialogComponent, BrowserAnimationsModule],
+ }).compileComponents();
+ })
+ );
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(EditTopicDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/shared/entry/info-tab-topic/edit-topic/edit-topic-dialog.component.ts b/src/app/shared/entry/info-tab-topic/edit-topic/edit-topic-dialog.component.ts
new file mode 100644
index 0000000000..613585065b
--- /dev/null
+++ b/src/app/shared/entry/info-tab-topic/edit-topic/edit-topic-dialog.component.ts
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2024 OICR and UCSC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Component, Inject } from '@angular/core';
+import { MatLegacyDialogRef, MatLegacyDialogModule, MAT_LEGACY_DIALOG_DATA } from '@angular/material/legacy-dialog';
+import { MatLegacyButtonModule } from '@angular/material/legacy-button';
+import { FlexModule } from '@ngbracket/ngx-layout/flex';
+import { MatLegacyInputModule } from '@angular/material/legacy-input';
+import { MatLegacyFormFieldModule } from '@angular/material/legacy-form-field';
+import { NgIf } from '@angular/common';
+import { MatDividerModule } from '@angular/material/divider';
+import { AlertComponent } from 'app/shared/alert/alert.component';
+import { DockstoreTool, Entry, EntryType, EntryTypeMetadata, Workflow } from 'app/shared/openapi';
+import { MatLegacyTooltipModule } from '@angular/material/legacy-tooltip';
+import { AiBubbleComponent } from 'app/shared/ai-bubble/ai-bubble.component';
+import { FormsModule } from '@angular/forms';
+import { MatLegacyRadioModule } from '@angular/material/legacy-radio';
+import { MatIconModule } from '@angular/material/icon';
+import { MatLegacyCardModule } from '@angular/material/legacy-card';
+import { EditTopicDialogService } from './edit-topic-dialog.service';
+import { EntryActionsService } from 'app/shared/entry-actions/entry-actions.service';
+
+export interface EditTopicDialogData {
+ entry: DockstoreTool | Workflow;
+}
+
+@Component({
+ selector: 'app-edit-topic-dialog',
+ templateUrl: './edit-topic-dialog.component.html',
+ styleUrls: ['./edit-topic-dialog.component.scss'],
+ standalone: true,
+ imports: [
+ MatLegacyDialogModule,
+ AlertComponent,
+ MatDividerModule,
+ NgIf,
+ MatLegacyFormFieldModule,
+ MatLegacyInputModule,
+ FlexModule,
+ MatLegacyButtonModule,
+ MatLegacyTooltipModule,
+ AiBubbleComponent,
+ FormsModule,
+ MatLegacyRadioModule,
+ MatIconModule,
+ MatLegacyCardModule,
+ ],
+})
+export class EditTopicDialogComponent {
+ TopicSelectionEnum = Entry.TopicSelectionEnum;
+ entry: Workflow | DockstoreTool;
+ entryType: EntryType;
+ entryTypeMetadata: EntryTypeMetadata;
+ isGitHubAppEntry: boolean;
+ isHostedEntry: boolean;
+ topicEditing: boolean;
+ selectedOption: Entry.TopicSelectionEnum;
+ editedTopicManual: string;
+
+ constructor(
+ public dialogRef: MatLegacyDialogRef,
+ public editTopicDialogService: EditTopicDialogService,
+ public entryActionsService: EntryActionsService,
+ @Inject(MAT_LEGACY_DIALOG_DATA) public data: EditTopicDialogData
+ ) {
+ this.entry = data.entry;
+ this.entryType = data.entry.entryType;
+ this.entryTypeMetadata = data.entry.entryTypeMetadata;
+ this.isGitHubAppEntry = (data.entry as Workflow).mode === Workflow.ModeEnum.DOCKSTOREYML; // Only Workflow has DOCKSTOREYML ModeEnum
+ this.isHostedEntry = this.entryActionsService.isEntryHosted(data.entry);
+ this.selectedOption = data.entry.topicSelection;
+ this.editedTopicManual = data.entry.topicManual;
+ }
+
+ saveTopic() {
+ this.editTopicDialogService.saveTopicChanges(this.entry, this.editedTopicManual, this.selectedOption);
+ }
+}
diff --git a/src/app/shared/entry/info-tab-topic/edit-topic/edit-topic-dialog.service.ts b/src/app/shared/entry/info-tab-topic/edit-topic/edit-topic-dialog.service.ts
new file mode 100644
index 0000000000..59fd114250
--- /dev/null
+++ b/src/app/shared/entry/info-tab-topic/edit-topic/edit-topic-dialog.service.ts
@@ -0,0 +1,48 @@
+import { Injectable } from '@angular/core';
+import { AlertService } from '../../../alert/state/alert.service';
+import { ContainersService, DockstoreTool, EntryType, Workflow, WorkflowsService } from '../../../openapi';
+import { WorkflowService } from '../../../state/workflow.service';
+import { ContainerService } from '../../../container.service';
+
+@Injectable()
+export class EditTopicDialogService {
+ constructor(
+ private alertService: AlertService,
+ private workflowsService: WorkflowsService,
+ private workflowService: WorkflowService,
+ private containersService: ContainersService,
+ private containerService: ContainerService
+ ) {}
+
+ saveTopicChanges(entry: Workflow | DockstoreTool, topicManual: string, topicSelection: Workflow.TopicSelectionEnum) {
+ this.alertService.start('Saving topic changes');
+ const newEntryForUpdate = { ...entry, topicManual: topicManual, topicSelection: topicSelection };
+
+ if (entry.entryType === EntryType.TOOL) {
+ this.containersService.updateContainer(entry.id, newEntryForUpdate as DockstoreTool).subscribe(
+ (response) => {
+ this.alertService.detailedSuccess();
+ const newTopicSelection = response.topicSelection;
+ this.containerService.updateActiveTopicSelection(newTopicSelection);
+ const newTopic = response.topicManual;
+ this.containerService.updateActiveTopic(newTopic);
+ },
+ (error) => {
+ this.alertService.detailedError(error);
+ }
+ );
+ } else {
+ this.workflowsService.updateWorkflow(entry.id, newEntryForUpdate as Workflow).subscribe(
+ (response) => {
+ this.alertService.detailedSuccess();
+ const newTopicSelection = response.topicSelection;
+ const newTopic = response.topicManual;
+ this.workflowService.updateActiveTopicManualAndTopicSelection(newTopic, newTopicSelection);
+ },
+ (error) => {
+ this.alertService.detailedError(error);
+ }
+ );
+ }
+ }
+}
diff --git a/src/app/shared/state/workflow.service.ts b/src/app/shared/state/workflow.service.ts
index 828710f68b..f9067a3a27 100644
--- a/src/app/shared/state/workflow.service.ts
+++ b/src/app/shared/state/workflow.service.ts
@@ -53,14 +53,8 @@ export class WorkflowService {
}
}
- updateActiveTopic(topic: string) {
- const newWorkflow = { ...this.workflowQuery.getActive(), topicManual: topic };
- this.workflowStore.upsert(newWorkflow.id, newWorkflow);
- this.extendedWorkflowService.update(newWorkflow);
- }
-
- updateActiveTopicSelection(topicSelection: Workflow.TopicSelectionEnum) {
- const newWorkflow = { ...this.workflowQuery.getActive(), topicSelection: topicSelection };
+ updateActiveTopicManualAndTopicSelection(topicManual: string, topicSelection: Workflow.TopicSelectionEnum) {
+ const newWorkflow = { ...this.workflowQuery.getActive(), topicManual: topicManual, topicSelection: topicSelection };
this.workflowStore.upsert(newWorkflow.id, newWorkflow);
this.extendedWorkflowService.update(newWorkflow);
}
diff --git a/src/app/container/info-tab/info-tab.component.css b/src/app/shared/styles/info-tab.component.scss
similarity index 96%
rename from src/app/container/info-tab/info-tab.component.css
rename to src/app/shared/styles/info-tab.component.scss
index b5351685e0..874ec6db35 100644
--- a/src/app/container/info-tab/info-tab.component.css
+++ b/src/app/shared/styles/info-tab.component.scss
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 OICR
+ * Copyright 2024 OICR and UCSC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/app/test/mocked-objects.ts b/src/app/test/mocked-objects.ts
index 9fb8b42348..992c7fac6b 100644
--- a/src/app/test/mocked-objects.ts
+++ b/src/app/test/mocked-objects.ts
@@ -18,7 +18,7 @@ import { OrgToolObject } from '../mytools/my-tool/my-tool.component';
import { Hit } from '../search/state/search.service';
import { ExtendedDockstoreTool } from '../shared/models/ExtendedDockstoreTool';
import { ExtendedWorkflow } from '../shared/models/ExtendedWorkflow';
-import { VersionVerifiedPlatform, Tag, WorkflowVersion, Author } from '../shared/openapi';
+import { VersionVerifiedPlatform, Tag, WorkflowVersion, Author, EntryTypeMetadata } from '../shared/openapi';
import { Notification } from '../shared/openapi/model/notification';
import { DockstoreTool } from './../shared/openapi/model/dockstoreTool';
import { SourceFile } from './../shared/openapi/model/sourceFile';
@@ -27,6 +27,61 @@ import { Workflow } from './../shared/openapi/model/workflow';
const DescriptorTypeEnum = Workflow.DescriptorTypeEnum;
+export const toolEntryTypeMetadata: EntryTypeMetadata = {
+ searchEntryType: 'tools',
+ searchSupported: true,
+ sitePath: 'containers',
+ term: 'tool',
+ termPlural: 'tools',
+ trsPrefix: '',
+ trsSupported: true,
+ type: 'TOOL',
+};
+
+export const workflowEntryTypeMetadata: EntryTypeMetadata = {
+ searchEntryType: 'workflows',
+ searchSupported: true,
+ sitePath: 'workflows',
+ term: 'workflow',
+ termPlural: 'workflows',
+ trsPrefix: '#workflow/',
+ trsSupported: true,
+ type: 'WORKFLOW',
+};
+
+export const serviceEntryTypeMetadata: EntryTypeMetadata = {
+ searchEntryType: '',
+ searchSupported: false,
+ sitePath: 'services',
+ term: 'service',
+ termPlural: 'services',
+ trsPrefix: '#service/',
+ trsSupported: true,
+ type: 'SERVICE',
+};
+
+export const appToolEntryTypeMetadata: EntryTypeMetadata = {
+ searchEntryType: 'tools',
+ searchSupported: true,
+ sitePath: 'containers',
+ term: 'tool',
+ termPlural: 'tools',
+ trsPrefix: '',
+ trsSupported: true,
+ type: 'APPTOOL',
+};
+
+export const notebookEntryTypeMetadata: EntryTypeMetadata = {
+ searchEntryType: '',
+ searchSupported: false,
+ sitePath: 'notebooks',
+ term: 'notebook',
+ termPlural: 'notebooks',
+ trsPrefix: '#notebook/',
+ trsSupported: true,
+ type: 'NOTEBOOK',
+};
+
export const updatedWorkflow: Workflow = {
type: '',
descriptorType: DescriptorTypeEnum.CWL,
@@ -40,6 +95,7 @@ export const updatedWorkflow: Workflow = {
sourceControl: 'github.com',
source_control_provider: 'GITHUB',
descriptorTypeSubclass: 'n/a',
+ entryTypeMetadata: workflowEntryTypeMetadata,
};
export const sampleWorkflow1: Workflow = {
@@ -56,6 +112,7 @@ export const sampleWorkflow1: Workflow = {
sourceControl: 'github.com',
source_control_provider: 'GITHUB',
descriptorTypeSubclass: 'n/a',
+ entryTypeMetadata: workflowEntryTypeMetadata,
};
export const sampleWorkflow2: Workflow = {
@@ -72,6 +129,7 @@ export const sampleWorkflow2: Workflow = {
sourceControl: 'github.com',
source_control_provider: 'GITHUB',
descriptorTypeSubclass: 'n/a',
+ entryTypeMetadata: workflowEntryTypeMetadata,
};
export const sampleWorkflow3: Workflow = {
@@ -89,6 +147,7 @@ export const sampleWorkflow3: Workflow = {
source_control_provider: 'GITHUB',
full_workflow_path: 'github.com/sampleWorkflowPath',
descriptorTypeSubclass: 'n/a',
+ entryTypeMetadata: workflowEntryTypeMetadata,
};
export const sampleWdlWorkflow1: Workflow = {
@@ -106,6 +165,7 @@ export const sampleWdlWorkflow1: Workflow = {
source_control_provider: 'GITHUB',
full_workflow_path: 'github.com/DataBiosphere/topmed-workflows/Functional_Equivalence',
descriptorTypeSubclass: 'n/a',
+ entryTypeMetadata: workflowEntryTypeMetadata,
};
export const sampleCwlExtendedWorkflow: ExtendedWorkflow = {
@@ -123,6 +183,7 @@ export const sampleCwlExtendedWorkflow: ExtendedWorkflow = {
source_control_provider: 'GITHUB',
full_workflow_path: 'github.com/dockstore-testing/md5sum-checker',
descriptorTypeSubclass: 'n/a',
+ entryTypeMetadata: workflowEntryTypeMetadata,
};
export const sampleWdlWorkflow2: Workflow = {
@@ -140,6 +201,7 @@ export const sampleWdlWorkflow2: Workflow = {
source_control_provider: 'GITHUB',
full_workflow_path: 'github.com/DataBiosphere/topmed-workflows/UM_aligner_wdl',
descriptorTypeSubclass: 'n/a',
+ entryTypeMetadata: workflowEntryTypeMetadata,
};
export const sampleWorkflowVersion: WorkflowVersion = {
@@ -179,6 +241,7 @@ export const sampleTool1: DockstoreTool = {
defaultCWLTestParameterFile: 'sampleDefaultCWLTestParameterFile',
defaultWDLTestParameterFile: 'sampleDefaultWDLTestParameterFile',
tool_path: '',
+ entryTypeMetadata: toolEntryTypeMetadata,
};
export const sampleTool2: DockstoreTool = {
@@ -196,6 +259,7 @@ export const sampleTool2: DockstoreTool = {
toolname: 'sampleToolname',
defaultCWLTestParameterFile: 'sampleDefaultCWLTestParameterFile',
defaultWDLTestParameterFile: 'sampleDefaultWDLTestParameterFile',
+ entryTypeMetadata: toolEntryTypeMetadata,
};
export const sampleTool3: DockstoreTool = {
@@ -213,6 +277,7 @@ export const sampleTool3: DockstoreTool = {
toolname: 'sampleToolname',
defaultCWLTestParameterFile: 'sampleDefaultCWLTestParameterFile',
defaultWDLTestParameterFile: 'sampleDefaultWDLTestParameterFile',
+ entryTypeMetadata: toolEntryTypeMetadata,
};
// Case 1: sampleTool1 in published entries, unpublished doesn't matter
diff --git a/src/app/test/service-stubs.ts b/src/app/test/service-stubs.ts
index fe735af383..c2e4e26f66 100644
--- a/src/app/test/service-stubs.ts
+++ b/src/app/test/service-stubs.ts
@@ -38,7 +38,20 @@ import { TokenUser } from './../shared/openapi/model/tokenUser';
import { User } from './../shared/openapi/model/user';
import { Workflow } from './../shared/openapi/model/workflow';
import { WorkflowVersion } from './../shared/openapi/model/workflowVersion';
-import { bitbucketToken, gitHubToken, gitLabToken, quayToken, sampleTag, sampleWorkflow1, updatedWorkflow } from './mocked-objects';
+import {
+ appToolEntryTypeMetadata,
+ bitbucketToken,
+ gitHubToken,
+ gitLabToken,
+ notebookEntryTypeMetadata,
+ quayToken,
+ sampleTag,
+ sampleWorkflow1,
+ serviceEntryTypeMetadata,
+ toolEntryTypeMetadata,
+ updatedWorkflow,
+ workflowEntryTypeMetadata,
+} from './mocked-objects';
import RoleEnum = Permission.RoleEnum;
import DescriptorTypeEnum = Workflow.DescriptorTypeEnum;
@@ -935,64 +948,19 @@ export class EntryTypeMetadataStubService {
get(type: newEntryType): EntryTypeMetadata {
switch (type) {
case newEntryType.WORKFLOW: {
- return {
- searchEntryType: 'workflows',
- searchSupported: true,
- sitePath: 'workflows',
- term: 'workflow',
- termPlural: 'workflows',
- trsPrefix: '#workflow/',
- trsSupported: true,
- type: 'WORKFLOW',
- };
+ return workflowEntryTypeMetadata;
}
case newEntryType.TOOL: {
- return {
- searchEntryType: 'tools',
- searchSupported: true,
- sitePath: 'containers',
- term: 'tool',
- termPlural: 'tools',
- trsPrefix: '',
- trsSupported: true,
- type: 'TOOL',
- };
+ return toolEntryTypeMetadata;
}
case newEntryType.SERVICE: {
- return {
- searchEntryType: '',
- searchSupported: false,
- sitePath: 'services',
- term: 'service',
- termPlural: 'services',
- trsPrefix: '#service/',
- trsSupported: true,
- type: 'SERVICE',
- };
+ return serviceEntryTypeMetadata;
}
case newEntryType.APPTOOL: {
- return {
- searchEntryType: 'tools',
- searchSupported: true,
- sitePath: 'containers',
- term: 'tool',
- termPlural: 'tools',
- trsPrefix: '',
- trsSupported: true,
- type: 'APPTOOL',
- };
+ return appToolEntryTypeMetadata;
}
case newEntryType.NOTEBOOK: {
- return {
- searchEntryType: '',
- searchSupported: false,
- sitePath: 'notebooks',
- term: 'notebook',
- termPlural: 'notebooks',
- trsPrefix: '#notebook/',
- trsSupported: true,
- type: 'NOTEBOOK',
- };
+ return notebookEntryTypeMetadata;
}
}
return null;
@@ -1010,4 +978,9 @@ export class MarkdownWrapperStubService {
export class EntryActionsStubService {
updateBackingEntry(entry) {}
+ isEntryHosted(entry) {}
+}
+
+export class EditTopicDialogStubService {
+ saveTopicChanges(entry: Workflow | DockstoreTool, topicManual: string, topicSelection: Workflow.TopicSelectionEnum) {}
}
diff --git a/src/app/workflow/info-tab/info-tab.component.css b/src/app/workflow/info-tab/info-tab.component.css
index efe631b0b2..71b2c025d5 100644
--- a/src/app/workflow/info-tab/info-tab.component.css
+++ b/src/app/workflow/info-tab/info-tab.component.css
@@ -27,19 +27,3 @@
.mat-column-orcid_id {
width: 20rem;
}
-
-/* Bootstrap adds a 5px bottom margin, this counteracts it. Remove once Bootstrap is removed */
-::ng-deep label {
- margin-bottom: 0px;
-}
-
-/* Better alignment for "save" icon instead of vertical-align: middle */
-.mat-icon-sm {
- vertical-align: text-bottom;
-}
-
-/* Disabled state for "edit" buttons */
-.mat-raised-button.mat-button-disabled.mat-button-disabled {
- background-color: white;
- filter: opacity(0.3);
-}
diff --git a/src/app/workflow/info-tab/info-tab.component.html b/src/app/workflow/info-tab/info-tab.component.html
index c33827b346..a58db562c9 100644
--- a/src/app/workflow/info-tab/info-tab.component.html
+++ b/src/app/workflow/info-tab/info-tab.component.html
@@ -193,120 +193,12 @@
-