Skip to content
Merged
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 @@ -3,7 +3,7 @@ import { ActionWithRulesAndAddersProps } from 'react-querybuilder';

import { Button } from '@/components/primitives/button';

export const AddConditionAction = ({ label, title, rules, handleOnClick }: ActionWithRulesAndAddersProps) => {
export const AddConditionAction = ({ label, title, rules, handleOnClick, context }: ActionWithRulesAndAddersProps) => {
if (rules && rules.length >= 10) {
return null;
}
Expand All @@ -14,7 +14,10 @@ export const AddConditionAction = ({ label, title, rules, handleOnClick }: Actio
variant="secondary"
size="2xs"
className="bg-transparent"
onClick={handleOnClick}
onClick={(e) => {
handleOnClick(e);
context?.saveForm();
}}
leadingIcon={RiAddFill}
title={title}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ import { ActionWithRulesAndAddersProps } from 'react-querybuilder';
import { StackedPlusLine } from '@/components/icons/stacked-plus-line';
import { Button } from '@/components/primitives/button';

export const AddGroupAction = ({ label, title, level, rules, handleOnClick }: ActionWithRulesAndAddersProps) => {
export const AddGroupAction = ({
label,
title,
level,
rules,
handleOnClick,
context,
}: ActionWithRulesAndAddersProps) => {
if (level === 1 || (rules && rules.length >= 10)) {
return null;
}
Expand All @@ -14,7 +21,10 @@ export const AddGroupAction = ({ label, title, level, rules, handleOnClick }: Ac
variant="secondary"
size="2xs"
className="bg-transparent"
onClick={handleOnClick}
onClick={(e) => {
handleOnClick(e);
context?.saveForm();
}}
leadingIcon={StackedPlusLine}
title={title}
>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import { type CombinatorSelectorProps } from 'react-querybuilder';

import { toSelectOptions } from '@/components/conditions-editor/select-option-utils';
import { Select, SelectContent, SelectTrigger, SelectValue } from '@/components/primitives/select';
import { cn } from '@/utils/ui';
import { toSelectOptions } from '@/components/conditions-editor/select-option-utils';

export const CombinatorSelector = ({ disabled, value, options, handleOnChange }: CombinatorSelectorProps) => {
export const CombinatorSelector = ({ disabled, value, options, handleOnChange, context }: CombinatorSelectorProps) => {
return (
<Select onValueChange={handleOnChange} disabled={disabled} value={value}>
<Select
onValueChange={(e) => {
handleOnChange(e);
context?.saveForm();
}}
disabled={disabled}
value={value}
>
<SelectTrigger size="2xs" className={cn('w-18 hover:bg-bg-weak hover:text-text-strong text-label-xs gap-1')}>
<SelectValue />
</SelectTrigger>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,16 @@ function InternalConditionsEditor({
isAllowedVariable,
query,
onQueryChange,
saveForm,
}: {
fields: Field[];
variables: LiquidVariable[];
isAllowedVariable: IsAllowedVariable;
query: RuleGroupType;
onQueryChange: (query: RuleGroupType) => void;
saveForm: () => void;
}) {
const context = useMemo(() => ({ variables, isAllowedVariable }), [variables, isAllowedVariable]);
const context = useMemo(() => ({ variables, isAllowedVariable, saveForm }), [variables, isAllowedVariable, saveForm]);

return (
<QueryBuilder
Expand All @@ -79,16 +81,24 @@ function InternalConditionsEditor({
);
}

export type ConditionsEditorContext = {
variables: LiquidVariable[];
isAllowedVariable: IsAllowedVariable;
saveForm: () => void;
};

export function ConditionsEditor({
query,
onQueryChange,
fields,
saveForm,
variables,
isAllowedVariable,
}: {
query: RuleGroupType;
onQueryChange: (query: RuleGroupType) => void;
fields: Field[];
saveForm: () => void;
variables: LiquidVariable[];
isAllowedVariable: IsAllowedVariable;
}) {
Expand All @@ -100,6 +110,7 @@ export function ConditionsEditor({
isAllowedVariable={isAllowedVariable}
query={query}
onQueryChange={onQueryChange}
saveForm={saveForm}
/>
</ConditionsEditorProvider>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, { useMemo } from 'react';
import { FieldSelectorProps } from 'react-querybuilder';
import { useFormContext } from 'react-hook-form';
import { FieldSelectorProps } from 'react-querybuilder';

import { Code2 } from '@/components/icons/code-2';
import { VariableSelect } from '@/components/conditions-editor/variable-select';
import { Code2 } from '@/components/icons/code-2';

export const FieldSelector = React.memo(
({ handleOnChange, options, path, value, disabled }: FieldSelectorProps) => {
({ handleOnChange, options, path, value, disabled, context }: FieldSelectorProps) => {
const form = useFormContext();
const queryPath = 'query.rules.' + path.join('.rules.') + '.field';
const { error } = form.getFieldState(queryPath, form.formState);
Expand All @@ -23,7 +23,10 @@ export const FieldSelector = React.memo(
return (
<VariableSelect
leftIcon={<Code2 className="text-feature size-3 min-w-3" />}
onChange={handleOnChange}
onChange={(e) => {
handleOnChange(e);
context?.saveForm();
}}
options={optionsArray}
title="Fields"
value={value}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import React from 'react';
import { OperatorSelectorProps } from 'react-querybuilder';

import { toSelectOptions } from '@/components/conditions-editor/select-option-utils';
import { Select, SelectContent, SelectTrigger, SelectValue } from '@/components/primitives/select';
import { cn } from '@/utils/ui';
import { toSelectOptions } from '@/components/conditions-editor/select-option-utils';

export const OperatorSelector = React.memo(
({ disabled, value, options, handleOnChange }: OperatorSelectorProps) => {
({ disabled, value, options, handleOnChange, context }: OperatorSelectorProps) => {
return (
<Select onValueChange={handleOnChange} disabled={disabled} value={value}>
<Select
onValueChange={(e) => {
handleOnChange(e);
context?.saveForm();
}}
disabled={disabled}
value={value}
>
<SelectTrigger
size="2xs"
className={cn('w-18 bg-background hover:bg-bg-weak hover:text-text-strong text-label-xs gap-1')}
Expand Down
21 changes: 14 additions & 7 deletions apps/dashboard/src/components/conditions-editor/rule-actions.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import React, { useMemo } from 'react';
import { isRuleGroup, ActionWithRulesProps, getParentPath } from 'react-querybuilder';
import { RiMore2Fill } from 'react-icons/ri';
import { ActionWithRulesProps, getParentPath, isRuleGroup } from 'react-querybuilder';

import { Delete } from '@/components/icons/delete';
import { SquareTwoStack } from '@/components/icons/square-two-stack';
import { CompactButton } from '@/components/primitives/button-compact';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/primitives/dropdown-menu';
import { useConditionsEditorContext } from './conditions-editor-context';
import { CompactButton } from '@/components/primitives/button-compact';
import { Delete } from '@/components/icons/delete';
import { SquareTwoStack } from '@/components/icons/square-two-stack';
import { Tooltip, TooltipContent, TooltipPortal, TooltipTrigger } from '@/components/primitives/tooltip';
import { useConditionsEditorContext } from './conditions-editor-context';

export const RuleActions = React.memo(
({ path, ruleOrGroup }: ActionWithRulesProps) => {
({ path, ruleOrGroup, context }: ActionWithRulesProps) => {
const { removeRuleOrGroup, cloneRuleOrGroup, getParentGroup } = useConditionsEditorContext();
const parentGroup = useMemo(() => getParentGroup(ruleOrGroup.id), [ruleOrGroup, getParentGroup]);
const isGroup = isRuleGroup(ruleOrGroup);
Expand All @@ -40,6 +40,7 @@ export const RuleActions = React.memo(
<DropdownMenuItem
onClick={() => {
cloneRuleOrGroup(ruleOrGroup, getParentPath(path));
context?.saveForm();
}}
className="text-foreground-600 text-label-xs h-7"
disabled={isDuplicateDisabled}
Expand All @@ -56,7 +57,13 @@ export const RuleActions = React.memo(
</TooltipPortal>
</Tooltip>

<DropdownMenuItem onClick={() => removeRuleOrGroup(path)} className="text-error-base text-label-xs h-7">
<DropdownMenuItem
onClick={() => {
removeRuleOrGroup(path);
context?.saveForm();
}}
className="text-error-base text-label-xs h-7"
>
<Delete className="[&&]:size-3.5" />
Delete {isGroup ? `group` : `condition`}
</DropdownMenuItem>
Expand Down
10 changes: 4 additions & 6 deletions apps/dashboard/src/components/workflow-editor/nodes.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { ComponentProps } from 'react';
import { Link, useNavigate, useParams } from 'react-router-dom';
import { WorkflowOriginEnum } from '@novu/shared';
import { Node as FlowNode, Handle, NodeProps, Position } from '@xyflow/react';
import { ComponentProps } from 'react';
import { RiFilter3Fill, RiPlayCircleLine } from 'react-icons/ri';
import { RQBJsonLogic } from 'react-querybuilder';
import { WorkflowOriginEnum } from '@novu/shared';
import { Link, useNavigate, useParams } from 'react-router-dom';

import { createStep } from '@/components/workflow-editor/step-utils';
import { useWorkflow } from '@/components/workflow-editor/workflow-provider';
import { useConditionsCount } from '@/hooks/use-conditions-count';
import { STEP_TYPE_TO_COLOR } from '@/utils/color';
import { INLINE_CONFIGURABLE_STEP_TYPES, TEMPLATE_CONFIGURABLE_STEP_TYPES } from '@/utils/constants';
import { StepTypeEnum } from '@/utils/enums';
Expand All @@ -16,7 +17,6 @@ import { cn } from '@/utils/ui';
import { STEP_TYPE_TO_ICON } from '../icons/utils';
import { AddStepMenu } from './add-step-menu';
import { Node, NodeBody, NodeError, NodeHeader, NodeIcon, NodeName } from './base-node';
import { useConditionsCount } from '@/hooks/use-conditions-count';

export type NodeData = {
addStepIndex?: number;
Expand Down Expand Up @@ -360,8 +360,6 @@ export const AddNode = (_props: NodeProps<NodeType>) => {
},
{
onSuccess: (data) => {
console.log('data', data);

if (TEMPLATE_CONFIGURABLE_STEP_TYPES.includes(stepType)) {
navigate(
buildRoute(ROUTES.EDIT_STEP_TEMPLATE, {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import { StepResponseDto } from '@novu/shared';
import { buildDefaultValues, buildDefaultValuesOfDataSchema } from '@/utils/schema';
import { StepResponseDto } from '@novu/shared';

// Use the UI Schema to build the default values if it exists else use the data schema (code-first approach) values
export const getStepDefaultValues = (step: StepResponseDto): Record<string, unknown> => {
const controlValues = step.controls.values;
const hasControlValues = Object.keys(controlValues).length > 0;

const uiSchemaDefaultValues = buildDefaultValues(step.controls.uiSchema ?? {});
const dataSchemaDefaultValues = buildDefaultValuesOfDataSchema(step.controls.dataSchema ?? {});

if (Object.keys(step.controls.uiSchema ?? {}).length !== 0) {
return hasControlValues ? controlValues : buildDefaultValues(step.controls.uiSchema ?? {});
return {
...uiSchemaDefaultValues,
...controlValues,
};
Comment on lines +12 to +15
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why we needed to update this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a bug where if you visit step conditions and make a change before touching the template, your app crashes when visiting the template afterwards.

}

return hasControlValues ? controlValues : buildDefaultValuesOfDataSchema(step.controls.dataSchema ?? {});
return {
...dataSchemaDefaultValues,
...controlValues,
};
};
Loading
Loading