From d89cf6f0c3b28671cfcef1cfbc4344ca4d110d1d Mon Sep 17 00:00:00 2001 From: Josh Pinkney Date: Tue, 16 Jul 2019 14:57:19 -0400 Subject: [PATCH 1/2] Plugins and editors are now unified and have a dropdown for multiple versions Signed-off-by: Josh Pinkney --- .../workspace-editors.controller.ts | 70 +++++++++++++--- .../workspace-editors/workspace-editors.html | 7 +- .../workspace-editors/workspace-editors.styl | 4 + .../workspace-plugins.controller.ts | 83 ++++++++++++++++--- .../workspace-plugins/workspace-plugins.html | 5 +- .../workspace-plugins/workspace-plugins.styl | 6 +- .../components/api/plugin-registry.factory.ts | 5 ++ 7 files changed, 152 insertions(+), 28 deletions(-) diff --git a/dashboard/src/app/workspaces/workspace-details/workspace-editors/workspace-editors.controller.ts b/dashboard/src/app/workspaces/workspace-details/workspace-editors/workspace-editors.controller.ts index 17c8ab88339..211e045cc7b 100644 --- a/dashboard/src/app/workspaces/workspace-details/workspace-editors/workspace-editors.controller.ts +++ b/dashboard/src/app/workspaces/workspace-details/workspace-editors/workspace-editors.controller.ts @@ -10,7 +10,7 @@ * Red Hat, Inc. - initial API and implementation */ 'use strict'; -import {IPlugin, PluginRegistry} from '../../../../components/api/plugin-registry.factory'; +import {IPlugin, PluginRegistry, IPluginRow} from '../../../../components/api/plugin-registry.factory'; import {CheNotification} from '../../../../components/notification/che-notification.factory'; import {CheWorkspace} from '../../../../components/api/workspace/che-workspace.factory'; @@ -36,7 +36,7 @@ export class WorkspaceEditorsController { isLoading: boolean; editorOrderBy = 'displayName'; - editors: Array = []; + editors: Map = new Map(); // the key is publisher/name selectedEditor: string = ''; editorFilter: any; @@ -80,14 +80,26 @@ export class WorkspaceEditorsController { * Loads the list of plugins from registry. */ loadPlugins(): void { - this.editors = []; + this.editors = new Map(); this.isLoading = true; - this.pluginRegistry.fetchPlugins(this.pluginRegistryLocation).then((result: Array) => { + this.pluginRegistry.fetchPlugins(this.pluginRegistryLocation).then((result: Array) => { this.isLoading = false; - result.forEach((item: IPlugin) => { + result.forEach((item: IPluginRow) => { if (item.type === EDITOR_TYPE) { - this.editors.push(item); - }; + + // since plugin registry returns an array of plugins/editors with a single version we need to unite the editor versions into one + const pluginID = `${item.publisher}/${item.name}`; + + item.selected = 'latest'; // set the default selected to latest + + if (this.editors.has(pluginID)) { + const foundPlugin = this.editors.get(pluginID); + foundPlugin.versions.push(item.version); + } else { + item.versions = [item.version]; + this.editors.set(pluginID, item); + } + } }); this.updateEditors(); @@ -112,12 +124,39 @@ export class WorkspaceEditorsController { * * @param {IPlugin} plugin */ - updateEditor(plugin: IPlugin): void { + updateEditor(plugin: IPluginRow): void { if (plugin.type === EDITOR_TYPE) { - this.selectedEditor = plugin.isEnabled ? plugin.id : ''; + const pluginID = `${plugin.publisher}/${plugin.name}`; + const pluginIDWithVersion = `${plugin.publisher}/${plugin.name}/${plugin.selected}`; + + this.selectedEditor = plugin.isEnabled ? pluginIDWithVersion : ''; + + this.editors.get(pluginID).selected = plugin.selected; + this.editors.get(pluginID).id = pluginIDWithVersion; + this.cheWorkspace.getWorkspaceDataManager().setEditor(this.workspace, this.selectedEditor); } - + + this.onChange(); + } + + /** + * Update the selected editor version when the editor version dropdown is changed + * + * @param {IPlugin} plugin + */ + updateSelectedEditorVersion(plugin: IPluginRow): void { + if (plugin.type === EDITOR_TYPE) { + const pluginID = `${plugin.publisher}/${plugin.name}`; + + // create a plugin id with the newly selected version + const pluginIDWithVersion = `${pluginID}/${plugin.selected}`; + + this.editors.get(pluginID).selected = plugin.selected; + this.editors.get(pluginID).id = pluginIDWithVersion; + + this.cheWorkspace.getWorkspaceDataManager().setEditor(this.workspace, pluginIDWithVersion); + } this.onChange(); } @@ -128,11 +167,18 @@ export class WorkspaceEditorsController { this.selectedEditor = this.cheWorkspace.getWorkspaceDataManager().getEditor(this.workspace); // check each editor's enabled state: - this.editors.forEach((editor: IPlugin) => { + this.editors.forEach((editor: IPluginRow) => { editor.isEnabled = this.isEditorEnabled(editor); + if (editor.id === this.selectedEditor) { + + // this.selectedEditor is in the form publisher/name/pluginVersion + const editorSep = this.selectedEditor.split('/'); + const pluginVersion = editorSep[2]; + editor.selected = pluginVersion; + } }); - this.cheListHelper.setList(this.editors, 'name'); + this.cheListHelper.setList(Array.from(this.editors.values()), 'name'); } /** diff --git a/dashboard/src/app/workspaces/workspace-details/workspace-editors/workspace-editors.html b/dashboard/src/app/workspaces/workspace-details/workspace-editors/workspace-editors.html index c1b8601ae04..40f7e35f595 100644 --- a/dashboard/src/app/workspaces/workspace-details/workspace-editors/workspace-editors.html +++ b/dashboard/src/app/workspaces/workspace-details/workspace-editors/workspace-editors.html @@ -24,9 +24,9 @@ + ng-if="workspaceEditorsController.editors && workspaceEditorsController.editors.size > 0">
+ ng-repeat="editor in workspaceEditorsController.cheListHelper.getVisibleItems() | orderBy:[workspaceEditorsController.editorOrderBy, 'displayName' ]">
- {{editor.version}} +
diff --git a/dashboard/src/app/workspaces/workspace-details/workspace-editors/workspace-editors.styl b/dashboard/src/app/workspaces/workspace-details/workspace-editors/workspace-editors.styl index 6498ccd3b12..6ba61beffd6 100755 --- a/dashboard/src/app/workspaces/workspace-details/workspace-editors/workspace-editors.styl +++ b/dashboard/src/app/workspaces/workspace-details/workspace-editors/workspace-editors.styl @@ -60,5 +60,9 @@ md-tab-content .plugin-page-separator .che-list-item-checkbox min-width 50px height inherit + .che-version-dropdown + width:80%; + border-color: transparent; + background-colur: #e4e4e4; diff --git a/dashboard/src/app/workspaces/workspace-details/workspace-plugins/workspace-plugins.controller.ts b/dashboard/src/app/workspaces/workspace-details/workspace-plugins/workspace-plugins.controller.ts index 0bd6afc0e9e..c3132a62f4d 100644 --- a/dashboard/src/app/workspaces/workspace-details/workspace-plugins/workspace-plugins.controller.ts +++ b/dashboard/src/app/workspaces/workspace-details/workspace-plugins/workspace-plugins.controller.ts @@ -10,7 +10,7 @@ * Red Hat, Inc. - initial API and implementation */ 'use strict'; -import {IPlugin, PluginRegistry} from '../../../../components/api/plugin-registry.factory'; +import {IPlugin, PluginRegistry, IPluginRow} from '../../../../components/api/plugin-registry.factory'; import {CheNotification} from '../../../../components/notification/che-notification.factory'; import {CheWorkspace} from '../../../../components/api/workspace/che-workspace.factory'; @@ -37,7 +37,7 @@ export class WorkspacePluginsController { isLoading: boolean; pluginOrderBy = 'displayName'; - plugins: Array = []; + plugins: Map = new Map(); // the key is publisher/name selectedPlugins: Array = []; pluginFilter: any; @@ -82,13 +82,42 @@ export class WorkspacePluginsController { * Loads the list of plugins from registry. */ loadPlugins(): void { - this.plugins = []; + this.plugins = new Map(); this.isLoading = true; - this.pluginRegistry.fetchPlugins(this.pluginRegistryLocation).then((result: Array) => { + this.pluginRegistry.fetchPlugins(this.pluginRegistryLocation).then((result: Array) => { this.isLoading = false; - result.forEach((item: IPlugin) => { + result.forEach((item: IPluginRow) => { if (item.type !== EDITOR_TYPE) { - this.plugins.push(item); + + // since plugin registry returns an array of plugins/editors with a single version we need to unite the plugin versions into one + const pluginID = `${item.publisher}/${item.name}`; + + item.selected = 'latest'; // set the default selected to latest + + if (this.plugins.has(pluginID)) { + const foundPlugin = this.plugins.get(pluginID); + foundPlugin.versions.push(item.version); + } else { + item.versions = [item.version]; + this.plugins.set(pluginID, item); + } + + } + }); + + this.selectedPlugins.forEach(plugin => { + // a selected plugin is in the form publisher/name/version + // find the currently selected ones and set them along with their id + const pluginSep = plugin.split('/'); + const published = pluginSep[0]; + const name = pluginSep[1]; + const version = pluginSep[2]; + const pluginID = `${published}/${name}`; + + if (this.plugins.has(pluginID)) { + const foundPlugin = this.plugins.get(pluginID); + foundPlugin.id = plugin; + foundPlugin.selected = version; } }); @@ -114,19 +143,53 @@ export class WorkspacePluginsController { * * @param {IPlugin} plugin */ - updatePlugin(plugin: IPlugin): void { + updatePlugin(plugin: IPluginRow): void { if (plugin.type !== EDITOR_TYPE) { + + const pluginID = `${plugin.publisher}/${plugin.name}`; + const pluginIDWithVersion = `${plugin.publisher}/${plugin.name}/${plugin.selected}`; + + this.plugins.get(pluginID).selected = plugin.selected; + this.plugins.get(pluginID).id = pluginIDWithVersion; + if (plugin.isEnabled) { - this.selectedPlugins.push(plugin.id); + this.selectedPlugins.push(pluginIDWithVersion); } else { this.selectedPlugins.splice(this.selectedPlugins.indexOf(plugin.id), 1); } + this.cheWorkspace.getWorkspaceDataManager().setPlugins(this.workspace, this.selectedPlugins); } this.onChange(); } + /** + * Update the selected plugin version when the plugin version dropdown is changed + * + * @param {IPlugin} plugin + */ + updateSelectedPlugin(plugin: IPluginRow): void { + if (plugin.type !== EDITOR_TYPE) { + const pluginID = `${plugin.publisher}/${plugin.name}`; + const pluginIDWithVersion = `${pluginID}/${plugin.selected}`; + + this.plugins.get(pluginID).selected = plugin.selected; + this.plugins.get(pluginID).id = pluginIDWithVersion; + + const currentlySelectedPlugins = this.cheWorkspace.getWorkspaceDataManager().getPlugins(this.workspace); + + if (plugin.isEnabled) { + currentlySelectedPlugins.splice(this.selectedPlugins.indexOf(plugin.id), 1, pluginIDWithVersion); + } else { + currentlySelectedPlugins.push(pluginIDWithVersion); + } + this.cheWorkspace.getWorkspaceDataManager().setPlugins(this.workspace, currentlySelectedPlugins); + this.selectedPlugins = currentlySelectedPlugins; + } + this.onChange(); + } + /** * Update the state of plugins. */ @@ -136,7 +199,7 @@ export class WorkspacePluginsController { this.plugins.forEach((plugin: IPlugin) => { plugin.isEnabled = this.isPluginEnabled(plugin); }); - this.cheListHelper.setList(this.plugins, 'displayName'); + this.cheListHelper.setList(Array.from(this.plugins.values()), 'displayName'); } /** @@ -145,6 +208,6 @@ export class WorkspacePluginsController { * @returns {boolean} the plugin's enabled state */ private isPluginEnabled(plugin: IPlugin): boolean { - return this.selectedPlugins.indexOf(plugin.id) >= 0 + return this.selectedPlugins.indexOf(plugin.id) >= 0; } } diff --git a/dashboard/src/app/workspaces/workspace-details/workspace-plugins/workspace-plugins.html b/dashboard/src/app/workspaces/workspace-details/workspace-plugins/workspace-plugins.html index 7dec5d2e919..0bf53fce640 100644 --- a/dashboard/src/app/workspaces/workspace-details/workspace-plugins/workspace-plugins.html +++ b/dashboard/src/app/workspaces/workspace-details/workspace-plugins/workspace-plugins.html @@ -34,7 +34,7 @@ + ng-if="workspacePluginsController.plugins && workspacePluginsController.plugins.size > 0">
@@ -61,7 +61,8 @@
- {{plugin.version}} +
diff --git a/dashboard/src/app/workspaces/workspace-details/workspace-plugins/workspace-plugins.styl b/dashboard/src/app/workspaces/workspace-details/workspace-plugins/workspace-plugins.styl index 4f43711d8a5..46c0e47ddaa 100755 --- a/dashboard/src/app/workspaces/workspace-details/workspace-plugins/workspace-plugins.styl +++ b/dashboard/src/app/workspaces/workspace-details/workspace-plugins/workspace-plugins.styl @@ -60,9 +60,13 @@ md-tab-content .plugin-page-separator .che-list-item-checkbox min-width 50px height inherit + .che-version-dropdown + width:80%; + border-color: transparent; + background-colur: #e4e4e4; + .plugin-page-separator margin-top 40px margin-bottom 10px height 1px background-color $list-separator-color - diff --git a/dashboard/src/components/api/plugin-registry.factory.ts b/dashboard/src/components/api/plugin-registry.factory.ts index bfbad73e734..27229b2ed6d 100644 --- a/dashboard/src/components/api/plugin-registry.factory.ts +++ b/dashboard/src/components/api/plugin-registry.factory.ts @@ -26,6 +26,11 @@ export interface IPlugin { isEnabled: boolean; } +export interface IPluginRow extends IPlugin { + selected: string; + versions: string[]; +} + /** * This class is handling plugin registry api From 250a57959bb13527388217bd5f1fafd8031f40e1 Mon Sep 17 00:00:00 2001 From: Oleksii Kurinnyi Date: Thu, 8 Aug 2019 17:13:58 +0200 Subject: [PATCH 2/2] fix updating plugins and editors list on workspace page Signed-off-by: Oleksii Kurinnyi --- .../workspace-editors.controller.ts | 24 ++++++++--- .../workspace-plugins.controller.ts | 42 ++++++++++++++----- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/dashboard/src/app/workspaces/workspace-details/workspace-editors/workspace-editors.controller.ts b/dashboard/src/app/workspaces/workspace-details/workspace-editors/workspace-editors.controller.ts index 211e045cc7b..0d20439f6b6 100644 --- a/dashboard/src/app/workspaces/workspace-details/workspace-editors/workspace-editors.controller.ts +++ b/dashboard/src/app/workspaces/workspace-details/workspace-editors/workspace-editors.controller.ts @@ -169,12 +169,11 @@ export class WorkspaceEditorsController { // check each editor's enabled state: this.editors.forEach((editor: IPluginRow) => { editor.isEnabled = this.isEditorEnabled(editor); - if (editor.id === this.selectedEditor) { + if (editor.isEnabled) { // this.selectedEditor is in the form publisher/name/pluginVersion - const editorSep = this.selectedEditor.split('/'); - const pluginVersion = editorSep[2]; - editor.selected = pluginVersion; + const { publisher, name, version } = this.splitEditorId(this.selectedEditor); + editor.selected = version; } }); @@ -187,6 +186,21 @@ export class WorkspaceEditorsController { * @returns {boolean} the editor's enabled state */ private isEditorEnabled(editor: IPlugin): boolean { - return editor.id === this.selectedEditor; + const partialId = `${editor.publisher}/${editor.name}/`; + return this.selectedEditor && this.selectedEditor.indexOf(partialId) !== -1; } + + /** + * Splits an editor ID by a separator (slash) + * @param id a string in form `${publisher}/${name}` or `${publisher}/${name}/${version}` + */ + private splitEditorId(id: string): { publisher: string, name: string, version?: string } { + const parts = id.split('/'); + return { + publisher: parts[0], + name: parts[1], + version: parts[2] + }; + } + } diff --git a/dashboard/src/app/workspaces/workspace-details/workspace-plugins/workspace-plugins.controller.ts b/dashboard/src/app/workspaces/workspace-details/workspace-plugins/workspace-plugins.controller.ts index c3132a62f4d..a4319256247 100644 --- a/dashboard/src/app/workspaces/workspace-details/workspace-plugins/workspace-plugins.controller.ts +++ b/dashboard/src/app/workspaces/workspace-details/workspace-plugins/workspace-plugins.controller.ts @@ -108,11 +108,8 @@ export class WorkspacePluginsController { this.selectedPlugins.forEach(plugin => { // a selected plugin is in the form publisher/name/version // find the currently selected ones and set them along with their id - const pluginSep = plugin.split('/'); - const published = pluginSep[0]; - const name = pluginSep[1]; - const version = pluginSep[2]; - const pluginID = `${published}/${name}`; + const {publisher, name, version} = this.splitPluginId(plugin); + const pluginID = `${publisher}/${name}`; if (this.plugins.has(pluginID)) { const foundPlugin = this.plugins.get(pluginID); @@ -196,18 +193,41 @@ export class WorkspacePluginsController { private updatePlugins(): void { this.selectedPlugins = this.cheWorkspace.getWorkspaceDataManager().getPlugins(this.workspace); // check each plugin's enabled state: - this.plugins.forEach((plugin: IPlugin) => { - plugin.isEnabled = this.isPluginEnabled(plugin); + this.plugins.forEach((plugin: IPluginRow) => { + const selectedPluginId = this.findInSelected(plugin); + plugin.isEnabled = !!selectedPluginId; + if (selectedPluginId) { + plugin.id = selectedPluginId; + const {publisher, name, version} = this.splitPluginId(selectedPluginId); + plugin.selected = version; + } }); this.cheListHelper.setList(Array.from(this.plugins.values()), 'displayName'); } /** - * + * Finds given plugin in the list of enabled plugins and returns its ID with version * @param {IPlugin} plugin - * @returns {boolean} the plugin's enabled state + * @returns {string | undefined} plugin ID + */ + private findInSelected(plugin: IPluginRow): string | undefined { + return this.selectedPlugins.find(selectedPluginId => { + const partialId = `${plugin.publisher}/${plugin.name}/`; + return selectedPluginId.indexOf(partialId) !== -1; + }); + } + + /** + * Splits a plugin ID by a separator (slash) + * @param id a string in form `${publisher}/${name}` or `${publisher}/${name}/${version}` */ - private isPluginEnabled(plugin: IPlugin): boolean { - return this.selectedPlugins.indexOf(plugin.id) >= 0; + private splitPluginId(id: string): { publisher: string, name: string, version?: string } { + const parts = id.split('/'); + return { + publisher: parts[0], + name: parts[1], + version: parts[2] + }; } + }