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

Nv 3510 - Open onboarding workflow node #5207

Merged

Conversation

djabarovgeorge
Copy link
Contributor

What change does this PR introduce?

This ticket is responsible for:

  • navigate to a specific workflow node.
  • reuse existing workflow.
  • allow to fetch workflow by identifier.

Why was this change needed?

Other information (Screenshots)

Copy link

linear bot commented Feb 17, 2024

Comment on lines +39 to +42
segment.track('[Get Started] Click Create Notification Template', {
templateIdentifier: blueprintIdentifier,
location: TemplateCreationSourceEnum.ONBOARDING_GET_STARTED,
});
Copy link
Contributor Author

@djabarovgeorge djabarovgeorge Feb 19, 2024

Choose a reason for hiding this comment

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

This way we will know if the user wanted to Create new use case workflow, or Configure use case node.

Suggested change
segment.track('[Get Started] Click Create Notification Template', {
templateIdentifier: blueprintIdentifier,
location: TemplateCreationSourceEnum.ONBOARDING_GET_STARTED,
});
if(node){
segment.track('Click Configure Use-Case Node [Get Started] ', {
templateIdentifier: blueprintIdentifier,
node: node
});
} else {
segment.track('Click Create Workflow [Get Started] ', {
templateIdentifier: blueprintIdentifier,
});

Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure I understand why we'd switch the [ ] to the end.

Also, this seems like something that could be handled with a ternary:

Suggested change
segment.track('[Get Started] Click Create Notification Template', {
templateIdentifier: blueprintIdentifier,
location: TemplateCreationSourceEnum.ONBOARDING_GET_STARTED,
});
const action = node ? 'Click Create Notification Template' : 'Click Create Workflow';
segment.track(`[Get Started] ${action}`, {
templateIdentifier: blueprintIdentifier,
location: TemplateCreationSourceEnum.ONBOARDING_GET_STARTED,
});

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Let's centralize the topic regarding the [area] in one place, i already addressed this question here :)
#5212 (comment)

Regarding the ternary, it has two cons in my opinion

  • one event we have a node and another does not.
  • as I love less code with reusable variables, in those scenarios where we log data it will be harder to debug code and search when the log is dynamic.

let me know what you think on the matter

Copy link
Contributor

Choose a reason for hiding this comment

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

When we don't have a node, it should be undefined, correct? In that event, it wouldn't appear anyway on the tracking event

Copy link
Contributor

@antonjoel82 antonjoel82 left a comment

Choose a reason for hiding this comment

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

Thanks for the updates!

@@ -13,3 +13,10 @@ export interface OnboardingUseCase {
steps: IOnboardingStep[];
Demo: React.ComponentType<any>;
}

export enum OnboardingNodeEnum {
Copy link
Contributor

Choose a reason for hiding this comment

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

🎯 suggestion: ‏‏Would prefer to reuse an existing enum that making another one

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could you point me to the right enum, I did not find a proper one.

Now when I am looking at the name I find it misleading, as we do not pass a node but a route. I will update it. i think OnboardingWorkflowRouteEnum would be more appropriate but naming in not the easy part 😅

async findBlueprint(idOrIdentifier: string) {
if (!this.blueprintOrganizationId) throw new DalException('Blueprint environment id was not found');

buildIdOrIdentifierQuery(idOrIdentifier: string) {
Copy link
Contributor

Choose a reason for hiding this comment

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

💭 thought: This seems like something that may be handled better at the service layer rather than making than opening up this query to multiple input types. While this may be a bit of an exaggeration, if we continue with this pattern, we could end up with a single query for 7 different identifier types.

I'd love to hear other opinions on it, but I think this query should be "closed" for modification and instead create a separate query function for the other type of identifier. This allows another function to delegate which query should be used. I also imagine a worst-case scenario that could involve | across an unindexed field resulting in terrible performance for every execution.

Definitely not a blocker, but perhaps a discussion item!‏

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Firstly, let me say that I completely agree. I really dislike having to add it here instead of at the application layer. Now, let me explain why it's included here, and if you have any other suggestions, I'd be more than happy to hear them, given the reasons mentioned above.

Here's why it's included here:

  • We want to provide users of those endpoints, starting with the blueprint and now the template itself, the ability to fetch by the identifier in cases where our user might not be aware of the _id.
  • The main reason is the validation we perform on the query payload build. To construct a proper payload, we need to determine whether it is a MongoDB ID or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But you got me thinking 👀, let me try something out.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done! :)
let me know what you think, and btw thanks for questioning the implementation ♥️

Comment on lines +39 to +42
segment.track('[Get Started] Click Create Notification Template', {
templateIdentifier: blueprintIdentifier,
location: TemplateCreationSourceEnum.ONBOARDING_GET_STARTED,
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure I understand why we'd switch the [ ] to the end.

Also, this seems like something that could be handled with a ternary:

Suggested change
segment.track('[Get Started] Click Create Notification Template', {
templateIdentifier: blueprintIdentifier,
location: TemplateCreationSourceEnum.ONBOARDING_GET_STARTED,
});
const action = node ? 'Click Create Notification Template' : 'Click Create Workflow';
segment.track(`[Get Started] ${action}`, {
templateIdentifier: blueprintIdentifier,
location: TemplateCreationSourceEnum.ONBOARDING_GET_STARTED,
});

Comment on lines +39 to +42
segment.track('[Get Started] Click Create Notification Template', {
templateIdentifier: blueprintIdentifier,
location: TemplateCreationSourceEnum.ONBOARDING_GET_STARTED,
});
Copy link
Contributor

Choose a reason for hiding this comment

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

When we don't have a node, it should be undefined, correct? In that event, it wouldn't appear anyway on the tracking event

},
});

const openNewTab = (url) => window.open(url, '_blank', 'noreferrer noopener');
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
const openNewTab = (url) => window.open(url, '_blank', 'noreferrer noopener');
const openNewTab = (url: string) => window.open(url, '_blank', 'noreferrer noopener');

And this function should be extracted outside of the component for reusability and to avoid re-computing it unnecessarily every time

return <Link onClick={() => handleOpenWorkflowClick()}>{children}</Link>;
}

function buildUrl(workflowData, node?: OnboardingWorkflowRouteEnum) {
Copy link
Contributor

Choose a reason for hiding this comment

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

💣 chore: ‏Please add types to every param

return this.mapEntity(item);
}

async findBlueprintByTriggerIdentifier(identifier: string) {
Copy link
Contributor

Choose a reason for hiding this comment

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

👏 praise: Nice, well done!‏

import { useSegment } from '../../../components/providers/SegmentProvider';
import { OnboardingWorkflowRouteEnum } from '../consts/types';

export function OpenWorkflowButton({
Copy link
Contributor

Choose a reason for hiding this comment

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

🎯 suggestion: This component and file are quite overloaded with functionality. I'd suggest we refactor it to improve readability and testability‏

Comment on lines +66 to +69
segment.track('[Get Started] Click Create Notification Template', {
templateIdentifier: blueprintIdentifier,
location: TemplateCreationSourceEnum.ONBOARDING_GET_STARTED,
});
Copy link
Contributor

Choose a reason for hiding this comment

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

duplicated call to the above

Comment on lines +44 to +62
const blueprintData = await getBlueprint();

if (!blueprintData) {
return;
}

try {
const workflowIdentifier = blueprintData.name.toLowerCase();
const workflowData = await getTemplateById(workflowIdentifier);
if (workflowData) {
const url = buildUrl(workflowData, node);
openNewTab(url);
}
} catch (error) {
createTemplateFromBlueprint({
blueprint: blueprintData,
params: { __source: TemplateCreationSourceEnum.ONBOARDING_GET_STARTED },
});
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I think that we should extract this logic to a reusable hook and do all of this under the react query mutation, like:

const useCreateTemplateFromBlueprint = (options) => {

   const { mutate: createTemplateFromBlueprint, ...rest } = useMutation(() => {
      // all logic should be placed here
      
   }, {
      ...options,
      onSuccess: ...,
      onError: ...,
   }); 


   return {
      createTemplateFromBlueprint,
   }
}

@antonjoel82
Copy link
Contributor

Per discussion with @LetItRock, we will merge this for now, and handle the discussion items above in a separate PR

@antonjoel82 antonjoel82 merged commit ac591ab into usecase-onboarding-project Feb 22, 2024
16 of 24 checks passed
@antonjoel82 antonjoel82 deleted the nv-3510-open-onboarding-workflow-node branch February 22, 2024 17:48
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