Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dashboard): add delay step #7131

Open
wants to merge 18 commits into
base: next
Choose a base branch
from
Open

Conversation

ChmaraX
Copy link
Contributor

@ChmaraX ChmaraX commented Nov 26, 2024

What changed? Why was the change needed?

Current know issues:

  • LD flag for disabling steps (will be done in separate PR)
  • [visual] the error border is missing on the amount field (will be done in separate PR)

Added logic for control value forms which are on the first sidebar:

image

wf_delay_step.mp4

Copy link

linear bot commented Nov 26, 2024

Copy link

netlify bot commented Nov 26, 2024

Deploy Preview for novu-stg-vite-dashboard-poc ready!

Name Link
🔨 Latest commit 2a08599
🔍 Latest deploy log https://app.netlify.com/sites/novu-stg-vite-dashboard-poc/deploys/6745d5864c78640008f5a263
😎 Deploy Preview https://deploy-preview-7131--novu-stg-vite-dashboard-poc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

};

export const ConfigureStepInlineForm = (props: ConfigureStepInlineFormProps) => {
const { workflow, step, issues, update, updateStepCache } = props;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

we are drilling the props quite deep, we should think about using the hooks here, but I left it like this for consistency.

Comment on lines +32 to +48
/**
* We need to get the issues from the workflow response
* because the step is not re-fetched when workflow is updated
*
* TODO:
* 1. add all step data to workflow response
* 2. remove StepProvider and keep just the WorkflowProvider with step value
*/
const issues = useMemo(() => {
const newIssues = workflow?.steps.find(
(s) =>
getEncodedId({ slug: s.slug, divider: STEP_DIVIDER }) ===
getEncodedId({ slug: stepSlug, divider: STEP_DIVIDER })
)?.issues;

return { ...newIssues };
}, [workflow, stepSlug]);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The fact that we update both step and workflow with one endpoint, but fetch the updated data from 2 endpoints causes a lot of issues regarding stale data, caching etc etc.

We should fix this asap by fetching everything from workflows response as I suggested here in the comment or some other solution.

Copy link

github-actions bot commented Dec 3, 2024

LaunchDarkly flag references

🔍 1 flag added or modified

Name Key Aliases found Info
IS_ND_DELAY_DIGEST_EMAIL_ENABLED IS_ND_DELAY_DIGEST_EMAIL_ENABLED

Copy link

pkg-pr-new bot commented Dec 3, 2024

Open in Stackblitz

@novu/client

npm i https://pkg.pr.new/novuhq/novu/@novu/client@7131

@novu/framework

npm i https://pkg.pr.new/novuhq/novu/@novu/framework@7131

@novu/js

npm i https://pkg.pr.new/novuhq/novu/@novu/js@7131

@novu/headless

npm i https://pkg.pr.new/novuhq/novu/@novu/headless@7131

@novu/nextjs

npm i https://pkg.pr.new/novuhq/novu/@novu/nextjs@7131

@novu/node

npm i https://pkg.pr.new/novuhq/novu/@novu/node@7131

@novu/notification-center

npm i https://pkg.pr.new/novuhq/novu/@novu/notification-center@7131

novu

npm i https://pkg.pr.new/novuhq/novu@7131

@novu/providers

npm i https://pkg.pr.new/novuhq/novu/@novu/providers@7131

@novu/react

npm i https://pkg.pr.new/novuhq/novu/@novu/react@7131

@novu/react-native

npm i https://pkg.pr.new/novuhq/novu/@novu/react-native@7131

@novu/shared

npm i https://pkg.pr.new/novuhq/novu/@novu/shared@7131

commit: 44f83c5


export type StepEditorContextType = {
isPending: boolean;
step?: StepDataDto;
refetch: (options?: RefetchOptions) => Promise<QueryObserverResult<StepDataDto, Error>>;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

unused

Copy link
Contributor

@SokratisVidros SokratisVidros left a comment

Choose a reason for hiding this comment

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

I strongly suggest decoupling the form logic from the form wrapper. That is, the form of every step editor should work both in the first side bar or the second sidebar.

Currently, I noticed a lot of duplication between the template form and the inline form. Introducing a StepForm component to host the form handling that is reused from the different sidebar containers should simplify the logic drastically.

isReadOnly?: boolean;
};

export const NumberInputWithSelect = ({
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
export const NumberInputWithSelect = ({
export const DurationInput = ({

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Its a generic component not necessarily a duration, it can be also 10 horses

import { useMemo } from 'react';

type InputWithSelectProps = {
fields: {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nested in props is always 👿 . how about using two flat props?

  1. unit: 'seconds' | 'minutes' | 'hours' | 'months'
  2. amount: number

This should simplify the logic of the handleChange a lot.

Copy link
Contributor

Choose a reason for hiding this comment

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

@SokratisVidros this is what we agreed before with @desiprisg and we use this pattern in other places where the component is using two form fields

selectKey: string;
};
options: string[];
defaultOption?: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need the default option prop? The unit prop should be the default option otherwise its defaultOption[0].

placeholder,
isReadOnly,
}: InputWithSelectProps) => {
const { getFieldState, setValue, getValues, control } = useFormContext();
Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest making the DurationInput a primitive and then wiring it to the RHF either in workflow editor or with a wrapper component under /components/workflow-editor if necessary.

It will give us way more flexibility and make the component reusable.

Copy link
Contributor

Choose a reason for hiding this comment

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

The wrapper component already exists. See here.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure we can do something about it because this component uses the two form fields, check the FormField usage.

import { SaveFormContext } from '@/components/workflow-editor/steps/save-form-context';
import { DelayForm } from '@/components/workflow-editor/steps/delay/delay-form';

const STEP_TYPE_TO_INLINE_FORM: Record<StepTypeEnum, (args: StepInlineFormProps) => React.JSX.Element | null> = {
Copy link
Contributor

Choose a reason for hiding this comment

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

This code along with calculateDefaultValues is duplicated between this new component and configure-step-template-form.tsx We need to make it dry.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree.
Also, it will result in the form nested under another form, which we wanted to avoid.
The configure-step-form should just register all the fields under the controls in the form I guess, because this is the shape of the step and that will be updated later with using the update workflow endpoint.

{
   "name": "In-App Step",
   "stepId": "some-step-id",
   "controls": { ... } 
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Later here we will also need to connect custom step controls from the code created workflows.

import { useMemo } from 'react';

type InputWithSelectProps = {
fields: {
Copy link
Contributor

Choose a reason for hiding this comment

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

@SokratisVidros this is what we agreed before with @desiprisg and we use this pattern in other places where the component is using two form fields

placeholder,
isReadOnly,
}: InputWithSelectProps) => {
const { getFieldState, setValue, getValues, control } = useFormContext();
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure we can do something about it because this component uses the two form fields, check the FormField usage.

@@ -73,6 +75,7 @@ export const AddStepMenu = ({
onMenuItemClick: (stepType: StepTypeEnum) => void;
}) => {
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const isDelayDigestEmailEnabled = useFeatureFlag(FeatureFlagsKeysEnum.IS_ND_DELAY_DIGEST_EMAIL_ENABLED);
Copy link
Contributor

Choose a reason for hiding this comment

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

what ND means? new dashboard?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes

import { SaveFormContext } from '@/components/workflow-editor/steps/save-form-context';
import { DelayForm } from '@/components/workflow-editor/steps/delay/delay-form';

const STEP_TYPE_TO_INLINE_FORM: Record<StepTypeEnum, (args: StepInlineFormProps) => React.JSX.Element | null> = {
Copy link
Contributor

Choose a reason for hiding this comment

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

I agree.
Also, it will result in the form nested under another form, which we wanted to avoid.
The configure-step-form should just register all the fields under the controls in the form I guess, because this is the shape of the step and that will be updated later with using the update workflow endpoint.

{
   "name": "In-App Step",
   "stepId": "some-step-id",
   "controls": { ... } 
}

import { SaveFormContext } from '@/components/workflow-editor/steps/save-form-context';
import { DelayForm } from '@/components/workflow-editor/steps/delay/delay-form';

const STEP_TYPE_TO_INLINE_FORM: Record<StepTypeEnum, (args: StepInlineFormProps) => React.JSX.Element | null> = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Later here we will also need to connect custom step controls from the code created workflows.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants