From 28d1c2e1311df44e2327279998defbb86d2e9bb1 Mon Sep 17 00:00:00 2001 From: Vladyslav Zhukovskyi Date: Tue, 12 Nov 2019 10:52:08 +0200 Subject: [PATCH] Add ability to configure borders in quick pick items list on plugin side Signed-off-by: Vladyslav Zhukovskyi --- .../contribution/terminal-command-filter.ts | 9 +- .../contribution/terminal-quick-open.ts | 88 +++++++++++-------- .../task-plugin/src/che-workspace-client.ts | 29 ++++++ .../src/machine/machines-picker.ts | 64 +++++++++++--- 4 files changed, 142 insertions(+), 48 deletions(-) diff --git a/extensions/eclipse-che-theia-terminal/src/browser/contribution/terminal-command-filter.ts b/extensions/eclipse-che-theia-terminal/src/browser/contribution/terminal-command-filter.ts index 7079ac0fe..7d35143c4 100644 --- a/extensions/eclipse-che-theia-terminal/src/browser/contribution/terminal-command-filter.ts +++ b/extensions/eclipse-che-theia-terminal/src/browser/contribution/terminal-command-filter.ts @@ -17,7 +17,10 @@ export const CONTAINER_SOURCE_ATTRIBUTE = 'source'; * Return list containers with recipe source attribute. */ export function filterRecipeContainers(containers: WorkspaceContainer[]): WorkspaceContainer[] { - return containers.filter((container: WorkspaceContainer) => - container.attributes && (!container.attributes[CONTAINER_SOURCE_ATTRIBUTE] || container.attributes[CONTAINER_SOURCE_ATTRIBUTE] === RECIPE_CONTAINER_SOURCE) - ); + return containers.filter(container => isDevContainer(container)); +} + +export function isDevContainer(container: WorkspaceContainer): boolean { + return container.attributes !== undefined + && (!container.attributes[CONTAINER_SOURCE_ATTRIBUTE] || container.attributes[CONTAINER_SOURCE_ATTRIBUTE] === RECIPE_CONTAINER_SOURCE); } diff --git a/extensions/eclipse-che-theia-terminal/src/browser/contribution/terminal-quick-open.ts b/extensions/eclipse-che-theia-terminal/src/browser/contribution/terminal-quick-open.ts index 7053625eb..786cb5536 100644 --- a/extensions/eclipse-che-theia-terminal/src/browser/contribution/terminal-quick-open.ts +++ b/extensions/eclipse-che-theia-terminal/src/browser/contribution/terminal-quick-open.ts @@ -11,20 +11,18 @@ import { injectable, inject } from 'inversify'; import { QuickOpenMode, QuickOpenOptions, ApplicationShell, KeybindingRegistry, - QuickOpenModel, QuickOpenItem, QuickOpenHandler, QuickOpenService + QuickOpenModel, QuickOpenItem, QuickOpenHandler, QuickOpenService, QuickOpenGroupItem, QuickOpenGroupItemOptions, QuickOpenItemOptions } from '@theia/core/lib/browser'; import { CHEWorkspaceService } from '../../common/workspace-service'; import { TerminalApiEndPointProvider } from '../server-definition/terminal-proxy-creator'; import { OpenTerminalHandler } from './exec-terminal-contribution'; -import { filterRecipeContainers } from './terminal-command-filter'; +import { isDevContainer } from './terminal-command-filter'; @injectable() export class TerminalQuickOpenService implements QuickOpenHandler, QuickOpenModel { prefix: string = 'term '; description: string = 'Create new terminal for specific container.'; private items: QuickOpenItem[] = []; - private isOpen: boolean; - private hideToolContainers: boolean; @inject(QuickOpenService) private readonly quickOpenService: QuickOpenService; @@ -45,29 +43,56 @@ export class TerminalQuickOpenService implements QuickOpenHandler, QuickOpenMode protected readonly terminalInSpecificContainerCommandId: string; async displayListMachines(doOpen: OpenTerminalHandler) { - const items: QuickOpenItem[] = []; + this.items = []; + + const containers = await this.workspaceService.getContainerList(); + + const devContainers = containers.filter(container => isDevContainer(container)); + const toolingContainers = containers.filter(container => !isDevContainer(container)); + + this.items.push( + ...devContainers.map((container, index) => { + const options: QuickOpenItemOptions = { + label: container.name, + run(mode: QuickOpenMode): boolean { + if (mode !== QuickOpenMode.OPEN) { + return false; + } + doOpen(container.name); + + return true; + } + }; + + const group: QuickOpenGroupItemOptions = { + groupLabel: index === 0 ? devContainers.length === 1 ? 'Developer Container' : 'Developer Containers' : '', + showBorder: false + }; + + return new QuickOpenGroupItem({ ...options, ...group }); + }), + ...toolingContainers.map((container, index) => { + const options: QuickOpenItemOptions = { + label: container.name, + run(mode: QuickOpenMode): boolean { + if (mode !== QuickOpenMode.OPEN) { + return false; + } + doOpen(container.name); + + return true; + } + }; + + const group: QuickOpenGroupItemOptions = { + groupLabel: devContainers.length <= 0 ? '' : index === 0 ? toolingContainers.length === 1 ? 'Tooling Container' : 'Tooling Containers' : '', + showBorder: devContainers.length <= 0 ? false : index === 0 ? true : false + }; + + return new QuickOpenGroupItem({ ...options, ...group }); + }) + ); - let containers = await this.workspaceService.getContainerList(); - - if (this.isOpen) { - // trigger show/hide tool containers - this.hideToolContainers = !this.hideToolContainers; - } else { - this.isOpen = true; - this.hideToolContainers = true; - } - - if (this.hideToolContainers) { - containers = filterRecipeContainers(containers); - } - - for (const container of containers) { - items.push(new NewTerminalItem(container.name, async newTermItemFunc => { - doOpen(newTermItemFunc.machineName); - })); - } - - this.items = Array.isArray(items) ? items : [items]; this.showTerminalItems(); } @@ -82,19 +107,12 @@ export class TerminalQuickOpenService implements QuickOpenHandler, QuickOpenMode } getOptions(): QuickOpenOptions { - let placeholder = 'Select container to create new terminal'; - const keybinding = this.getShortCutCommand(); - if (keybinding) { - placeholder += ` (Press ${keybinding} to show/hide tool containers)`; - } + const placeholder = 'Select container to create new terminal'; return { placeholder: placeholder, fuzzyMatchLabel: true, fuzzyMatchDescription: true, - fuzzySort: false, - onClose: () => { - this.isOpen = false; - } + fuzzySort: false }; } diff --git a/plugins/task-plugin/src/che-workspace-client.ts b/plugins/task-plugin/src/che-workspace-client.ts index 1b1c1c759..ad2f0c167 100644 --- a/plugins/task-plugin/src/che-workspace-client.ts +++ b/plugins/task-plugin/src/che-workspace-client.ts @@ -14,6 +14,13 @@ import { injectable } from 'inversify'; const TERMINAL_SERVER_TYPE = 'terminal'; +export const RECIPE_CONTAINER_SOURCE = 'recipe'; +export const CONTAINER_SOURCE_ATTRIBUTE = 'source'; + +export interface WorkspaceContainer extends cheApi.workspace.Machine { + name: string +} + @injectable() export class CheWorkspaceClient { @@ -54,6 +61,28 @@ export class CheWorkspaceClient { return machines; } + async getContainers(): Promise { + const containers: WorkspaceContainer[] = []; + try { + const workspace = await this.getCurrentWorkspace(); + + if (workspace.runtime && workspace.runtime.machines) { + const machines = workspace.runtime.machines; + for (const machineName in machines) { + if (!machines.hasOwnProperty(machineName)) { + continue; + } + const container: WorkspaceContainer = { name: machineName, ...machines[machineName] }; + containers.push(container); + } + } + } catch (e) { + throw new Error('Unable to get list workspace containers. Cause: ' + e); + } + + return containers; + } + async getCommands(): Promise { const workspace: cheApi.workspace.Workspace = await this.getCurrentWorkspace(); diff --git a/plugins/task-plugin/src/machine/machines-picker.ts b/plugins/task-plugin/src/machine/machines-picker.ts index 6c696ea66..19a3ae62b 100644 --- a/plugins/task-plugin/src/machine/machines-picker.ts +++ b/plugins/task-plugin/src/machine/machines-picker.ts @@ -9,8 +9,8 @@ **********************************************************************/ import { injectable, inject } from 'inversify'; -import * as theia from '@theia/plugin'; -import { CheWorkspaceClient } from '../che-workspace-client'; +import { QuickPickItem, window } from '@theia/plugin'; +import { CheWorkspaceClient, WorkspaceContainer, CONTAINER_SOURCE_ATTRIBUTE, RECIPE_CONTAINER_SOURCE } from '../che-workspace-client'; const CONTAINERS_PLACE_HOLDER = 'Pick a container to run the task'; export const COMPONENT_ATTRIBUTE: string = 'component'; @@ -29,24 +29,68 @@ export class MachinesPicker { */ async pick(containerNames?: string[]): Promise { if (!containerNames) { - containerNames = await this.cheWorkspaceClient.getContainersNames(); + return this.pickContainerFromClient(); } if (containerNames.length === 1) { return Promise.resolve(containerNames[0]); } - return this.showMachineQuickPick(containerNames); + return this.showQuickPick(containerNames.map(containerName => ({ label: containerName }))); } - private showMachineQuickPick(items: string[]): Promise { + private showQuickPick(items: QuickPickItem[]): Promise { return new Promise(resolve => { + if (items.length === 0) { + return; + } - const options = { placeHolder: CONTAINERS_PLACE_HOLDER } as theia.QuickPickOptions; - options.onDidSelectItem = (item => { - const machineName = typeof item === 'string' ? item : item.label; - resolve(machineName); + window.showQuickPick(items, { + placeHolder: CONTAINERS_PLACE_HOLDER, + ignoreFocusOut: false, + onDidSelectItem: (item => { + resolve((item).label); + }) }); - theia.window.showQuickPick(items, options); }); } + + private async pickContainerFromClient(): Promise { + const containers = await this.cheWorkspaceClient.getContainers(); + + if (containers.length === 1) { + return Promise.resolve(containers[0].name); + } + + const items = this.toQuickPickItems(containers); + + return this.showQuickPick(items); + } + + private toQuickPickItems(containers: WorkspaceContainer[]): QuickPickItem[] { + const items: QuickPickItem[] = []; + + const devContainers = containers.filter(container => this.isDevContainer(container)); + const toolingContainers = containers.filter(container => !this.isDevContainer(container)); + + items.push(...devContainers.map((container, index) => { + label: container.name, + groupLabel: index === 0 ? devContainers.length === 1 ? 'Developer Container' : 'Developer Containers' : '', + showBorder: false + } + )); + + items.push(...toolingContainers.map((container, index) => { + label: container.name, + groupLabel: devContainers.length <= 0 ? '' : index === 0 ? toolingContainers.length === 1 ? 'Tooling Container' : 'Tooling Containers' : '', + showBorder: devContainers.length <= 0 ? false : index === 0 ? true : false + } + )); + + return items; + } + + private isDevContainer(container: WorkspaceContainer): boolean { + return container.attributes !== undefined + && (!container.attributes[CONTAINER_SOURCE_ATTRIBUTE] || container.attributes[CONTAINER_SOURCE_ATTRIBUTE] === RECIPE_CONTAINER_SOURCE); + } }