mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Using named badges
This commit is contained in:
parent
97802c8978
commit
c0e341bee1
18 changed files with 87 additions and 184 deletions
|
@ -36,6 +36,7 @@ const createSetupContractMock = () => {
|
|||
addApplicationClass: jest.fn(),
|
||||
removeApplicationClass: jest.fn(),
|
||||
getApplicationClasses$: jest.fn(),
|
||||
addNamedBadge: jest.fn(),
|
||||
getBadge$: jest.fn(),
|
||||
setBadge: jest.fn(),
|
||||
getBreadcrumbs$: jest.fn(),
|
||||
|
|
|
@ -81,7 +81,8 @@ export class ChromeService {
|
|||
const applicationClasses$ = new Rx.BehaviorSubject<Set<string>>(new Set());
|
||||
const helpExtension$ = new Rx.BehaviorSubject<ChromeHelpExtension | undefined>(undefined);
|
||||
const breadcrumbs$ = new Rx.BehaviorSubject<ChromeBreadcrumb[]>([]);
|
||||
const badge$ = new Rx.BehaviorSubject<ChromeBadge | undefined>(undefined);
|
||||
const badge$ = new Rx.BehaviorSubject<ChromeBadge | undefined | string>(undefined);
|
||||
const namedBadges = new Map<string, ChromeBadge>();
|
||||
|
||||
if (!this.browserSupportsCsp && injectedMetadata.getCspConfig().warnLegacyBrowsers) {
|
||||
notifications.toasts.addWarning(
|
||||
|
@ -182,15 +183,26 @@ export class ChromeService {
|
|||
takeUntil(this.stop$)
|
||||
),
|
||||
|
||||
/**
|
||||
* Sets a named badge which can be used by setBadge
|
||||
*/
|
||||
addNamedBadge: (name: string, badge: ChromeBadge) => {
|
||||
namedBadges.set(name, badge);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get an observable of the current badge
|
||||
*/
|
||||
getBadge$: () => badge$.pipe(takeUntil(this.stop$)),
|
||||
getBadge$: (): Rx.Observable<ChromeBadge | undefined> =>
|
||||
badge$.pipe(
|
||||
map(badge => (typeof badge === 'string' ? namedBadges.get(badge) : badge)),
|
||||
takeUntil(this.stop$)
|
||||
),
|
||||
|
||||
/**
|
||||
* Override the current badge
|
||||
*/
|
||||
setBadge: (badge: ChromeBadge | undefined) => {
|
||||
setBadge: (badge: ChromeBadge | undefined | string) => {
|
||||
badge$.next(badge);
|
||||
},
|
||||
|
||||
|
|
|
@ -58,19 +58,10 @@ uiRoutes
|
|||
.defaults(/dashboard/, {
|
||||
requireDefaultIndex: true,
|
||||
requireUICapability: 'dashboard.show',
|
||||
badge: (i18n, uiCapabilities) => {
|
||||
if (uiCapabilities.dashboard.showWriteControls) {
|
||||
return undefined;
|
||||
badge: (uiCapabilities) => {
|
||||
if (!uiCapabilities.dashboard.showWriteControls) {
|
||||
return 'readOnly';
|
||||
}
|
||||
|
||||
return {
|
||||
text: i18n('kbn.dashboard.badge.readOnly.text', {
|
||||
defaultMessage: 'Read Only',
|
||||
}),
|
||||
tooltip: i18n('kbn.dashboard.badge.readOnly.tooltip', {
|
||||
defaultMessage: 'You lack the authority',
|
||||
}),
|
||||
};
|
||||
}
|
||||
})
|
||||
.when(DashboardConstants.LANDING_PAGE_PATH, {
|
||||
|
|
|
@ -34,19 +34,10 @@ uiRoutes
|
|||
});
|
||||
|
||||
uiRoutes.defaults(/^\/dev_tools(\/|$)/, {
|
||||
badge: (i18n, uiCapabilities) => {
|
||||
if (uiCapabilities.dev_tools.save) {
|
||||
return undefined;
|
||||
badge: (uiCapabilities) => {
|
||||
if (!uiCapabilities.dev_tools.save) {
|
||||
return 'readOnly';
|
||||
}
|
||||
|
||||
return {
|
||||
text: i18n('kbn.devTools.badge.readOnly.text', {
|
||||
defaultMessage: 'Read Only',
|
||||
}),
|
||||
tooltip: i18n('kbn.devTools.badge.readOnly.tooltip', {
|
||||
defaultMessage: 'You lack the authority',
|
||||
}),
|
||||
};
|
||||
},
|
||||
k7Breadcrumbs: (i18n) => [
|
||||
{
|
||||
|
|
|
@ -90,19 +90,10 @@ uiRoutes
|
|||
? getSavedSearchBreadcrumbs
|
||||
: getRootBreadcrumbs
|
||||
),
|
||||
badge: (i18n, uiCapabilities) => {
|
||||
if (uiCapabilities.discover.save) {
|
||||
return undefined;
|
||||
badge: (uiCapabilities) => {
|
||||
if (!uiCapabilities.discover.save) {
|
||||
return 'readOnly';
|
||||
}
|
||||
|
||||
return {
|
||||
text: i18n('kbn.discover.badge.readOnly.text', {
|
||||
defaultMessage: 'Read Only',
|
||||
}),
|
||||
tooltip: i18n('kbn.discover.badge.readOnly.tooltip', {
|
||||
defaultMessage: 'You lack the authority',
|
||||
}),
|
||||
};
|
||||
}
|
||||
})
|
||||
.when('/discover/:id?', {
|
||||
|
|
|
@ -86,19 +86,10 @@ uiRoutes
|
|||
.defaults(/management\/kibana\/(index_patterns|index_pattern)/, {
|
||||
resolve: indexPatternsResolutions,
|
||||
requireUICapability: 'management.kibana.index_patterns',
|
||||
badge: (i18n, uiCapabilities) => {
|
||||
if (uiCapabilities.indexPatterns.save) {
|
||||
return undefined;
|
||||
badge: (uiCapabilities) => {
|
||||
if (!uiCapabilities.indexPatterns.save) {
|
||||
return 'readOnly';
|
||||
}
|
||||
|
||||
return {
|
||||
text: i18n('kbn.management.indexPatterns.badge.readOnly.text', {
|
||||
defaultMessage: 'Read Only',
|
||||
}),
|
||||
tooltip: i18n('kbn.management.indexPatterns.badge.readOnly.tooltip', {
|
||||
defaultMessage: 'You lack the authority',
|
||||
}),
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -63,19 +63,10 @@ uiRoutes
|
|||
template: indexTemplate,
|
||||
k7Breadcrumbs: getBreadcrumbs,
|
||||
requireUICapability: 'management.kibana.settings',
|
||||
badge: (i18n, uiCapabilities) => {
|
||||
if (uiCapabilities.advancedSettings.save) {
|
||||
return undefined;
|
||||
badge: (uiCapabilities) => {
|
||||
if (!uiCapabilities.advancedSettings.save) {
|
||||
return 'readOnly';
|
||||
}
|
||||
|
||||
return {
|
||||
text: i18n('kbn.management.advancedSettings.badge.readOnly.text', {
|
||||
defaultMessage: 'Read Only',
|
||||
}),
|
||||
tooltip: i18n('kbn.management.advancedSettings.badge.readOnly.tooltip', {
|
||||
defaultMessage: 'You lack the authority',
|
||||
}),
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -33,19 +33,10 @@ uiRoutes
|
|||
.defaults(/visualize/, {
|
||||
requireDefaultIndex: true,
|
||||
requireUICapability: 'visualize.show',
|
||||
badge: (i18n, uiCapabilities) => {
|
||||
if (uiCapabilities.visualize.save) {
|
||||
return undefined;
|
||||
badge: (uiCapabilities) => {
|
||||
if (!uiCapabilities.visualize.save) {
|
||||
return 'readOnly';
|
||||
}
|
||||
|
||||
return {
|
||||
text: i18n('kbn.visualize.badge.readOnly.text', {
|
||||
defaultMessage: 'Read Only',
|
||||
}),
|
||||
tooltip: i18n('kbn.visualize.badge.readOnly.tooltip', {
|
||||
defaultMessage: 'You lack the authority',
|
||||
}),
|
||||
};
|
||||
}
|
||||
})
|
||||
.when(VisualizeConstants.LANDING_PAGE_PATH, {
|
||||
|
|
|
@ -72,19 +72,10 @@ require('ui/routes')
|
|||
? getSavedSheetBreadcrumbs
|
||||
: getCreateBreadcrumbs
|
||||
),
|
||||
badge: (i18n, uiCapabilities) => {
|
||||
if (uiCapabilities.timelion.save) {
|
||||
return undefined;
|
||||
badge: (uiCapabilities) => {
|
||||
if (!uiCapabilities.timelion.save) {
|
||||
return 'readOnly';
|
||||
}
|
||||
|
||||
return {
|
||||
text: i18n('kbn.timelion.badge.readOnly.text', {
|
||||
defaultMessage: 'Read Only',
|
||||
}),
|
||||
tooltip: i18n('kbn.timelion.badge.readOnly.tooltip', {
|
||||
defaultMessage: 'You lack the authority',
|
||||
}),
|
||||
};
|
||||
},
|
||||
resolve: {
|
||||
savedSheet: function (redirectWhenMissing, savedSheets, $route) {
|
||||
|
|
|
@ -62,6 +62,10 @@ function createBadgeApi(chrome: { [key: string]: any }) {
|
|||
set(newBadge: Badge | undefined) {
|
||||
newPlatformChrome.setBadge(newBadge);
|
||||
},
|
||||
|
||||
addNamedBadge(name: string, badge: Badge) {
|
||||
newPlatformChrome.addNamedBadge(name, badge);
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,33 +4,18 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { InjectedIntl, injectI18n } from '@kbn/i18n/react';
|
||||
import React from 'react';
|
||||
import { injectUICapabilities, UICapabilities } from 'ui/capabilities/react';
|
||||
import chrome from 'ui/chrome';
|
||||
|
||||
interface Props {
|
||||
uiCapabilities: UICapabilities;
|
||||
intl: InjectedIntl;
|
||||
}
|
||||
|
||||
class UpdateBadgeComponent extends React.Component<Props> {
|
||||
public componentDidMount() {
|
||||
const { uiCapabilities, intl } = this.props;
|
||||
chrome.badge.set(
|
||||
!uiCapabilities.apm.save
|
||||
? {
|
||||
text: intl.formatMessage({
|
||||
defaultMessage: 'Read Only',
|
||||
id: 'xpack.apm.header.badge.readOnly.text'
|
||||
}),
|
||||
tooltip: intl.formatMessage({
|
||||
defaultMessage: 'You lack the authority',
|
||||
id: 'xpack.aapm.header.badge.readOnly.tooltip'
|
||||
})
|
||||
}
|
||||
: undefined
|
||||
);
|
||||
const { uiCapabilities } = this.props;
|
||||
chrome.badge.set(!uiCapabilities.apm.save ? 'readOnly' : undefined);
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
@ -38,6 +23,4 @@ class UpdateBadgeComponent extends React.Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
export const UpdateBadge = injectUICapabilities(
|
||||
injectI18n(UpdateBadgeComponent)
|
||||
);
|
||||
export const UpdateBadge = injectUICapabilities(UpdateBadgeComponent);
|
||||
|
|
|
@ -9,7 +9,6 @@ import './angular/config';
|
|||
import './angular/services';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import chrome from 'ui/chrome';
|
||||
import { uiCapabilities } from 'ui/capabilities';
|
||||
import { CanvasRootController } from './angular/controllers';
|
||||
|
@ -39,15 +38,4 @@ chrome.helpExtension.set(domNode => {
|
|||
});
|
||||
|
||||
// set the read-only badge when appropriate
|
||||
chrome.badge.set(
|
||||
uiCapabilities.canvas.save
|
||||
? undefined
|
||||
: {
|
||||
text: i18n.translate('xpack.canvas.badge.readOnly.text', {
|
||||
defaultMessage: 'Read Only',
|
||||
}),
|
||||
tooltip: i18n.translate('xpack.canvas.badge.readOnly.tooltip', {
|
||||
defaultMessage: 'You lack the authority',
|
||||
}),
|
||||
}
|
||||
);
|
||||
chrome.badge.set(!uiCapabilities.canvas.save ? 'readOnly' : undefined);
|
||||
|
|
|
@ -6,16 +6,7 @@
|
|||
|
||||
|
||||
export function getReadonlyBadge(i18n, uiCapabilities) {
|
||||
if (uiCapabilities.graph.save) {
|
||||
return null;
|
||||
if (!uiCapabilities.graph.save) {
|
||||
return 'readOnly';
|
||||
}
|
||||
|
||||
return {
|
||||
text: i18n('xpack.graph.badge.readOnly.text', {
|
||||
defaultMessage: 'Read Only',
|
||||
}),
|
||||
tooltip: i18n('xpack.graph.badge.readOnly.tooltip', {
|
||||
defaultMessage: 'You lack the authority',
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
import React from 'react';
|
||||
|
||||
import { InjectedIntl, injectI18n } from '@kbn/i18n/react';
|
||||
import { Breadcrumb } from 'ui/chrome/api/breadcrumbs';
|
||||
import { WithKibanaChrome } from '../../containers/with_kibana_chrome';
|
||||
import { ExternalHeader } from './external_header';
|
||||
|
@ -14,33 +13,17 @@ import { ExternalHeader } from './external_header';
|
|||
interface HeaderProps {
|
||||
breadcrumbs?: Breadcrumb[];
|
||||
readOnlyBadge?: boolean;
|
||||
intl: InjectedIntl;
|
||||
}
|
||||
|
||||
export const Header = injectI18n(
|
||||
({ breadcrumbs = [], readOnlyBadge = false, intl }: HeaderProps) => (
|
||||
<WithKibanaChrome>
|
||||
{({ setBreadcrumbs, setBadge }) => (
|
||||
<ExternalHeader
|
||||
breadcrumbs={breadcrumbs}
|
||||
setBreadcrumbs={setBreadcrumbs}
|
||||
badge={
|
||||
readOnlyBadge
|
||||
? {
|
||||
text: intl.formatMessage({
|
||||
defaultMessage: 'Read Only',
|
||||
id: 'xpack.infra.header.badge.readOnly.text',
|
||||
}),
|
||||
tooltip: intl.formatMessage({
|
||||
defaultMessage: 'You lack the authority',
|
||||
id: 'xpack.infra.header.badge.readOnly.tooltip',
|
||||
}),
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
setBadge={setBadge}
|
||||
/>
|
||||
)}
|
||||
</WithKibanaChrome>
|
||||
)
|
||||
export const Header = ({ breadcrumbs = [], readOnlyBadge = false }: HeaderProps) => (
|
||||
<WithKibanaChrome>
|
||||
{({ setBreadcrumbs, setBadge }) => (
|
||||
<ExternalHeader
|
||||
breadcrumbs={breadcrumbs}
|
||||
setBreadcrumbs={setBreadcrumbs}
|
||||
badge={readOnlyBadge ? 'readOnly' : undefined}
|
||||
setBadge={setBadge}
|
||||
/>
|
||||
)}
|
||||
</WithKibanaChrome>
|
||||
);
|
||||
|
|
|
@ -39,6 +39,12 @@ import { recentlyAccessed } from 'ui/persisted_log';
|
|||
|
||||
const app = uiModules.get('app/maps', ['ngRoute', 'react']);
|
||||
|
||||
const badge = (uiCapabilities) => {
|
||||
if (!uiCapabilities.maps.save) {
|
||||
return 'readOnly';
|
||||
}
|
||||
};
|
||||
|
||||
app.directive('mapListing', function (reactDirective) {
|
||||
return reactDirective(MapListing);
|
||||
});
|
||||
|
@ -46,24 +52,9 @@ app.directive('mapListing', function (reactDirective) {
|
|||
routes.enable();
|
||||
|
||||
routes
|
||||
.defaults(/.*/, {
|
||||
badge: (i18n, uiCapabilities) => {
|
||||
if (uiCapabilities.maps.save) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
text: i18n('xpack.maps.badge.readOnly.text', {
|
||||
defaultMessage: 'Read Only',
|
||||
}),
|
||||
tooltip: i18n('xpack.maps.badge.readOnly.tooltip', {
|
||||
defaultMessage: 'You lack the authority',
|
||||
}),
|
||||
};
|
||||
}
|
||||
})
|
||||
.when('/', {
|
||||
template: listingTemplate,
|
||||
badge,
|
||||
controller($scope, gisMapSavedObjectLoader, config) {
|
||||
$scope.listingLimit = config.get('savedObjects:listingLimit');
|
||||
$scope.find = (search) => {
|
||||
|
@ -90,6 +81,7 @@ routes
|
|||
.when('/map', {
|
||||
template: mapTemplate,
|
||||
controller: 'GisMapController',
|
||||
badge,
|
||||
resolve: {
|
||||
map: function (gisMapSavedObjectLoader, redirectWhenMissing) {
|
||||
return gisMapSavedObjectLoader.get()
|
||||
|
@ -102,6 +94,7 @@ routes
|
|||
.when('/map/:id', {
|
||||
template: mapTemplate,
|
||||
controller: 'GisMapController',
|
||||
badge,
|
||||
resolve: {
|
||||
map: function (gisMapSavedObjectLoader, redirectWhenMissing, $route,
|
||||
Private) {
|
||||
|
|
|
@ -91,7 +91,8 @@ export const security = (kibana) => new kibana.Plugin({
|
|||
}],
|
||||
hacks: [
|
||||
'plugins/security/hacks/on_session_timeout',
|
||||
'plugins/security/hacks/on_unauthorized_response'
|
||||
'plugins/security/hacks/on_unauthorized_response',
|
||||
'plugins/security/hacks/badges',
|
||||
],
|
||||
home: ['plugins/security/register_feature'],
|
||||
injectDefaultVars: function (server) {
|
||||
|
|
17
x-pack/plugins/security/public/hacks/badges.ts
Normal file
17
x-pack/plugins/security/public/hacks/badges.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import chrome from 'ui/chrome';
|
||||
|
||||
chrome.badge.addNamedBadge('readOnly', {
|
||||
text: i18n.translate('xpack.security.badges.readOnly.text', {
|
||||
defaultMessage: 'Read Only',
|
||||
}),
|
||||
tooltip: i18n.translate('xpack.security.badges.readOnly.tooltip', {
|
||||
defaultMessage: `You're not authorized to save changes.`,
|
||||
}),
|
||||
});
|
|
@ -149,14 +149,7 @@ class Application extends React.Component<UptimeAppProps, UptimeAppState> {
|
|||
|
||||
public componentWillMount() {
|
||||
this.setBreadcrumbs([overviewBreadcrumb]);
|
||||
this.setBadge(
|
||||
!uiCapabilities.uptime.save
|
||||
? {
|
||||
text: 'Read Only',
|
||||
tooltip: 'You lack the authority',
|
||||
}
|
||||
: undefined
|
||||
);
|
||||
this.setBadge(!uiCapabilities.uptime.save ? 'readOnly' : undefined);
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue