-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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: add invite team members nudge flow #5549
Conversation
✅ Deploy Preview for novu-design ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
✅ Deploy Preview for dev-web-novu ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
apps/api/src/app/invites/usecases/invite-nudge-webhook/invite-nudge-usecase.ts
Outdated
Show resolved
Hide resolved
// check if this is first trigger | ||
const notifications = await this.notificationRepository.count({ | ||
_organizationId: command.organizationId, | ||
_environmentId: command.environmentId, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
☑ chore: This will be super costly in terms of Mongo request, what we can do instead is take the first five or whatever number of notifications, and if there are then return.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall I add limit 1
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, but maybe better would be to do that with findOne
@@ -206,4 +221,68 @@ export class ParseEventRequest { | |||
|
|||
return reservedVariables?.map((reservedVariable) => reservedVariable.type) || []; | |||
} | |||
|
|||
public async sendInAppNudgeForTeamMemberInvite(command: ParseEventRequestCommand) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
☑ chore: we don't need to do this for self-hosted
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, but all code above it is not needed to be executed
@@ -206,4 +221,68 @@ export class ParseEventRequest { | |||
|
|||
return reservedVariables?.map((reservedVariable) => reservedVariable.type) || []; | |||
} | |||
|
|||
public async sendInAppNudgeForTeamMemberInvite(command: ParseEventRequestCommand) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤓 nitpick (non-blocking): can we please also cover this logic with e2e tests?
@@ -206,4 +221,68 @@ export class ParseEventRequest { | |||
|
|||
return reservedVariables?.map((reservedVariable) => reservedVariable.type) || []; | |||
} | |||
|
|||
public async sendInAppNudgeForTeamMemberInvite(command: ParseEventRequestCommand) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
☑ chore: and let's maybe also have this under the feature flag so we can disable if something is odd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can I copy this line of code after changing the key
https://github.com/novuhq/novu/blob/NV-3697/apps/api/src/app/messages/usecases/get-messages/get-messages.usecase.ts#L61C5-L68C7 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, but with the new feature flag created in LD and as well as constant in the code
export class InviteNudgeWebhook { | ||
constructor(private memberRepository: MemberRepository) {} | ||
|
||
async execute(command: InviteNudgeWebhookCommand) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
☑ chore: same behind the feature flag
apps/api/src/app/events/usecases/parse-event-request/parse-event-request.usecase.ts
Outdated
Show resolved
Hide resolved
apps/api/src/app/widgets/usecases/mark-message-as/mark-message-as.usecase.ts
Outdated
Show resolved
Hide resolved
const location = useLocation(); | ||
const state = location.state as { redirectTo?: { pathname?: string } }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤓 nitpick (non-blocking): please put the appropriate types on the useLocation
hook
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a couple notes on the web
side!
export interface LocationState { | ||
redirectTo: { | ||
pathname: string; | ||
}; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❓ question: Why are we defining the type for the return of the useLocation
hook here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
☑ chore: We should avoid exporting a generic type from here as we may unknowingly cause circular dependencies
if (state?.redirectTo?.pathname) { | ||
navigate(state?.redirectTo?.pathname); | ||
} else { | ||
navigate(ROUTES.WORKFLOWS); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✏ suggestion:
if (state?.redirectTo?.pathname) { | |
navigate(state?.redirectTo?.pathname); | |
} else { | |
navigate(ROUTES.WORKFLOWS); | |
} | |
navigate(state?.redirectTo?.pathname || ROUTES.WORKFLOWS); |
* feat: add initial flow for invite nudge * feat: add route redirect * fix: add protonmail in cspell * fix: create const for payload key * fix: add state prop in navigate * fix: add user in analytics * fix: add webhook url variable * fix: pr comments, featute flag * fix: update hubspot list env variable * fix: failing test * fix: navigate to pathname * fix: decryption api key for webhook hmac
What changed? Why was the change needed?
In NV-3697, we want to use Novu workflow to send in-app and after some delay email. hubspot will be used to send email
Novu workflow :- Trigger -> in-app -> delay (24hr) -> email (with condition on webhook)
Flow:- User trigger the workflow, based on all conditions, in-app notification is sent to the user. After 24hr delay, workflow will create post request to webhookUrl (here webhookurl is new /invites/webhook API). If all conditions are satisfied, email is sent using hubspot.
Screenshots
Expand for optional sections
Related enterprise PR
Special notes for your reviewer