Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import {
UnionIcon,
} from '../../icons';
import { WarningPopup } from '../../UI/WarningPopup';
import { ETemplateParts, ITemplateListItem } from '../../../types/template';
import { ETemplateParts } from '../../../types/template';
import { history } from '../../../utils/history';
import { sanitizeText } from '../../../utils/strings';
import { TCloneTemplatePayload, TDeleteTemplatePayload } from '../../../redux/actions';
import { ITemplateCardProps } from './types';
import { Dropdown, TDropdownOption } from '../../UI';
import { getTemplateEditRoute } from '../../../utils/routes';
import { getLinkToHighlightsByTemplate } from '../../../utils/routes/getLinkToHighlightsByTemplate';
Expand All @@ -27,22 +27,10 @@ import { getLinkToTemplate } from '../../../utils/routes/getLinkToTemplate';

import styles from '../Templates.css';

export interface ITemplateCardProps extends ITemplateListItem {
canEdit: boolean | undefined;
onRunWorkflow(): void;
cloneTemplate(payload: TCloneTemplatePayload): void;
deleteTemplate(payload: TDeleteTemplatePayload): void;
}

export interface ITemplateCardState {
isModalVisible: boolean;
}

export function TemplateCard({
canEdit,
id,
isActive,
isPublic,
name,
tasksCount,
deleteTemplate,
Expand Down Expand Up @@ -165,7 +153,6 @@ export function TemplateCard({
<TemplateCardFooter
templateId={id}
isActive={isActive}
isPublic={isPublic}
tasksCount={tasksCount}
onRunWorkflow={onRunWorkflow}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,27 @@ import { IntlMessages } from '../../IntlMessages';
import { getPluralNoun } from '../../../utils/helpers';
import { PlayLogoIcon, WarningIcon } from '../../icons';
import { Button, Tooltip } from '../../UI';
import { EIntegrations } from '../../../types/integrations';
import { TemplateIntegrationsIndicator, useTemplateIntegrationsList } from '../../TemplateIntegrationsStats';

import { checkShowDraftTemplateWarning } from '../utils/checkShowDraftTemplateWarning';
import {
hasTemplateCardIntegrations,
TEMPLATE_CARD_INTEGRATIONS_EXCLUDE,
} from '../utils/templateIntegrations';

import styles from '../Templates.css';

export interface ITemplateCardFooterProps {
templateId: number;
tasksCount: number;
isActive: boolean;
isPublic: boolean;
onRunWorkflow(): void;
}
import { ITemplateCardFooterProps } from './types';

export function TemplateCardFooter({
templateId,
tasksCount,
isActive,
isPublic,
onRunWorkflow,
}: ITemplateCardFooterProps) {
const { formatMessage } = useIntl();
const templateIntegrations = useTemplateIntegrationsList(templateId);
const showDraftWarning = checkShowDraftTemplateWarning(isActive, isPublic, templateIntegrations);
const hasIntegrations = hasTemplateCardIntegrations(templateIntegrations);
const showIntegrationsIndicator = isActive || hasIntegrations;
const showDraftWarning = !isActive && hasIntegrations;

const renderRunWorkflowButton = () => {
return (
Expand Down Expand Up @@ -95,20 +91,22 @@ export function TemplateCardFooter({
return (
<div className={styles['card__footer']}>
<div className={styles['card-footer__left']}>
<TemplateIntegrationsIndicator
templateId={templateId}
exlcude={[EIntegrations.Webhooks]}
integratedIndicator={(
<div className={classnames(styles['card-integration'], styles['card-integration_integrated'])}>
{formatMessage({ id: 'templates.template-integrated' })}
</div>
)}
disconnectedIndicator={(
<div className={classnames(styles['card-integration'], styles['card-integration_not-integrated'])}>
{formatMessage({ id: 'templates.template-not-integrated' })}
</div>
)}
/>
{showIntegrationsIndicator && (
<TemplateIntegrationsIndicator
templateId={templateId}
exlcude={TEMPLATE_CARD_INTEGRATIONS_EXCLUDE}
integratedIndicator={(
<div className={classnames(styles['card-integration'], styles['card-integration_integrated'])}>
{formatMessage({ id: 'templates.template-integrated' })}
</div>
)}
disconnectedIndicator={(
<div className={classnames(styles['card-integration'], styles['card-integration_not-integrated'])}>
{formatMessage({ id: 'templates.template-not-integrated' })}
</div>
)}
/>
)}

{renderCardStats()}
</div>
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/public/components/Templates/TemplatesUser/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
import { ITemplatesList } from '../../../types/redux';
import { ITemplateListItem } from '../../../types/template';
import { TCloneTemplatePayload, TDeleteTemplatePayload } from '../../../redux/actions';

export interface ITemplateCardProps extends ITemplateListItem {
canEdit: boolean | undefined;
onRunWorkflow(): void;
cloneTemplate(payload: TCloneTemplatePayload): void;
deleteTemplate(payload: TDeleteTemplatePayload): void;
}

export interface ITemplateCardFooterProps {
templateId: number;
tasksCount: number;
isActive: boolean;
onRunWorkflow(): void;
}

export interface ITemplatesUserProps {
templatesList: ITemplatesList;
loading?: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { EIntegrations } from '../../../../types/integrations';

import { checkShowDraftTemplateWarning } from '../checkShowDraftTemplateWarning';
import { hasTemplateCardIntegrations } from '../templateIntegrations';

describe('hasTemplateCardIntegrations', () => {
it('returns false when template has no integrations', () => {
expect(hasTemplateCardIntegrations([])).toBe(false);
});

it('returns false when template has only account-wide webhooks', () => {
expect(hasTemplateCardIntegrations([EIntegrations.Webhooks])).toBe(false);
});

it('returns true when template has connected integrations', () => {
expect(hasTemplateCardIntegrations([EIntegrations.API])).toBe(true);
});
});

describe('checkShowDraftTemplateWarning', () => {
it('returns false for active template', () => {
expect(checkShowDraftTemplateWarning(true, true, [EIntegrations.API])).toBe(false);
});

it('returns false for inactive template without integrations', () => {
expect(checkShowDraftTemplateWarning(false, false, [])).toBe(false);
});

it('returns true for inactive public template', () => {
expect(checkShowDraftTemplateWarning(false, true, [])).toBe(true);
});

it('returns true for inactive template with integrations', () => {
expect(checkShowDraftTemplateWarning(false, false, [EIntegrations.Zapier])).toBe(true);
});

it('returns true for inactive template with only webhooks', () => {
expect(checkShowDraftTemplateWarning(false, false, [EIntegrations.Webhooks])).toBe(true);
});
Comment thread
cursor[bot] marked this conversation as resolved.
});
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { EIntegrations } from "../../../types/integrations";
import { isArrayWithItems } from "../../../utils/helpers";
import { EIntegrations } from '../../../types/integrations';
import { isArrayWithItems } from '../../../utils/helpers';

export function checkShowDraftTemplateWarning(
isTemplateActive: boolean,
isTemplatePublic: boolean,
templateIntegrations: EIntegrations[]
templateIntegrations: EIntegrations[],
) {
return !isTemplateActive && (isArrayWithItems(templateIntegrations) || isTemplatePublic);
return !isTemplateActive && (isTemplatePublic || isArrayWithItems(templateIntegrations));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { EIntegrations } from '../../../types/integrations';

// Webhooks are account-wide, so they do not affect a template card's state.
export const TEMPLATE_CARD_INTEGRATIONS_EXCLUDE = [EIntegrations.Webhooks];

export function hasTemplateCardIntegrations(templateIntegrations: EIntegrations[]) {
return templateIntegrations.some(
integration => !TEMPLATE_CARD_INTEGRATIONS_EXCLUDE.includes(integration),
);
}