From 0dfe9bee39fd0ba8575a76c8f7bafa742ceb034f Mon Sep 17 00:00:00 2001 From: Oleksii Kurinnyi Date: Mon, 10 Feb 2020 17:26:35 +0200 Subject: [PATCH] [UD] Make some features togglable, add optional FAQ button (#15907) * Make some UD features togglable. Allows to configure in `product.json` whether to show workspace sharing tab and kubernetes namespace selector or not. Signed-off-by: Oleksii Kurinnyi * Add optional FAQ button into footer Signed-off-by: Oleksii Kurinnyi * Update README.md Signed-off-by: Oleksii Kurinnyi * fixup! Make some UD features togglable. --- dashboard/README.md | 14 +++++ .../import-custom-stack.controller.ts | 19 +++++-- .../import-custom-stack.html | 5 +- .../ready-to-go-stacks.controller.ts | 14 ++++- .../ready-to-go-stacks.html | 5 +- .../workspace-details.directive.spec.ts | 5 +- .../workspace-details.service.ts | 37 ++++++++----- .../workspace-details-overview.controller.ts | 11 ++++ .../workspace-details-overview.html | 4 +- .../branding/che-branding.factory.ts | 22 +++++++- .../che-dashboard-configuration.service.ts | 52 ++++++++++++++++++- .../widget/footer/che-footer.controller.ts | 21 +++++++- .../widget/footer/che-footer.directive.ts | 6 --- .../components/widget/footer/che-footer.html | 38 +++++++++++--- dashboard/src/index.html | 8 +-- 15 files changed, 213 insertions(+), 48 deletions(-) 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"> - Make a wish - {{cheFooterController.email.title}} - Docs - {{cheFooterController.supportHelpTitle}} - {{link.title}} + {{cheFooterController.links.supportEmail.title}} + + {{cheFooterController.links.email.title}} + + {{cheFooterController.links.docs.title}} + + {{cheFooterController.links.faq.title}} + + {{cheFooterController.links.supportPath.title}} + 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}}