diff --git a/dashboard/README.md b/dashboard/README.md
index 8b21b83696..5cacf68fdf 100644
--- a/dashboard/README.md
+++ b/dashboard/README.md
@@ -274,3 +274,17 @@ The `"configuration.prefetch"` section allows to define resources that UD should
...
]
```
+
+The `"configuration.features.disabled"` field defines features that should be disabled and not displayed in User Dashboard. Available values are `"workspaceSharing"`, `"kubernetesNamespaceSelector"`.
+
+For example, this config disables kubernetes namespace selector:
+
+```json
+{
+ "configuration": {
+ "features": {
+ "disabled": ["kubernetesNamespaceSelector"]
+ }
+ }
+}
+```
diff --git a/dashboard/src/app/workspaces/create-workspace/import-custom-stack/import-custom-stack.controller.ts b/dashboard/src/app/workspaces/create-workspace/import-custom-stack/import-custom-stack.controller.ts
index 580d2c98c5..da6799e2d7 100644
--- a/dashboard/src/app/workspaces/create-workspace/import-custom-stack/import-custom-stack.controller.ts
+++ b/dashboard/src/app/workspaces/create-workspace/import-custom-stack/import-custom-stack.controller.ts
@@ -17,6 +17,8 @@ import {RandomSvc} from '../../../../components/utils/random.service';
import {NamespaceSelectorSvc} from '../ready-to-go-stacks/namespace-selector/namespace-selector.service';
import { CheKubernetesNamespace } from '../../../../components/api/che-kubernetes-namespace.factory';
import { CheWorkspace } from '../../../../components/api/workspace/che-workspace.factory';
+import { CheDashboardConfigurationService } from '../../../../components/branding/che-dashboard-configuration.service';
+import { TogglableFeature } from '../../../../components/branding/che-branding.factory';
/**
* This class is handling the controller for stack importing directive.
@@ -26,18 +28,18 @@ import { CheWorkspace } from '../../../../components/api/workspace/che-workspace
export class ImportStackController implements IImportStackScopeBindings {
static $inject = [
+ 'cheDashboardConfigurationService',
'cheKubernetesNamespace',
'cheWorkspace',
'createWorkspaceSvc',
'namespaceSelectorSvc',
- 'randomSvc'
+ 'randomSvc',
];
onChange: IImportStackScopeOnChange;
-
infrastructureNamespaceHint: string;
-
ephemeralMode: boolean;
+ enabledKubernetesNamespaceSelector: boolean = false;
/**
* Kubernetes Namespace API interaction.
@@ -59,6 +61,10 @@ export class ImportStackController implements IImportStackScopeBindings {
* Workspace creation service.
*/
private createWorkspaceSvc: CreateWorkspaceSvc;
+ /**
+ * Dashboard configuration service.
+ */
+ private cheDashboardConfigurationService: CheDashboardConfigurationService;
/**
* The selected source for devfile importing(URL or YAML).
*/
@@ -88,12 +94,14 @@ export class ImportStackController implements IImportStackScopeBindings {
* Default constructor that is using resource injection
*/
constructor(
+ cheDashboardConfigurationService: CheDashboardConfigurationService,
cheKubernetesNamespace: CheKubernetesNamespace,
cheWorkspace: CheWorkspace,
createWorkspaceSvc: CreateWorkspaceSvc,
namespaceSelectorSvc: NamespaceSelectorSvc,
- randomSvc: RandomSvc
+ randomSvc: RandomSvc,
) {
+ this.cheDashboardConfigurationService = cheDashboardConfigurationService;
this.cheKubernetesNamespace = cheKubernetesNamespace;
this.cheWorkspace = cheWorkspace;
this.createWorkspaceSvc = createWorkspaceSvc;
@@ -106,6 +114,9 @@ export class ImportStackController implements IImportStackScopeBindings {
this.cheWorkspace.fetchWorkspaceSettings().then((settings: che.IWorkspaceSettings) => {
this.ephemeralMode = settings['che.workspace.persist_volumes.default'] === 'false';
});
+ this.cheDashboardConfigurationService.ready.then(() => {
+ this.enabledKubernetesNamespaceSelector = this.cheDashboardConfigurationService.enabledFeature(TogglableFeature.KUBERNETES_NAMESPACE_SELECTOR);
+ });
}
updateDevfileFromRemote(devfile: che.IWorkspaceDevfile, attrs: { factoryurl?: string } | undefined): void {
diff --git a/dashboard/src/app/workspaces/create-workspace/import-custom-stack/import-custom-stack.html b/dashboard/src/app/workspaces/create-workspace/import-custom-stack/import-custom-stack.html
index be2ddfc2f1..0f6b4932d3 100644
--- a/dashboard/src/app/workspaces/create-workspace/import-custom-stack/import-custom-stack.html
+++ b/dashboard/src/app/workspaces/create-workspace/import-custom-stack/import-custom-stack.html
@@ -16,7 +16,10 @@
-
+
diff --git a/dashboard/src/app/workspaces/create-workspace/ready-to-go-stacks/ready-to-go-stacks.controller.ts b/dashboard/src/app/workspaces/create-workspace/ready-to-go-stacks/ready-to-go-stacks.controller.ts
index b285880290..2d16b2dcad 100644
--- a/dashboard/src/app/workspaces/create-workspace/ready-to-go-stacks/ready-to-go-stacks.controller.ts
+++ b/dashboard/src/app/workspaces/create-workspace/ready-to-go-stacks/ready-to-go-stacks.controller.ts
@@ -18,6 +18,8 @@ import { IReadyToGoStacksScopeBindings, IReadyToGoStacksScopeOnChange } from './
import { ProjectSourceSelectorService } from './project-source-selector/project-source-selector.service';
import { CheKubernetesNamespace } from '../../../../components/api/che-kubernetes-namespace.factory';
import { CheWorkspace } from '../../../../components/api/workspace/che-workspace.factory';
+import { CheDashboardConfigurationService } from '../../../../components/branding/che-dashboard-configuration.service';
+import { TogglableFeature } from '../../../../components/branding/che-branding.factory';
/**
* This class is handling the controller for predefined stacks.
@@ -27,12 +29,13 @@ import { CheWorkspace } from '../../../../components/api/workspace/che-workspace
export class ReadyToGoStacksController implements IReadyToGoStacksScopeBindings {
static $inject = [
+ 'cheDashboardConfigurationService',
'cheKubernetesNamespace',
'cheWorkspace',
'createWorkspaceSvc',
'namespaceSelectorSvc',
'projectSourceSelectorService',
- 'randomSvc'
+ 'randomSvc',
];
/**
@@ -53,10 +56,12 @@ export class ReadyToGoStacksController implements IReadyToGoStacksScopeBindings
WORKSPACE_NAME_FORM = 'workspaceName';
infrastructureNamespaceHint: string = '';
ephemeralMode: boolean;
+ enabledKubernetesNamespaceSelector: boolean = false;
/**
* Injected dependencies.
*/
+ private cheDashboardConfigurationService: CheDashboardConfigurationService;
private cheKubernetesNamespace: CheKubernetesNamespace;
private cheWorkspace: CheWorkspace;
private createWorkspaceSvc: CreateWorkspaceSvc;
@@ -101,13 +106,15 @@ export class ReadyToGoStacksController implements IReadyToGoStacksScopeBindings
* Default constructor that is using resource injection
*/
constructor(
+ cheDashboardConfigurationService: CheDashboardConfigurationService,
cheKubernetesNamespace: CheKubernetesNamespace,
cheWorkspace: CheWorkspace,
createWorkspaceSvc: CreateWorkspaceSvc,
namespaceSelectorSvc: NamespaceSelectorSvc,
projectSourceSelectorService: ProjectSourceSelectorService,
- randomSvc: RandomSvc
+ randomSvc: RandomSvc,
) {
+ this.cheDashboardConfigurationService = cheDashboardConfigurationService;
this.cheKubernetesNamespace = cheKubernetesNamespace;
this.cheWorkspace = cheWorkspace;
this.createWorkspaceSvc = createWorkspaceSvc;
@@ -131,6 +138,9 @@ export class ReadyToGoStacksController implements IReadyToGoStacksScopeBindings
this.cheWorkspace.fetchWorkspaceSettings().then((settings: che.IWorkspaceSettings) => {
this.ephemeralMode = settings['che.workspace.persist_volumes.default'] === 'false';
});
+ this.cheDashboardConfigurationService.ready.then(() => {
+ this.enabledKubernetesNamespaceSelector = this.cheDashboardConfigurationService.enabledFeature(TogglableFeature.KUBERNETES_NAMESPACE_SELECTOR);
+ });
}
/**
diff --git a/dashboard/src/app/workspaces/create-workspace/ready-to-go-stacks/ready-to-go-stacks.html b/dashboard/src/app/workspaces/create-workspace/ready-to-go-stacks/ready-to-go-stacks.html
index 148d492df6..b619dd3024 100644
--- a/dashboard/src/app/workspaces/create-workspace/ready-to-go-stacks/ready-to-go-stacks.html
+++ b/dashboard/src/app/workspaces/create-workspace/ready-to-go-stacks/ready-to-go-stacks.html
@@ -37,7 +37,10 @@
-
+
diff --git a/dashboard/src/app/workspaces/workspace-details/workspace-details.directive.spec.ts b/dashboard/src/app/workspaces/workspace-details/workspace-details.directive.spec.ts
index 9a0af85c77..4403dd149e 100644
--- a/dashboard/src/app/workspaces/workspace-details/workspace-details.directive.spec.ts
+++ b/dashboard/src/app/workspaces/workspace-details/workspace-details.directive.spec.ts
@@ -246,7 +246,10 @@ describe(`WorkspaceDetailsController >`, () => {
menu: {
disabled: []
},
- prefetch: {}
+ prefetch: {},
+ features: {
+ disabled: []
+ }
};
}
};
diff --git a/dashboard/src/app/workspaces/workspace-details/workspace-details.service.ts b/dashboard/src/app/workspaces/workspace-details/workspace-details.service.ts
index 070181b80e..80bb4ac2b8 100644
--- a/dashboard/src/app/workspaces/workspace-details/workspace-details.service.ts
+++ b/dashboard/src/app/workspaces/workspace-details/workspace-details.service.ts
@@ -19,6 +19,8 @@ import {CheService} from '../../../components/api/che-service.factory';
import {PluginRegistry} from '../../../components/api/plugin-registry.factory';
import {WorkspaceDataManager} from '../../../components/api/workspace/workspace-data-manager';
import { ConfirmDialogService } from '../../../components/service/confirm-dialog/confirm-dialog.service';
+import { CheDashboardConfigurationService } from '../../../components/branding/che-dashboard-configuration.service';
+import { TogglableFeature } from '../../../components/branding/che-branding.factory';
interface IPage {
title: string;
@@ -84,14 +86,15 @@ export class WorkspaceDetailsService {
static $inject = [
'$log',
'$q',
- 'cheWorkspace',
+ 'cheDashboardConfigurationService',
'cheNotification',
- 'ideSvc',
- 'workspaceDetailsProjectsService',
- 'cheService',
'chePermissions',
+ 'cheService',
+ 'cheWorkspace',
'confirmDialogService',
- 'pluginRegistry'
+ 'ideSvc',
+ 'pluginRegistry',
+ 'workspaceDetailsProjectsService',
];
/**
@@ -102,6 +105,10 @@ export class WorkspaceDetailsService {
* Promises service.
*/
private $q: ng.IQService;
+ /**
+ * Dashboard configuration service.
+ */
+ private cheDashboardConfigurationService: CheDashboardConfigurationService;
/**
* Workspace API interaction.
*/
@@ -156,23 +163,25 @@ export class WorkspaceDetailsService {
constructor (
$log: ng.ILogService,
$q: ng.IQService,
- cheWorkspace: CheWorkspace,
+ cheDashboardConfigurationService: CheDashboardConfigurationService,
cheNotification: CheNotification,
- ideSvc: IdeSvc,
- workspaceDetailsProjectsService: WorkspaceDetailsProjectsService,
- cheService: CheService,
chePermissions: che.api.IChePermissions,
+ cheService: CheService,
+ cheWorkspace: CheWorkspace,
confirmDialogService: ConfirmDialogService,
- pluginRegistry: PluginRegistry
+ ideSvc: IdeSvc,
+ pluginRegistry: PluginRegistry,
+ workspaceDetailsProjectsService: WorkspaceDetailsProjectsService,
) {
this.$log = $log;
this.$q = $q;
- this.cheWorkspace = cheWorkspace;
+ this.cheDashboardConfigurationService = cheDashboardConfigurationService;
this.cheNotification = cheNotification;
+ this.cheWorkspace = cheWorkspace;
+ this.confirmDialogService = confirmDialogService;
this.ideSvc = ideSvc;
this.pluginRegistry = pluginRegistry;
this.workspaceDetailsProjectsService = workspaceDetailsProjectsService;
- this.confirmDialogService = confirmDialogService;
this.observable = new Observable();
@@ -181,7 +190,9 @@ export class WorkspaceDetailsService {
this.observable = new Observable();
cheService.fetchServices().finally(() => {
- if (cheService.isServiceAvailable(chePermissions.getPermissionsServicePath())) {
+ const sharingEnabled = this.cheDashboardConfigurationService.enabledFeature(TogglableFeature.WORKSPACE_SHARING);
+ const permissionServiceAvailable = cheService.isServiceAvailable(chePermissions.getPermissionsServicePath());
+ if (sharingEnabled && permissionServiceAvailable) {
this.addPage('Share', '', 'icon-ic_folder_shared_24px');
}
});
diff --git a/dashboard/src/app/workspaces/workspace-details/workspace-overview/workspace-details-overview.controller.ts b/dashboard/src/app/workspaces/workspace-details/workspace-overview/workspace-details-overview.controller.ts
index b629dee29c..e850e223da 100644
--- a/dashboard/src/app/workspaces/workspace-details/workspace-overview/workspace-details-overview.controller.ts
+++ b/dashboard/src/app/workspaces/workspace-details/workspace-overview/workspace-details-overview.controller.ts
@@ -16,6 +16,8 @@ import {ConfirmDialogService} from '../../../../components/service/confirm-dialo
import {NamespaceSelectorSvc} from '../../create-workspace/ready-to-go-stacks/namespace-selector/namespace-selector.service';
import {WorkspaceDetailsService} from '../workspace-details.service';
import { CheKubernetesNamespace } from '../../../../components/api/che-kubernetes-namespace.factory';
+import { CheDashboardConfigurationService } from '../../../../components/branding/che-dashboard-configuration.service';
+import { TogglableFeature } from '../../../../components/branding/che-branding.factory';
const STARTING = WorkspaceStatus[WorkspaceStatus.STARTING];
const RUNNING = WorkspaceStatus[WorkspaceStatus.RUNNING];
@@ -35,6 +37,7 @@ export class WorkspaceDetailsOverviewController {
'$route',
'$scope',
'$timeout',
+ 'cheDashboardConfigurationService',
'cheKubernetesNamespace',
'cheNotification',
'cheWorkspace',
@@ -49,12 +52,14 @@ export class WorkspaceDetailsOverviewController {
* Displaying name of infrastructure namespace.
*/
infrastructureNamespace: string;
+ enabledKubernetesNamespaceSelector: boolean = false;
private $location: ng.ILocationService;
private $q: ng.IQService;
private $route: ng.route.IRouteService;
private $scope: ng.IScope;
private $timeout: ng.ITimeoutService;
+ private cheDashboardConfigurationService: CheDashboardConfigurationService;
private cheKubernetesNamespace: CheKubernetesNamespace;
private cheNotification: CheNotification;
private cheWorkspace: CheWorkspace;
@@ -83,6 +88,7 @@ export class WorkspaceDetailsOverviewController {
$route: ng.route.IRouteService,
$scope: ng.IScope,
$timeout: ng.ITimeoutService,
+ cheDashboardConfigurationService: CheDashboardConfigurationService,
cheKubernetesNamespace: CheKubernetesNamespace,
cheNotification: CheNotification,
cheWorkspace: CheWorkspace,
@@ -95,6 +101,7 @@ export class WorkspaceDetailsOverviewController {
this.$route = $route;
this.$scope = $scope;
this.$timeout = $timeout;
+ this.cheDashboardConfigurationService = cheDashboardConfigurationService;
this.cheKubernetesNamespace = cheKubernetesNamespace;
this.cheNotification = cheNotification;
this.cheWorkspace = cheWorkspace;
@@ -121,6 +128,10 @@ export class WorkspaceDetailsOverviewController {
deRegistrationFn();
});
+ this.cheDashboardConfigurationService.ready.then(() => {
+ this.enabledKubernetesNamespaceSelector = this.cheDashboardConfigurationService.enabledFeature(TogglableFeature.KUBERNETES_NAMESPACE_SELECTOR);
+ });
+
this.init();
}
diff --git a/dashboard/src/app/workspaces/workspace-details/workspace-overview/workspace-details-overview.html b/dashboard/src/app/workspaces/workspace-details/workspace-overview/workspace-details-overview.html
index e46d662187..63d34e2fdd 100644
--- a/dashboard/src/app/workspaces/workspace-details/workspace-overview/workspace-details-overview.html
+++ b/dashboard/src/app/workspaces/workspace-details/workspace-overview/workspace-details-overview.html
@@ -29,7 +29,9 @@
-
;
@@ -60,6 +61,14 @@ interface IBrandingConfiguration {
cheCDN: string;
resources: string[];
};
+ features: {
+ disabled: TogglableFeature[];
+ };
+}
+
+export enum TogglableFeature {
+ WORKSPACE_SHARING = 'workspaceSharing',
+ KUBERNETES_NAMESPACE_SELECTOR = 'kubernetesNamespaceSelector',
}
const ASSET_PREFIX = 'assets/branding/';
@@ -321,7 +330,8 @@ export class CheBranding {
factory: this.branding.docs && this.branding.docs.factory ? this.branding.docs.factory : DEFAULT_DOCS_FACTORY,
organization: this.branding.docs && this.branding.docs.organization ? this.branding.docs.organization : DEFAULT_DOCS_ORGANIZATION,
general: this.branding.docs && this.branding.docs.general ? this.branding.docs.general : DEFAULT_DOCS_GENERAL,
- converting: this.branding.docs && this.branding.docs.converting ? this.branding.docs.converting : DEFAULT_DOCS_CONVERTING
+ converting: this.branding.docs && this.branding.docs.converting ? this.branding.docs.converting : DEFAULT_DOCS_CONVERTING,
+ faq: this.branding.docs && this.branding.docs.faq ? this.branding.docs.faq : undefined
};
}
@@ -344,10 +354,18 @@ export class CheBranding {
menu: {
disabled:
this.branding.configuration &&
- this.branding.configuration.menu && this.branding.configuration.menu.disabled
+ this.branding.configuration.menu && this.branding.configuration.menu.disabled
? this.branding.configuration.menu.disabled
: []
},
+ features: {
+ disabled:
+ this.branding.configuration &&
+ this.branding.configuration.features &&
+ this.branding.configuration.features.disabled
+ ? this.branding.configuration.features.disabled
+ : []
+ },
prefetch: {
cheCDN: this.branding.configuration &&
this.branding.configuration.prefetch &&
diff --git a/dashboard/src/components/branding/che-dashboard-configuration.service.ts b/dashboard/src/components/branding/che-dashboard-configuration.service.ts
index a0507d2c19..2804742cc7 100644
--- a/dashboard/src/components/branding/che-dashboard-configuration.service.ts
+++ b/dashboard/src/components/branding/che-dashboard-configuration.service.ts
@@ -11,7 +11,12 @@
*/
'use strict';
-import { CheBranding } from './che-branding.factory';
+import { CheBranding, TogglableFeature } from './che-branding.factory';
+
+export type FooterLink = {
+ title: string;
+ reference: string;
+};
/**
* This class handles configuration data of Dashboard.
@@ -35,6 +40,10 @@ export class CheDashboardConfigurationService {
this.cheBranding = cheBranding;
}
+ get ready(): ng.IPromise {
+ return this.cheBranding.ready;
+ }
+
allowedMenuItem(menuItem: che.ConfigurableMenuItem | string): boolean {
const disabledItems = this.cheBranding.getConfiguration().menu.disabled;
return (disabledItems as string[]).indexOf(menuItem) === -1;
@@ -48,4 +57,45 @@ export class CheDashboardConfigurationService {
});
}
+ enabledFeature(feature: TogglableFeature): boolean {
+ const disabledFeatures = this.cheBranding.getConfiguration().features.disabled;
+ return disabledFeatures.indexOf(feature) === -1;
+ }
+
+ getFooterLinks(): { [key: string]: FooterLink } {
+ const links: { [key: string]: FooterLink } = {};
+ if (this.cheBranding.getProductSupportEmail()) {
+ links.supportEmail = {
+ title: 'Make a wish',
+ reference: this.cheBranding.getProductSupportEmail()
+ };
+ }
+ if (this.cheBranding.getFooter().email) {
+ const email = this.cheBranding.getFooter().email;
+ links.email = {
+ title: email.title,
+ reference: email.address
+ };
+ }
+ if (this.cheBranding.getDocs().general) {
+ links.docs = {
+ title: 'Docs',
+ reference: this.cheBranding.getDocs().general
+ };
+ }
+ if (this.cheBranding.getDocs().faq) {
+ links.faq = {
+ title: 'FAQ',
+ reference: this.cheBranding.getDocs().faq
+ };
+ }
+ if (this.cheBranding.getProductHelpPath() && this.cheBranding.getProductHelpTitle()) {
+ links.supportPath = {
+ title: this.cheBranding.getProductHelpTitle(),
+ reference: this.cheBranding.getProductHelpPath()
+ };
+ }
+ return links;
+ }
+
}
diff --git a/dashboard/src/components/widget/footer/che-footer.controller.ts b/dashboard/src/components/widget/footer/che-footer.controller.ts
index 9141aa29f3..431d29c70c 100644
--- a/dashboard/src/components/widget/footer/che-footer.controller.ts
+++ b/dashboard/src/components/widget/footer/che-footer.controller.ts
@@ -11,6 +11,7 @@
*/
'use strict';
+import { CheDashboardConfigurationService, FooterLink } from '../../branding/che-dashboard-configuration.service';
/**
* This class is handling the controller for the footer.
@@ -19,7 +20,25 @@
*/
export class CheFooterController {
- $onInit(): void { }
+ static $inject = [
+ 'cheDashboardConfigurationService',
+ ];
+
+ links: { [key: string]: FooterLink };
+
+ private cheDashboardConfigurationService: CheDashboardConfigurationService;
+
+ constructor(
+ cheDashboardConfigurationService: CheDashboardConfigurationService,
+ ) {
+ this.cheDashboardConfigurationService = cheDashboardConfigurationService;
+ }
+
+ $onInit(): void {
+ this.cheDashboardConfigurationService.ready.then(() => {
+ this.links = this.cheDashboardConfigurationService.getFooterLinks();
+ });
+ }
/**
* Returns 'Make a wish' email subject.
diff --git a/dashboard/src/components/widget/footer/che-footer.directive.ts b/dashboard/src/components/widget/footer/che-footer.directive.ts
index 5e9cfb3b91..a4cd816a16 100644
--- a/dashboard/src/components/widget/footer/che-footer.directive.ts
+++ b/dashboard/src/components/widget/footer/che-footer.directive.ts
@@ -77,15 +77,9 @@ export class CheFooter {
this.controllerAs = 'cheFooterController';
this.scope = {
- supportHelpPath: '@cheSupportHelpPath',
- supportHelpTitle: '@cheSupportHelpTitle',
- supportEmail: '@cheSupportEmail',
logo: '@cheLogo',
- docs: '@cheDocs',
version: '@cheVersion',
productName: '@cheProductName',
- links: '=cheLinks',
- email: '=?cheEmail'
};
}
}
diff --git a/dashboard/src/components/widget/footer/che-footer.html b/dashboard/src/components/widget/footer/che-footer.html
index 7e79de6368..f5d5cb0bb5 100644
--- a/dashboard/src/components/widget/footer/che-footer.html
+++ b/dashboard/src/components/widget/footer/che-footer.html
@@ -16,15 +16,37 @@
flex-order-gt-sm="2" flex-order-sm="1" flex-order-xs="1"
layout="row" layout-align="start center">
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/dashboard/src/index.html b/dashboard/src/index.html
index 2a32bd7b3a..77d916b436 100644
--- a/dashboard/src/index.html
+++ b/dashboard/src/index.html
@@ -49,15 +49,9 @@
-
{{branding.footer.content}}