Skip to content

Commit

Permalink
Merge pull request #5300 from novuhq/nv-3283-providers-warning-cut-off
Browse files Browse the repository at this point in the history
fix(web): workflow settings - providers warnings were cut off
  • Loading branch information
LetItRock authored Mar 14, 2024
2 parents 1e0bbac + 7196f3d commit 405b147
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 148 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ const STATUS_TO_ICON = {
Disabled: 'bolt',
};

export const IntegrationStatus = ({ active }: { active: boolean }) => {
export const IntegrationStatus = ({ active, className }: { active: boolean; className?: string }) => {
const status = active ? 'Active' : 'Disabled';

return (
<StatusHolder data-disabled={status === 'Disabled'} data-test-id="integration-status-cell">
<StatusHolder className={className} data-disabled={status === 'Disabled'} data-test-id="integration-status-cell">
<StatusIcon icon={STATUS_TO_ICON[status] as any} />
<StatusName>{status}</StatusName>
</StatusHolder>
Expand Down
261 changes: 120 additions & 141 deletions apps/web/src/pages/templates/components/ListProviders.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { MouseEventHandler, useMemo } from 'react';
import styled from '@emotion/styled';
import { Group, Stack, Text, UnstyledButton, useMantineColorScheme } from '@mantine/core';
import { ChannelTypeEnum, NOVU_SMS_EMAIL_PROVIDERS } from '@novu/shared';
import { Button, colors, Tooltip } from '@novu/design-system';

import { When } from '../../../components/utils/When';
import { Button, colors, Tooltip } from '@novu/design-system';
import { useEnvController } from '../../../hooks';
import { IntegrationEnvironmentPill } from '../../integrations/components/IntegrationEnvironmentPill';
import { IntegrationStatus } from '../../integrations/components/IntegrationStatus';
Expand All @@ -11,165 +13,142 @@ import { stepNames } from '../constants';
import { ChannelTitle } from './ChannelTitle';
import { LackIntegrationAlert } from './LackIntegrationAlert';

const getIntegrationIcon = (colorScheme: string, providerId: string) => {
return '/static/images/providers/' + colorScheme + '/square/' + providerId + '.svg';
};

const ListProvidersContainer = styled.div`
margin-bottom: 2rem;
overflow: hidden;
`;

const TitleAndButtonContainer = styled.div`
display: flex;
justify-content: space-between;
color: ${colors.B60};
margin-bottom: 0.75rem;
font-size: 0.875rem;
line-height: 1.25rem;
`;

const ConfigureButton = styled(Button)`
height: 2rem;
padding: 0.5rem 1rem;
`;

const IntegrationButton = styled(UnstyledButton)<
{ isActive: boolean; isDark: boolean } & { onClick?: MouseEventHandler<HTMLButtonElement> }
>`
width: 100%;
padding: 0.5rem 0.75rem;
background: ${({ isDark }) => (isDark ? colors.B20 : colors.B98)};
border-radius: 0.5rem;
margin-bottom: 0.75rem;
line-height: 1;
opacity: ${({ isActive, isDark }) => (isActive || isDark ? 1 : 0.4)};
`;

const IntegrationIcon = styled.img<{ isActive: boolean; isDark: boolean }>`
height: 1.5rem;
max-width: 8.75rem;
opacity: ${({ isActive, isDark }) => (isActive || isDark ? 1 : 0.4)};
`;

const IntegrationStatusStyled = styled(IntegrationStatus)`
min-width: 5rem;
`;

export const ListProviders = ({
channel,
providers,
channelProviders,
setConfigureChannel,
setProvider,
}: {
channel: ChannelTypeEnum;
providers: IIntegratedProvider[];
channelProviders: IIntegratedProvider[];
setConfigureChannel: (channel: ChannelTypeEnum) => void;
setProvider: (provider: IIntegratedProvider) => void;
}) => {
const { colorScheme } = useMantineColorScheme();
const { environment: currentEnvironment } = useEnvController();
const containsNovuProvider = useMemo(
() =>
NOVU_SMS_EMAIL_PROVIDERS.some(
(providerId) => providerId === channelProviders.find((provider) => provider.connected)?.providerId
),
[channelProviders]
);
const providersForTheCurrentEnvironment = useMemo(
() =>
channelProviders.filter((provider) => provider.connected && provider.environmentId === currentEnvironment?._id),
[channelProviders, currentEnvironment?._id]
);
const hasProviders = providersForTheCurrentEnvironment.length > 0;
const hasNovuProvider = providersForTheCurrentEnvironment.length === 1 && containsNovuProvider;
const isDark = colorScheme === 'dark';

return (
<div
style={{
marginBottom: 32,
overflow: 'hidden',
}}
>
<div
style={{
color: colors.B60,
marginBottom: 12,
fontSize: 14,
lineHeight: '20px',
}}
>
<Group position="apart">
<ChannelTitle spacing={8} channel={channel} />
<Button
sx={{
height: '32px',
padding: '7.5px 15px',
}}
variant={providers.filter((provider) => provider.connected).length > 0 ? 'outline' : 'gradient'}
<ListProvidersContainer>
<TitleAndButtonContainer>
<ChannelTitle spacing={8} channel={channel} />
<ConfigureButton
variant={hasProviders ? 'outline' : 'gradient'}
onClick={() => {
setConfigureChannel(channel);
}}
>
Configure
</ConfigureButton>
</TitleAndButtonContainer>
{providersForTheCurrentEnvironment.map((provider) => {
return (
<IntegrationButton
key={provider.identifier ?? provider.providerId}
isDark={isDark}
isActive={provider.active}
onClick={() => {
setConfigureChannel(channel);
setProvider(provider);
setConfigureChannel(provider.channel);
}}
>
Configure
</Button>
</Group>
</div>
{providers
.filter((provider) => provider.connected && provider.environmentId === currentEnvironment?._id)
.map((provider) => {
return (
<UnstyledButton
key={provider.identifier ?? provider.providerId}
style={{
width: '100%',
padding: '8px 12px',
background: colorScheme === 'dark' ? colors.B20 : colors.B98,
borderRadius: 8,
marginBottom: 12,
lineHeight: 1,
opacity: provider.active ? 1 : colorScheme === 'dark' ? 1 : 0.4,
}}
onClick={() => {
setProvider(provider);
setConfigureChannel(provider.channel);
}}
>
<Group spacing={16} position="apart">
<Group spacing={16} position="apart">
<Group spacing={16} position="apart">
<img
src={'/static/images/providers/' + colorScheme + '/square/' + provider.providerId + '.svg'}
alt={provider.displayName}
style={{
height: '24px',
maxWidth: '140px',
opacity: provider.active ? 1 : colorScheme === 'dark' ? 0.4 : 1,
}}
/>

<Stack
sx={{
width: '117px',
}}
spacing={0}
>
<Tooltip label={provider.displayName}>
<Text size="md" truncate="end">
{provider.name || provider.displayName}
</Text>
</Tooltip>
<When truthy={provider.identifier !== undefined}>
<Text
sx={{
color: colors.B40,
}}
size="sm"
>
Key: {provider.identifier}
</Text>
</When>
</Stack>
</Group>
<Group spacing={16} position="apart">
<IntegrationEnvironmentPill name={currentEnvironment?.name || 'Development'} />
<div
style={{
minWidth: 76,
}}
>
<IntegrationStatus active={provider.active} />
</div>
</Group>
<IntegrationIcon
src={getIntegrationIcon(colorScheme, provider.providerId)}
alt={provider.displayName}
isDark={isDark}
isActive={provider.active}
/>
<Stack w="15rem" spacing={0}>
<Tooltip label={provider.displayName}>
<Text size="md" truncate="end">
{provider.name || provider.displayName}
</Text>
</Tooltip>
<When truthy={provider.identifier}>
<Text color={colors.B40} size="sm">
Key: {provider.identifier}
</Text>
</When>
</Stack>
</Group>
</UnstyledButton>
);
})}
<LackIntegrationByType providers={providers} channel={channel} />
</div>
);
};

const LackIntegrationByType = ({
providers,
channel,
}: {
providers: IIntegratedProvider[];
channel: ChannelTypeEnum;
}) => {
const { environment: currentEnvironment } = useEnvController();
const containsNovuProvider = NOVU_SMS_EMAIL_PROVIDERS.some(
(providerId) => providerId === providers.find((provider) => provider.connected)?.providerId
);

return (
<>
<When truthy={providers.filter((provider) => provider.connected).length === 0}>
<div
style={{
marginBottom: -28,
}}
>
<LackIntegrationAlert
text={`Please configure ${stepNames[channel]} provider to activate the channel`}
channelType={channel}
/>
</div>
<Group spacing={16} position="apart">
<IntegrationEnvironmentPill name={currentEnvironment?.name || 'Development'} />
<IntegrationStatusStyled active={provider.active} />
</Group>
</Group>
</IntegrationButton>
);
})}
<When truthy={!hasProviders}>
<LackIntegrationAlert
text={`Please configure ${stepNames[channel]} provider to activate the channel`}
channelType={channel}
/>
</When>
<When
truthy={
providers.filter((provider) => provider.connected && provider.environmentId === currentEnvironment?._id)
.length === 1 && containsNovuProvider
}
>
<div
style={{
marginBottom: -28,
}}
>
<LackIntegrationAlert text={'Connect a provider for this channel'} channelType={channel} type={'warning'} />
</div>
<When truthy={hasNovuProvider}>
<LackIntegrationAlert text={'Connect a provider for this channel'} channelType={channel} type={'warning'} />
</When>
</>
</ListProvidersContainer>
);
};
10 changes: 5 additions & 5 deletions apps/web/src/pages/templates/components/ProvidersPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,31 +37,31 @@ export function ProvidersPage() {
channel={ChannelTypeEnum.IN_APP}
setProvider={setProvider}
setConfigureChannel={setConfigureChannel}
providers={inAppProvider}
channelProviders={inAppProvider}
/>
<ListProviders
channel={ChannelTypeEnum.EMAIL}
setProvider={setProvider}
setConfigureChannel={setConfigureChannel}
providers={emailProviders}
channelProviders={emailProviders}
/>
<ListProviders
channel={ChannelTypeEnum.CHAT}
setProvider={setProvider}
setConfigureChannel={setConfigureChannel}
providers={chatProvider}
channelProviders={chatProvider}
/>
<ListProviders
channel={ChannelTypeEnum.PUSH}
setProvider={setProvider}
setConfigureChannel={setConfigureChannel}
providers={pushProvider}
channelProviders={pushProvider}
/>
<ListProviders
channel={ChannelTypeEnum.SMS}
setProvider={setProvider}
setConfigureChannel={setConfigureChannel}
providers={smsProvider}
channelProviders={smsProvider}
/>
</ScrollArea>
</WorkflowSidebar>
Expand Down

0 comments on commit 405b147

Please sign in to comment.