Skip to content

Commit

Permalink
fix(api,dashboard): Invalid url error and in-app tabs spacing (#7167)
Browse files Browse the repository at this point in the history
  • Loading branch information
desiprisg authored Nov 29, 2024
1 parent 368050c commit 0b27448
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 116 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ export class PrepareAndValidateContentUsecase {
{
issueType: StepContentIssueEnum.INVALID_URL,
variableName: controlValue,
message: `Invalid URL: [[${controlValue}]]`,
message: 'Provide an absolute URL starting with https:// or a valid path starting with /',
},
];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { type ControlsMetadata } from '@novu/shared';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/primitives/collapsible';
import { JsonForm } from './json-form';
import { WorkflowOriginEnum } from '@/utils/enums';
import { InAppTabsSection } from '@/components/workflow-editor/steps/in-app/in-app-tabs-section';

export function CustomStepControls({
dataSchema,
Expand All @@ -20,29 +21,31 @@ export function CustomStepControls({
}

return (
<Collapsible
open={isEditorOpen}
onOpenChange={setIsEditorOpen}
className="bg-neutral-alpha-50 border-neutral-alpha-200 flex w-full flex-col gap-2 rounded-lg border p-2"
>
<CollapsibleTrigger className="flex w-full items-center justify-between text-sm">
<div className="flex items-center gap-1">
<RiInputField className="text-feature size-5" />
<span className="text-sm font-medium">Custom step controls</span>
</div>
<InAppTabsSection>
<Collapsible
open={isEditorOpen}
onOpenChange={setIsEditorOpen}
className="bg-neutral-alpha-50 border-neutral-alpha-200 flex w-full flex-col gap-2 rounded-lg border p-2"
>
<CollapsibleTrigger className="flex w-full items-center justify-between text-sm">
<div className="flex items-center gap-1">
<RiInputField className="text-feature size-5" />
<span className="text-sm font-medium">Custom step controls</span>
</div>

{isEditorOpen ? (
<RiArrowUpSLine className="text-neutral-alpha-400 size-5" />
) : (
<RiArrowDownSLine className="text-neutral-alpha-400 size-5" />
)}
</CollapsibleTrigger>
{isEditorOpen ? (
<RiArrowUpSLine className="text-neutral-alpha-400 size-5" />
) : (
<RiArrowDownSLine className="text-neutral-alpha-400 size-5" />
)}
</CollapsibleTrigger>

<CollapsibleContent>
<div className="bg-background rounded-md border border-dashed px-3 py-0">
<JsonForm schema={(dataSchema as RJSFSchema) || {}} variables={[]} />
</div>
</CollapsibleContent>
</Collapsible>
<CollapsibleContent>
<div className="bg-background rounded-md border border-dashed px-3 py-0">
<JsonForm schema={(dataSchema as RJSFSchema) || {}} variables={[]} />
</div>
</CollapsibleContent>
</Collapsible>
</InAppTabsSection>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
} from '@/components/workflow-editor/in-app-preview';
import { loadLanguage } from '@uiw/codemirror-extensions-langs';
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/primitives/accordion';
import { InAppTabsSection } from '@/components/workflow-editor/steps/in-app/in-app-tabs-section';

const getInitialAccordionValue = (value: string) => {
try {
Expand Down Expand Up @@ -59,84 +60,86 @@ export const InAppEditorPreview = (props: InAppEditorPreviewProps) => {
}, [value]);

return (
<div className="relative flex flex-col gap-3">
<div className="flex items-center gap-2.5 text-sm font-medium">
<Notification5Fill className="size-3" />
In-app template editor
</div>
<InAppTabsSection>
<div className="relative flex flex-col gap-3">
<div className="flex items-center gap-2.5 text-sm font-medium">
<Notification5Fill className="size-3" />
In-app template editor
</div>

<div className="relative my-2">
<div className="relative mx-auto max-w-sm">
<InAppPreviewBell />
<div className="relative my-2">
<div className="relative mx-auto max-w-sm">
<InAppPreviewBell />

<InAppPreview className="min-h-64">
<InAppPreviewHeader />
<InAppPreview className="min-h-64">
<InAppPreviewHeader />

<InAppPreviewNotification>
<InAppPreviewAvatar src={preview?.avatar} isPending={isPreviewPending} />
<InAppPreviewNotification>
<InAppPreviewAvatar src={preview?.avatar} isPending={isPreviewPending} />

<InAppPreviewNotificationContent>
<InAppPreviewSubject isPending={isPreviewPending}>{preview?.subject}</InAppPreviewSubject>
<InAppPreviewBody isPending={isPreviewPending} className="line-clamp-6">
{preview?.body}
</InAppPreviewBody>
<InAppPreviewNotificationContent>
<InAppPreviewSubject isPending={isPreviewPending}>{preview?.subject}</InAppPreviewSubject>
<InAppPreviewBody isPending={isPreviewPending} className="line-clamp-6">
{preview?.body}
</InAppPreviewBody>

<InAppPreviewActions>
<InAppPreviewPrimaryAction isPending={isPreviewPending}>
{preview?.primaryAction?.label}
</InAppPreviewPrimaryAction>
<InAppPreviewActions>
<InAppPreviewPrimaryAction isPending={isPreviewPending}>
{preview?.primaryAction?.label}
</InAppPreviewPrimaryAction>

<InAppPreviewSecondaryAction isPending={isPreviewPending}>
{preview?.secondaryAction?.label}
</InAppPreviewSecondaryAction>
</InAppPreviewActions>
</InAppPreviewNotificationContent>
</InAppPreviewNotification>
</InAppPreview>
<InAppPreviewSecondaryAction isPending={isPreviewPending}>
{preview?.secondaryAction?.label}
</InAppPreviewSecondaryAction>
</InAppPreviewActions>
</InAppPreviewNotificationContent>
</InAppPreviewNotification>
</InAppPreview>
</div>
<div className="to-background absolute -bottom-3 h-16 w-full bg-gradient-to-b from-transparent to-80%" />
</div>
<div className="to-background absolute -bottom-3 h-16 w-full bg-gradient-to-b from-transparent to-80%" />
</div>

<Accordion type="single" collapsible value={accordionValue} onValueChange={setAccordionValue}>
<AccordionItem value="payload">
<AccordionTrigger>
<div className="flex items-center gap-1">
<Code2 className="size-5" />
Configure preview
</div>
</AccordionTrigger>
<AccordionContent
ref={contentRef}
className="flex flex-col gap-2"
style={{ '--radix-collapsible-content-height': `${height}px` } as CSSProperties}
>
<Editor
value={value}
onChange={onChange}
lang="json"
extensions={[loadLanguage('json')?.extension ?? []]}
className="border-neutral-alpha-200 bg-background text-foreground-600 mx-0 mt-0 rounded-lg border border-dashed p-3"
/>
{payloadError && <p className="text-destructive text-xs">{payloadError}</p>}
<Button
size="xs"
type="button"
variant="outline"
className="self-end"
onClick={() => {
try {
applyPreview();
setPayloadError('');
} catch (e) {
setPayloadError(String(e));
}
}}
<Accordion type="single" collapsible value={accordionValue} onValueChange={setAccordionValue}>
<AccordionItem value="payload">
<AccordionTrigger>
<div className="flex items-center gap-1">
<Code2 className="size-5" />
Configure preview
</div>
</AccordionTrigger>
<AccordionContent
ref={contentRef}
className="flex flex-col gap-2"
style={{ '--radix-collapsible-content-height': `${height}px` } as CSSProperties}
>
Apply
</Button>
</AccordionContent>
</AccordionItem>
</Accordion>
</div>
<Editor
value={value}
onChange={onChange}
lang="json"
extensions={[loadLanguage('json')?.extension ?? []]}
className="border-neutral-alpha-200 bg-background text-foreground-600 mx-0 mt-0 rounded-lg border border-dashed p-3"
/>
{payloadError && <p className="text-destructive text-xs">{payloadError}</p>}
<Button
size="xs"
type="button"
variant="outline"
className="self-end"
onClick={() => {
try {
applyPreview();
setPayloadError('');
} catch (e) {
setPayloadError(String(e));
}
}}
>
Apply
</Button>
</AccordionContent>
</AccordionItem>
</Accordion>
</div>
</InAppTabsSection>
);
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { UiSchemaGroupEnum, type UiSchema } from '@novu/shared';

import { Notification5Fill } from '@/components/icons';
import { Separator } from '@/components/primitives/separator';
import { getComponentByType } from '@/components/workflow-editor/steps/component-utils';
import { InAppTabsSection } from '@/components/workflow-editor/steps/in-app/in-app-tabs-section';

const avatarKey = 'avatar';
const subjectKey = 'subject';
Expand All @@ -25,28 +27,37 @@ export const InAppEditor = ({ uiSchema }: { uiSchema?: UiSchema }) => {
} = uiSchema.properties ?? {};

return (
<div className="flex flex-col gap-3">
<div className="flex items-center gap-2.5 text-sm font-medium">
<Notification5Fill className="size-3" />
<span>In-app template editor</span>
</div>
<div className="flex flex-col gap-1 rounded-xl border border-neutral-100 p-1">
{(avatar || subject) && (
<div className="flex gap-1">
{avatar && getComponentByType({ component: avatar.component })}
{subject && getComponentByType({ component: subject.component })}
</div>
)}
{body && getComponentByType({ component: body.component })}
{(primaryAction || secondaryAction) &&
getComponentByType({
component: primaryAction.component || secondaryAction.component,
})}
</div>
{redirect &&
getComponentByType({
component: redirect.component,
})}
<div className="flex flex-col">
<InAppTabsSection className="flex flex-col gap-3">
<div className={'flex items-center gap-2.5 text-sm font-medium'}>
<Notification5Fill className="size-3" />
<span>In-app template editor</span>
</div>
<div className="flex flex-col gap-1 rounded-xl border border-neutral-100 p-1">
{(avatar || subject) && (
<div className="flex gap-1">
{avatar && getComponentByType({ component: avatar.component })}
{subject && getComponentByType({ component: subject.component })}
</div>
)}
{body && getComponentByType({ component: body.component })}
{(primaryAction || secondaryAction) &&
getComponentByType({
component: primaryAction.component || secondaryAction.component,
})}
</div>
</InAppTabsSection>

{redirect && (
<>
<Separator className="bg-neutral-100" />
<InAppTabsSection>
{getComponentByType({
component: redirect.component,
})}
</InAppTabsSection>
</>
)}
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { cn } from '@/utils/ui';
import { HTMLAttributes } from 'react';

type InAppTabsSectionProps = HTMLAttributes<HTMLDivElement>;
export const InAppTabsSection = (props: InAppTabsSectionProps) => {
const { className, ...rest } = props;
return <div className={cn('px-3 py-5', className)} {...rest} />;
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { CustomStepControls } from '../controls/custom-step-controls';
import { ConfigureStepTemplateFormProps } from '@/components/workflow-editor/steps/configure-step-template-form';
import { useDebouncedPreview } from '../use-debounced-preview';

const tabsContentClassName = 'h-full w-full px-3 py-3.5 overflow-y-auto';
const tabsContentClassName = 'h-full w-full overflow-y-auto';

export const InAppTabs = (props: ConfigureStepTemplateFormProps) => {
const { workflow, step } = props;
Expand Down

0 comments on commit 0b27448

Please sign in to comment.