add tabs for snow integration (#3726)
# What this PR does add incoming / outgoing tabs when integration is service now ## Which issue(s) this PR fixes https://github.com/grafana/oncall-private/issues/2460 ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not required)
This commit is contained in:
parent
32b11196c8
commit
fdbccdac99
3 changed files with 90 additions and 25 deletions
47
grafana-plugin/src/components/Tabs/Tabs.tsx
Normal file
47
grafana-plugin/src/components/Tabs/Tabs.tsx
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import React, { FC, useState } from 'react';
|
||||
|
||||
import { css } from '@emotion/css';
|
||||
import { Tab, TabsBar, TabContent, useStyles2 } from '@grafana/ui';
|
||||
import cn from 'classnames';
|
||||
|
||||
interface TabConfig {
|
||||
label: string;
|
||||
content: React.ReactNode;
|
||||
}
|
||||
|
||||
interface TabsProps {
|
||||
tabs: TabConfig[];
|
||||
defaultActiveLabel?: string;
|
||||
tabContentClassName?: string;
|
||||
}
|
||||
|
||||
const Tabs: FC<TabsProps> = ({ tabs, defaultActiveLabel, tabContentClassName }) => {
|
||||
const styles = useStyles2(getStyles);
|
||||
const [activeTabLabel, setActiveTabLabel] = useState(defaultActiveLabel || tabs[0].label);
|
||||
|
||||
return (
|
||||
<>
|
||||
<TabsBar>
|
||||
{tabs.map(({ label }) => (
|
||||
<Tab
|
||||
label={label}
|
||||
key={label}
|
||||
onChangeTab={() => setActiveTabLabel(label)}
|
||||
active={activeTabLabel === label}
|
||||
/>
|
||||
))}
|
||||
</TabsBar>
|
||||
<TabContent className={cn(styles.content, tabContentClassName)}>
|
||||
{tabs.find(({ label }) => label === activeTabLabel)?.content}
|
||||
</TabContent>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const getStyles = () => ({
|
||||
content: css({
|
||||
marginTop: '16px',
|
||||
}),
|
||||
});
|
||||
|
||||
export default Tabs;
|
||||
|
|
@ -125,3 +125,5 @@ const IntegrationHelper = {
|
|||
};
|
||||
|
||||
export default IntegrationHelper;
|
||||
|
||||
export const getIsBidirectionalIntegration = ({ integration }: AlertReceiveChannel) => integration === 'servicenow';
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import PageErrorHandlingWrapper, { PageBaseState } from 'components/PageErrorHan
|
|||
import { initErrorDataState } from 'components/PageErrorHandlingWrapper/PageErrorHandlingWrapper.helpers';
|
||||
import PluginLink from 'components/PluginLink/PluginLink';
|
||||
import RenderConditionally from 'components/RenderConditionally/RenderConditionally';
|
||||
import Tabs from 'components/Tabs/Tabs';
|
||||
import Tag from 'components/Tag/Tag';
|
||||
import Text from 'components/Text/Text';
|
||||
import TooltipBadge from 'components/TooltipBadge/TooltipBadge';
|
||||
|
|
@ -57,7 +58,7 @@ import {
|
|||
} from 'models/alert_receive_channel/alert_receive_channel.types';
|
||||
import { AlertTemplatesDTO } from 'models/alert_templates/alert_templates';
|
||||
import { ChannelFilter } from 'models/channel_filter/channel_filter.types';
|
||||
import IntegrationHelper from 'pages/integration/Integration.helper';
|
||||
import IntegrationHelper, { getIsBidirectionalIntegration } from 'pages/integration/Integration.helper';
|
||||
import styles from 'pages/integration/Integration.module.scss';
|
||||
import { AppFeature } from 'state/features';
|
||||
import { PageProps, SelectOption, WithStoreProps } from 'state/types';
|
||||
|
|
@ -155,6 +156,36 @@ class Integration extends React.Component<IntegrationProps, IntegrationState> {
|
|||
const isLegacyIntegration = integration && (integration?.value as string).toLowerCase().startsWith('legacy_');
|
||||
const contactPoints = alertReceiveChannelStore.connectedContactPoints?.[alertReceiveChannel.id];
|
||||
|
||||
const incomingPart = (
|
||||
<>
|
||||
<IntegrationCollapsibleTreeView configElements={this.getConfigForTreeComponent(id, templates) as any} />
|
||||
{isEditTemplateModalOpen && (
|
||||
<IntegrationTemplate
|
||||
id={id}
|
||||
onHide={() => {
|
||||
this.setState({
|
||||
isEditTemplateModalOpen: undefined,
|
||||
});
|
||||
if (selectedTemplate?.name !== 'route_template') {
|
||||
this.setState({ isTemplateSettingsOpen: true });
|
||||
}
|
||||
LocationHelper.update({ template: undefined, routeId: undefined }, 'partial');
|
||||
}}
|
||||
channelFilterId={channelFilterIdForEdit}
|
||||
onUpdateTemplates={this.onUpdateTemplatesCallback}
|
||||
onUpdateRoute={this.onUpdateRoutesCallback}
|
||||
template={selectedTemplate}
|
||||
templateBody={
|
||||
selectedTemplate?.name === 'route_template'
|
||||
? this.getRoutingTemplate(channelFilterIdForEdit)
|
||||
: templates[selectedTemplate?.name]
|
||||
}
|
||||
templates={templates}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<PageErrorHandlingWrapper errorData={errorData} objectName="integration" pageName="Integration">
|
||||
{() => (
|
||||
|
|
@ -223,32 +254,17 @@ class Integration extends React.Component<IntegrationProps, IntegrationState> {
|
|||
)}
|
||||
</div>
|
||||
|
||||
<IntegrationCollapsibleTreeView configElements={this.getConfigForTreeComponent(id, templates) as any} />
|
||||
|
||||
{isEditTemplateModalOpen && (
|
||||
<IntegrationTemplate
|
||||
id={id}
|
||||
onHide={() => {
|
||||
this.setState({
|
||||
isEditTemplateModalOpen: undefined,
|
||||
});
|
||||
if (selectedTemplate?.name !== 'route_template') {
|
||||
this.setState({ isTemplateSettingsOpen: true });
|
||||
}
|
||||
LocationHelper.update({ template: undefined, routeId: undefined }, 'partial');
|
||||
}}
|
||||
channelFilterId={channelFilterIdForEdit}
|
||||
onUpdateTemplates={this.onUpdateTemplatesCallback}
|
||||
onUpdateRoute={this.onUpdateRoutesCallback}
|
||||
template={selectedTemplate}
|
||||
templateBody={
|
||||
selectedTemplate?.name === 'route_template'
|
||||
? this.getRoutingTemplate(channelFilterIdForEdit)
|
||||
: templates[selectedTemplate?.name]
|
||||
}
|
||||
templates={templates}
|
||||
{getIsBidirectionalIntegration(alertReceiveChannel) ? (
|
||||
<Tabs
|
||||
tabs={[
|
||||
{ label: 'Incoming', content: incomingPart },
|
||||
{ label: 'Outgoing', content: <div>outgoing tab content</div> },
|
||||
]}
|
||||
/>
|
||||
) : (
|
||||
<>{incomingPart}</>
|
||||
)}
|
||||
|
||||
{isEditRegexpRouteTemplateModalOpen && (
|
||||
<EditRegexpRouteTemplateModal
|
||||
alertReceiveChannelId={id}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue