From fcf8a9bacb2860d6973627e0b5fe5d88a3b2d5be Mon Sep 17 00:00:00 2001 From: Rares Mardare Date: Mon, 8 May 2023 08:42:08 +0300 Subject: [PATCH] Templates&Grouping tweaks&improvements (#1879) # What this PR does ## Which issue(s) this PR fixes - Adds option to go back to the Integrations table - Fixed IntegrationCollapsibleTreeView component issue on expand/collapse - Reused/Renamed old CounterBadge to TooltipBadge - Added maintenance until/hearbeat display to integration - Changed `maintenace until` display on Integrations table --- .../components/CounterBadge/CounterBadge.tsx | 55 ---- .../IntegrationCollapsibleTreeView.tsx | 7 +- .../ScheduleQuality/ScheduleQuality.tsx | 10 +- .../TooltipBadge.module.scss} | 12 +- .../components/TooltipBadge/TooltipBadge.tsx | 72 +++++ .../src/models/alert_receive_channel.ts | 2 +- .../alert_receive_channel.types.ts | 5 +- .../src/pages/incident/Incident.module.scss | 2 +- .../integration_2/Integration2.helper.ts | 18 ++ .../integration_2/Integration2.module.scss | 15 +- .../src/pages/integration_2/Integration2.tsx | 257 ++++++++++-------- .../pages/integrations_2/Integrations2.tsx | 57 +--- .../src/pages/schedules/Schedules.tsx | 10 +- grafana-plugin/src/pages/users/Users.tsx | 6 +- grafana-plugin/src/style/vars.css | 2 + 15 files changed, 301 insertions(+), 229 deletions(-) delete mode 100644 grafana-plugin/src/components/CounterBadge/CounterBadge.tsx rename grafana-plugin/src/components/{CounterBadge/CounterBadge.module.scss => TooltipBadge/TooltipBadge.module.scss} (78%) create mode 100644 grafana-plugin/src/components/TooltipBadge/TooltipBadge.tsx diff --git a/grafana-plugin/src/components/CounterBadge/CounterBadge.tsx b/grafana-plugin/src/components/CounterBadge/CounterBadge.tsx deleted file mode 100644 index ef03048d..00000000 --- a/grafana-plugin/src/components/CounterBadge/CounterBadge.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import React, { FC } from 'react'; - -import { Icon, Tooltip, IconName, VerticalGroup, HorizontalGroup } from '@grafana/ui'; -import cn from 'classnames/bind'; - -import Text, { TextType } from 'components/Text/Text'; - -import styles from './CounterBadge.module.scss'; - -interface CounterBadgeProps { - borderType: Partial; - count: number | string; - tooltipTitle: string; - tooltipContent: React.ReactNode; - - icon?: string; - addPadding?: boolean; - - onHover?: () => void; -} - -const cx = cn.bind(styles); - -const CounterBadge: FC = (props) => { - const { borderType, count, tooltipTitle, tooltipContent, onHover, addPadding, icon } = props; - - return ( - - - {tooltipTitle} - {tooltipContent && {tooltipContent}} - - - } - > -
- - {icon && ( - - )} - {count} - -
-
- ); -}; - -export default CounterBadge; diff --git a/grafana-plugin/src/components/IntegrationCollapsibleTreeView/IntegrationCollapsibleTreeView.tsx b/grafana-plugin/src/components/IntegrationCollapsibleTreeView/IntegrationCollapsibleTreeView.tsx index 0db3a694..bd1446da 100644 --- a/grafana-plugin/src/components/IntegrationCollapsibleTreeView/IntegrationCollapsibleTreeView.tsx +++ b/grafana-plugin/src/components/IntegrationCollapsibleTreeView/IntegrationCollapsibleTreeView.tsx @@ -13,6 +13,7 @@ export interface IntegrationCollapsibleItem { expandedView: React.ReactNode; collapsedView: React.ReactNode; isCollapsible: boolean; + isExpanded?: boolean; } interface IntegrationCollapsibleTreeViewProps { @@ -53,7 +54,11 @@ const IntegrationCollapsibleTreeView: React.FC { const expandedArrayValues = new Array(configElements.length); configElements.forEach((elem, index) => { - expandedArrayValues[index] = Array.isArray(elem) ? new Array(elem.length).fill(true) : true; + if (Array.isArray(elem)) { + expandedArrayValues[index] = elem.map((el) => !el.isCollapsible || el.isExpanded); + } else { + expandedArrayValues[index] = !elem.isCollapsible || elem.isExpanded; + } }); return expandedArrayValues; diff --git a/grafana-plugin/src/components/ScheduleQuality/ScheduleQuality.tsx b/grafana-plugin/src/components/ScheduleQuality/ScheduleQuality.tsx index 61951ca0..0b97dd7c 100644 --- a/grafana-plugin/src/components/ScheduleQuality/ScheduleQuality.tsx +++ b/grafana-plugin/src/components/ScheduleQuality/ScheduleQuality.tsx @@ -3,11 +3,11 @@ import React, { FC, useEffect, useState } from 'react'; import { Tooltip, VerticalGroup } from '@grafana/ui'; import cn from 'classnames/bind'; -import CounterBadge from 'components/CounterBadge/CounterBadge'; import PluginLink from 'components/PluginLink/PluginLink'; import { ScheduleQualityDetails } from 'components/ScheduleQualityDetails/ScheduleQualityDetails'; import Tag from 'components/Tag/Tag'; import Text from 'components/Text/Text'; +import TooltipBadge from 'components/TooltipBadge/TooltipBadge'; import { Schedule, ScheduleScoreQualityResponse, ScheduleScoreQualityResult } from 'models/schedule/schedule.types'; import { useStore } from 'state/useStore'; @@ -40,10 +40,10 @@ const ScheduleQuality: FC = ({ schedule, lastUpdated }) => <>
{relatedEscalationChains?.length > 0 && schedule?.number_of_escalation_chains > 0 && ( - @@ -60,10 +60,10 @@ const ScheduleQuality: FC = ({ schedule, lastUpdated }) => )} {schedule.warnings?.length > 0 && ( - diff --git a/grafana-plugin/src/components/CounterBadge/CounterBadge.module.scss b/grafana-plugin/src/components/TooltipBadge/TooltipBadge.module.scss similarity index 78% rename from grafana-plugin/src/components/CounterBadge/CounterBadge.module.scss rename to grafana-plugin/src/components/TooltipBadge/TooltipBadge.module.scss index 1e09831f..99f79199 100644 --- a/grafana-plugin/src/components/CounterBadge/CounterBadge.module.scss +++ b/grafana-plugin/src/components/TooltipBadge/TooltipBadge.module.scss @@ -2,12 +2,7 @@ font-size: 12px; line-height: 16px; padding: 3px 4px; - - &--link, - &--warning, - &--success { - border-radius: 2px; - } + border-radius: 2px; &--primary { background: var(--tag-background-primary); @@ -24,6 +19,11 @@ border: 1px solid var(--tag-border-success); color: var(--tag-text-success); } + &--danger { + background: var(--tag-background-danger); + border: 1px solid var(--tag-border-danger); + color: var(--tag-text-danger); + } &--padding { padding: 3px 10px; diff --git a/grafana-plugin/src/components/TooltipBadge/TooltipBadge.tsx b/grafana-plugin/src/components/TooltipBadge/TooltipBadge.tsx new file mode 100644 index 00000000..cdbef993 --- /dev/null +++ b/grafana-plugin/src/components/TooltipBadge/TooltipBadge.tsx @@ -0,0 +1,72 @@ +import React, { FC } from 'react'; + +import { Icon, Tooltip, IconName, VerticalGroup, HorizontalGroup } from '@grafana/ui'; +import cn from 'classnames/bind'; + +import Text, { TextType } from 'components/Text/Text'; + +import styles from './TooltipBadge.module.scss'; + +interface TooltipBadgeProps { + className?: string; + borderType: Partial; + text?: number | string; + tooltipTitle: string; + tooltipContent: React.ReactNode; + + icon?: IconName; + customIcon?: React.ReactNode; + addPadding?: boolean; + + onHover?: () => void; +} + +const cx = cn.bind(styles); + +const TooltipBadge: FC = (props) => { + const { borderType, text, tooltipTitle, tooltipContent, onHover, addPadding, icon, customIcon, className } = props; + + return ( + + + {tooltipTitle} + {tooltipContent && {tooltipContent}} + +
+ } + > +
+ + {renderIcon()} + {text && {text}} + +
+ + ); + + function renderIcon() { + if (customIcon) { + return customIcon; + } + if (!icon) { + return null; + } + + return ; + } +}; + +export default TooltipBadge; diff --git a/grafana-plugin/src/models/alert_receive_channel.ts b/grafana-plugin/src/models/alert_receive_channel.ts index b092335e..76f95d0f 100644 --- a/grafana-plugin/src/models/alert_receive_channel.ts +++ b/grafana-plugin/src/models/alert_receive_channel.ts @@ -23,7 +23,7 @@ export interface AlertReceiveChannel { instructions: string; demo_alert_enabled: boolean; maintenance_mode?: MaintenanceMode; - maintenance_till?: string; + maintenance_till?: number; heartbeat: Heartbeat | null; is_available_for_integration_heartbeat: boolean; } diff --git a/grafana-plugin/src/models/alert_receive_channel/alert_receive_channel.types.ts b/grafana-plugin/src/models/alert_receive_channel/alert_receive_channel.types.ts index 1826ba2b..940efc28 100644 --- a/grafana-plugin/src/models/alert_receive_channel/alert_receive_channel.types.ts +++ b/grafana-plugin/src/models/alert_receive_channel/alert_receive_channel.types.ts @@ -4,8 +4,8 @@ import { Heartbeat } from 'models/heartbeat/heartbeat.types'; import { UserDTO as User } from 'models/user'; export enum MaintenanceMode { - Debug, - Maintenance, + Debug = 0, + Maintenance = 1, } export interface AlertReceiveChannel { @@ -26,6 +26,7 @@ export interface AlertReceiveChannel { instructions: string; demo_alert_enabled: boolean; maintenance_mode?: MaintenanceMode; + maintenance_till?: number; heartbeat: Heartbeat | null; is_available_for_integration_heartbeat: boolean; allow_delete: boolean; diff --git a/grafana-plugin/src/pages/incident/Incident.module.scss b/grafana-plugin/src/pages/incident/Incident.module.scss index 0779bd1a..188fcfc3 100644 --- a/grafana-plugin/src/pages/incident/Incident.module.scss +++ b/grafana-plugin/src/pages/incident/Incident.module.scss @@ -106,7 +106,7 @@ } .blue { - background: var(--timeline-icon-background-resolution-note); + background: var(--tag-border-primary); } .timeline-title { diff --git a/grafana-plugin/src/pages/integration_2/Integration2.helper.ts b/grafana-plugin/src/pages/integration_2/Integration2.helper.ts index 06f1b458..198e4070 100644 --- a/grafana-plugin/src/pages/integration_2/Integration2.helper.ts +++ b/grafana-plugin/src/pages/integration_2/Integration2.helper.ts @@ -1,3 +1,6 @@ +import dayjs from 'dayjs'; + +import { MaintenanceMode } from 'models/alert_receive_channel'; import { ChannelFilter } from 'models/channel_filter'; import { MAX_CHARACTERS_COUNT, TEXTAREA_ROWS_COUNT } from './Integration2.config'; @@ -36,6 +39,21 @@ const IntegrationHelper = { } return routeIndex ? 'Else' : 'If'; }, + + getMaintenanceText(maintenanceUntill: number, mode: number = undefined) { + const date = dayjs(new Date(maintenanceUntill * 1000)); + const now = dayjs(); + const hourDiff = date.diff(now, 'hours'); + const minDiff = date.diff(now, 'minutes'); + const totalMinDiff = minDiff - hourDiff * 60; + const totalDiffString = `${hourDiff}h ${totalMinDiff}m left`; + + if (mode) { + return `${mode === MaintenanceMode.Debug ? 'Debug Maintenance' : 'Maintenance'}: ${totalDiffString}`; + } + + return totalDiffString; + }, }; export default IntegrationHelper; diff --git a/grafana-plugin/src/pages/integration_2/Integration2.module.scss b/grafana-plugin/src/pages/integration_2/Integration2.module.scss index 06f13b04..bc297d1b 100644 --- a/grafana-plugin/src/pages/integration_2/Integration2.module.scss +++ b/grafana-plugin/src/pages/integration_2/Integration2.module.scss @@ -2,13 +2,19 @@ $FLEX-GAP: 4px; $MARGIN: 12px; $ITEMS-MARGIN: 24px; -.integration__heading-container { +.integration__heading-container, +.integration__subheading-container { margin-bottom: $ITEMS-MARGIN; } +.integration__heading-container { + display: flex; + gap: $FLEX-GAP; +} + .integration__heading { display: flex; - justify-content: space-between; + justify-content: flex-end; flex-direction: row; width: 100%; } @@ -16,6 +22,7 @@ $ITEMS-MARGIN: 24px; .integration__actions { display: flex; gap: $FLEX-GAP; + margin-left: auto; } .integration__actionsList { @@ -103,3 +110,7 @@ $ITEMS-MARGIN: 24px; .how-to-connect__tag { height: 25px; } + +.heartbeat-badge { + padding: 4px 12px; +} diff --git a/grafana-plugin/src/pages/integration_2/Integration2.tsx b/grafana-plugin/src/pages/integration_2/Integration2.tsx index a91d3ca1..fab7a6e2 100644 --- a/grafana-plugin/src/pages/integration_2/Integration2.tsx +++ b/grafana-plugin/src/pages/integration_2/Integration2.tsx @@ -1,7 +1,6 @@ import React, { useRef } from 'react'; import { - Badge, Button, HorizontalGroup, VerticalGroup, @@ -10,6 +9,7 @@ import { Tooltip, Modal, CascaderOption, + IconButton, } from '@grafana/ui'; import cn from 'classnames/bind'; import { get } from 'lodash-es'; @@ -19,7 +19,6 @@ import Emoji from 'react-emoji-render'; import { RouteComponentProps, withRouter } from 'react-router-dom'; import { TemplateForEdit, templateForEdit } from 'components/AlertTemplates/AlertTemplatesForm.config'; -import CounterBadge from 'components/CounterBadge/CounterBadge'; import IntegrationCollapsibleTreeView, { IntegrationCollapsibleItem, } from 'components/IntegrationCollapsibleTreeView/IntegrationCollapsibleTreeView'; @@ -31,12 +30,14 @@ import PluginLink from 'components/PluginLink/PluginLink'; import SourceCode from 'components/SourceCode/SourceCode'; import Tag from 'components/Tag/Tag'; import Text from 'components/Text/Text'; +import TooltipBadge from 'components/TooltipBadge/TooltipBadge'; import WithConfirm from 'components/WithConfirm/WithConfirm'; import { WithContextMenu } from 'components/WithContextMenu/WithContextMenu'; import IntegrationTemplate from 'containers/IntegrationTemplate/IntegrationTemplate'; import TeamName from 'containers/TeamName/TeamName'; import UserDisplayWithAvatar from 'containers/UserDisplay/UserDisplayWithAvatar'; import { WithPermissionControlTooltip } from 'containers/WithPermissionControl/WithPermissionControlTooltip'; +import { HeartGreenIcon, HeartRedIcon } from 'icons'; import { AlertReceiveChannel } from 'models/alert_receive_channel'; import { ChannelFilter } from 'models/channel_filter'; import { PageProps, WithStoreProps } from 'state/types'; @@ -54,7 +55,6 @@ import IntegrationHelper from './Integration2.helper'; import styles from './Integration2.module.scss'; import IntegrationBlock from './IntegrationBlock'; import IntegrationTemplateList from './IntegrationTemplatesList'; -// import { toJS } from 'mobx'; const cx = cn.bind(styles); @@ -127,80 +127,85 @@ class Integration2 extends React.Component {() => (
-
-

- -

-
- - - + + + +

+ +

- ( -
-
this.openIntegrationSettings(id, closeMenu)} - > - Integration Settings -
- -
this.openHearbeat(id, closeMenu)}> - Hearbeat -
- -
this.openStartMaintenance(id, closeMenu)} - > - Start Maintenance -
- -
- - -
- - Are you sure you want to delete {' '} - integration? - - } - > -
this.deleteIntegration(id, closeMenu)}> -
{ - // work-around to prevent 2 modals showing (withContextMenu and ConfirmModal) - const contextMenuEl = - document.querySelector('#integration-menu-options'); - if (contextMenuEl) { - contextMenuEl.style.display = 'none'; - } - }} - > - Stop Maintenance -
-
-
-
-
-
- )} +
+ +
+ Send demo alert + + + + ( +
+
this.openIntegrationSettings(id, closeMenu)} + > + Integration Settings +
+ +
this.openHearbeat(id, closeMenu)}> + Hearbeat +
+ +
this.openStartMaintenance(id, closeMenu)} + > + Start Maintenance +
+ +
+ + +
+ + Are you sure you want to delete {' '} + integration? + + } + > +
this.deleteIntegration(id, closeMenu)}> +
{ + // work-around to prevent 2 modals showing (withContextMenu and ConfirmModal) + const contextMenuEl = + document.querySelector('#integration-menu-options'); + if (contextMenuEl) { + contextMenuEl.style.display = 'none'; + } + }} + > + Stop Maintenance +
+
+
+
+
+
+ )} + > + {({ openMenu }) => } +
+
+ +
{alertReceiveChannel.description_short && ( {alertReceiveChannel.description_short} @@ -208,45 +213,39 @@ class Integration2 extends React.Component )} {alertReceiveChannelCounter && ( - - {/* is needed to be child, otherwise Tooltip won't render */} - - - - - - + /> )} - + + {alertReceiveChannel.maintenance_till && ( + + )} + + {this.renderHearbeat(alertReceiveChannel)} + Type: @@ -276,6 +275,7 @@ class Integration2 extends React.Component expandedView: , }, { + isExpanded: false, isCollapsible: true, collapsedView: ( Templates + Grouping: - {IntegrationHelper.getFilteredTemplate(templates['grouping_id_template'] || '', false)} + {IntegrationHelper.truncateLine(templates['grouping_id_template'] || '')} + + + + + Autoresolve: + + {IntegrationHelper.truncateLine(templates['resolve_condition_template'] || '')} @@ -384,6 +392,7 @@ class Integration2 extends React.Component return channelFilterIds.map((channelFilterId: ChannelFilter['id'], routeIndex: number) => ({ isCollapsible: true, + isExpanded: false, collapsedView: ( })); }; + renderHearbeat = (alertReceiveChannel: AlertReceiveChannel) => { + const { heartbeatStore, alertReceiveChannelStore } = this.props.store; + + const heartbeatId = alertReceiveChannelStore.alertReceiveChannelToHeartbeat[alertReceiveChannel.id]; + const heartbeat = heartbeatStore.items[heartbeatId]; + + const heartbeatStatus = Boolean(heartbeat?.status); + + return ( + : } + tooltipTitle={`Last heartbeat: ${alertReceiveChannel.heartbeat?.last_heartbeat_time_verbal || 'never'}`} + tooltipContent={undefined} + /> + ); + }; + + getAlertReceiveChannelCounterTooltip = () => { + const { id } = this.props.match.params; + const { alertReceiveChannelStore } = this.props.store; + const alertReceiveChannelCounter = alertReceiveChannelStore.counters[id]; + + return ( + alertReceiveChannelCounter?.alerts_count + + ' alert' + + (alertReceiveChannelCounter?.alerts_count === 1 ? '' : 's') + + ' in ' + + alertReceiveChannelCounter?.alert_groups_count + + ' alert group' + + (alertReceiveChannelCounter?.alert_groups_count === 1 ? '' : 's') + ); + }; + handleSlackChannelChange = () => {}; onUpdateRoutesCallback = ({ routing }: { routing: string }) => { diff --git a/grafana-plugin/src/pages/integrations_2/Integrations2.tsx b/grafana-plugin/src/pages/integrations_2/Integrations2.tsx index 051e3458..9e1885cd 100644 --- a/grafana-plugin/src/pages/integrations_2/Integrations2.tsx +++ b/grafana-plugin/src/pages/integrations_2/Integrations2.tsx @@ -17,6 +17,7 @@ import { } from 'components/PageErrorHandlingWrapper/PageErrorHandlingWrapper.helpers'; import PluginLink from 'components/PluginLink/PluginLink'; import Text from 'components/Text/Text'; +import TooltipBadge from 'components/TooltipBadge/TooltipBadge'; import WithConfirm from 'components/WithConfirm/WithConfirm'; import IntegrationForm from 'containers/IntegrationForm/IntegrationForm'; import RemoteFilters from 'containers/RemoteFilters/RemoteFilters'; @@ -25,10 +26,11 @@ import { WithPermissionControlTooltip } from 'containers/WithPermissionControl/W import { HeartGreenIcon, HeartRedIcon } from 'icons'; import { AlertReceiveChannel, MaintenanceMode } from 'models/alert_receive_channel'; import { MaintenanceType } from 'models/maintenance/maintenance.types'; +import IntegrationHelper from 'pages/integration_2/Integration2.helper'; import { PageProps, WithStoreProps } from 'state/types'; import { withMobXProviderContext } from 'state/withStore'; import LocationHelper from 'utils/LocationHelper'; -import { UserActions, isUserActionAllowed } from 'utils/authorization'; +import { UserActions } from 'utils/authorization'; import styles from './Integrations2.module.scss'; @@ -109,7 +111,7 @@ class Integrations extends React.Component render() { const { store, query } = this.props; const { alertReceiveChannelId } = this.state; - const { grafanaTeamStore, alertReceiveChannelStore, heartbeatStore, maintenanceStore } = store; + const { grafanaTeamStore, alertReceiveChannelStore, heartbeatStore } = store; const results = alertReceiveChannelStore.getSearchResult(); @@ -137,7 +139,7 @@ class Integrations extends React.Component width: '10%', title: 'Maintenance', key: 'maintenance', - render: (item: AlertReceiveChannel) => this.renderMaintenance(item, maintenanceStore, alertReceiveChannelStore), + render: (item: AlertReceiveChannel) => this.renderMaintenance(item), }, { width: '5%', @@ -299,52 +301,23 @@ class Integrations extends React.Component ); } - convertTimestampToTimeDifference(timestamp: string) { - const date = new Date(Number(timestamp) * 1000); - const timezoneOffset = new Date().getTimezoneOffset() * 60; - const localTimestamp = date.getTime() + timezoneOffset; - const currentTime = Date.now(); - const difference = localTimestamp - currentTime; - - let timeLeft; - if (difference < 3600000) { - timeLeft = Math.floor(difference / 60000) + 'm left'; - } else { - timeLeft = Math.floor(difference / 3600000) + 'h left'; - } - - return timeLeft; - } - - renderMaintenance(item: AlertReceiveChannel, maintenanceStore, alertReceiveChannelStore) { + renderMaintenance(item: AlertReceiveChannel) { const maintenanceMode = item.maintenance_mode; - const maintenanceTill = item.maintenance_till; if (maintenanceMode === MaintenanceMode.Debug || maintenanceMode === MaintenanceMode.Maintenance) { return ( - - this.handleStopMaintenance(item, maintenanceStore, alertReceiveChannelStore)} - > - {this.convertTimestampToTimeDifference(maintenanceTill)} - - } - color={maintenanceMode === MaintenanceMode.Debug ? 'orange' : 'blue'} - tooltip={ - maintenanceMode === MaintenanceMode.Debug - ? `Debug Maintenance: ${this.convertTimestampToTimeDifference(maintenanceTill)} left` - : `Maintenance: ${this.convertTimestampToTimeDifference(maintenanceTill)} left` - } +
+ - +
); } + return null; } diff --git a/grafana-plugin/src/pages/schedules/Schedules.tsx b/grafana-plugin/src/pages/schedules/Schedules.tsx index d7168c79..bfc58420 100644 --- a/grafana-plugin/src/pages/schedules/Schedules.tsx +++ b/grafana-plugin/src/pages/schedules/Schedules.tsx @@ -8,7 +8,6 @@ import { observer } from 'mobx-react'; import { RouteComponentProps, withRouter } from 'react-router-dom'; import Avatar from 'components/Avatar/Avatar'; -import CounterBadge from 'components/CounterBadge/CounterBadge'; import { MatchMediaTooltip } from 'components/MatchMediaTooltip/MatchMediaTooltip'; import NewScheduleSelector from 'components/NewScheduleSelector/NewScheduleSelector'; import PluginLink from 'components/PluginLink/PluginLink'; @@ -16,6 +15,7 @@ import { SchedulesFiltersType } from 'components/SchedulesFilters/SchedulesFilte import Table from 'components/Table/Table'; import Text from 'components/Text/Text'; import TimelineMarks from 'components/TimelineMarks/TimelineMarks'; +import TooltipBadge from 'components/TooltipBadge/TooltipBadge'; import UserTimezoneSelect from 'components/UserTimezoneSelect/UserTimezoneSelect'; import WithConfirm from 'components/WithConfirm/WithConfirm'; import RemoteFilters from 'containers/RemoteFilters/RemoteFilters'; @@ -306,10 +306,10 @@ class SchedulesPage extends React.Component {item.number_of_escalation_chains > 0 && ( - @@ -335,10 +335,10 @@ class SchedulesPage extends React.Component 0 && ( - diff --git a/grafana-plugin/src/pages/users/Users.tsx b/grafana-plugin/src/pages/users/Users.tsx index a80b8f00..47528812 100644 --- a/grafana-plugin/src/pages/users/Users.tsx +++ b/grafana-plugin/src/pages/users/Users.tsx @@ -8,7 +8,6 @@ import LegacyNavHeading from 'navbar/LegacyNavHeading'; import { RouteComponentProps, withRouter } from 'react-router-dom'; import Avatar from 'components/Avatar/Avatar'; -import CounterBadge from 'components/CounterBadge/CounterBadge'; import GTable from 'components/GTable/GTable'; import PageErrorHandlingWrapper, { PageBaseState } from 'components/PageErrorHandlingWrapper/PageErrorHandlingWrapper'; import { @@ -17,6 +16,7 @@ import { } from 'components/PageErrorHandlingWrapper/PageErrorHandlingWrapper.helpers'; import PluginLink from 'components/PluginLink/PluginLink'; import Text from 'components/Text/Text'; +import TooltipBadge from 'components/TooltipBadge/TooltipBadge'; import UsersFilters from 'components/UsersFilters/UsersFilters'; import UserSettings from 'containers/UserSettings/UserSettings'; import { WithPermissionControlTooltip } from 'containers/WithPermissionControl/WithPermissionControlTooltip'; @@ -361,10 +361,10 @@ class Users extends React.Component { return ( - diff --git a/grafana-plugin/src/style/vars.css b/grafana-plugin/src/style/vars.css index 93660210..bb378bcf 100644 --- a/grafana-plugin/src/style/vars.css +++ b/grafana-plugin/src/style/vars.css @@ -23,6 +23,7 @@ --tag-secondary: #464c54; --tag-background-primary: rgba(56, 113, 220, 0.2); --tag-border-primary: rgba(56, 113, 220, 0.2); + --tag-background-danger: rgba(242, 73, 92, 0.15); --tag-text-primary: rgba(110, 159, 255, 1); --tag-border-danger: rgb(151, 11, 27); --tag-text-danger: rgb(247, 144, 156); @@ -30,6 +31,7 @@ --tag-background-warning: rgba(245, 183, 61, 0.18); --tag-text-warning: rgb(255, 190, 124); --tag-border-success: rgb(49, 100, 43); + --tag-border-link: rgba(56, 113, 220, 0.2); --tag-background-success: rgba(27, 133, 94, 0.15); --tag-text-success: rgb(165, 214, 159); }