freeCodeCamp / chapter

A self-hosted event management tool for nonprofits
BSD 3-Clause "New" or "Revised" License
1.92k stars 360 forks source link

As a user / future participant after the event, I will automatically get emails notifying me of subsequent events. #107

Closed QuincyLarson closed 2 years ago

allella commented 4 years ago

Below are preliminary suggestions and questions regarding this #107 and #274.

The direction set forth here will also inform the text and email "mail merge" templates needed for #275 and #276.

Assumptions / Suggestions

Questions

allella commented 4 years ago

Also, I noticed after the fact that this comment may have been better on #274. However, since the RSVP, subscribe / unsubscribe, and email notices are all intertwined I'm not sure it matters much as long as it doesn't confuse this API issue.

ceciliaconsta3 commented 4 years ago

@allella A label is definitely the surest bet. If, and it sounds like, we will use the Subscribe component in a form alongside other elements to complete an event sign-up, (if MVP won't have a User Account Settings page) we should treat the Subscribe switch as a checkbox using checkbox role instead. It'll get sent at form submission with the other fields.

I think "Active" color as Subscribe/unchecked status and grey/disabled for Unsubscribe/checked status would do.

ceciliaconsta3 commented 4 years ago

Let me know if I covered this logic flow correctly:

1. User is automatically subscribed to chapter notifications on joining (assuming user email address a required field)

2. User subscription at event RSVP level:

3. User subscription at chapter level through event specific email:

(?) something to evaluate/discuss, perhaps after MVP ships

As for the user + chapter subscription relationship, autogenerate unique event keys based on userID + chapterID + eventID in new Subscription table?

allella commented 4 years ago

Thanks, replaying the logic highlighted some potential areas of confusion with only having subscriptions toggle on / off via rsvp or unsubscribe link.

This user story suggested getting upcoming event notifications AFTER you've attended, but with Meetup.com I believe it's possible to subscribe and get notices without ever having attended. That's a reasonable expectation too, though not explicitly an MVP story.

I guess we could also have a button on a chapter landing page to subscribe to all chapter email notifications whether they be reminders of upcoming events or general chapter notifications sent by an organizer (not an MVP that I've seen).

The question now is if subscribing and unsubscribe is connected to an rsvp (#108 & #276). Or, are subscriptions intended for upcoming events and more general announcements?

I could see a use case for both and we already have an MVP story for both cases. If we do both then I suspect we'd need to add an rsvp.subscribed to the schema to allow for subscribing or unsubscribing from a specific event's notifications vs non-event notifications.

allella commented 4 years ago

To summarize, would the following be a reasonable MVP flow?

Applicable to #107 & #275 & #274 user_chapters.subscribed would be added to the schema as a boolean to be toggled on or off by an authenticated user via the chapter landing page, like a "Follow / Unfollow" UI button or toggle. This would turn on notifications which are not related to a rsvp.

Such email notifications would have a URL to allow the user to "Unfollow {chapters.name} Notifications".

If we needed to trim the scope, then these emails could simply have a link going directly to the chapter landing page where the Follow / Unfollow button would need to be toggled. The downside here is the user would need to be logged in to stop receiving these notices.

Applicable to #108 & #276 rsvp.subscribed would be added to the schema as a boolean and this field would be for notifications which are directly related to a specific rsvp.

The user would be able to click a "Stop Receiving Notifications for {events.name}" unsubscribe link. If we narrowed the scope here as well, then the email could direct the user to the event landing page. Again, this more simple approach would have the downside of requiring a user to be logged in and then toggle a button on the event landing page to disable.

Madalena-15 commented 4 years ago

@allella @ceciliaconsta3 I have been reading your comments in both this issue and #274 and already got some questions! But I will start off with one or two...

Not sure if the user will have a general account setting page or not, but for assumption's sake, let's say there is. There could be a page for managing subscriptions (via both notifications or emails) and for auser to find this page in one of these two ways, which is either:

So, once the user starts receiving emails (after going to the event) and they want to unsubscribe, they can click on the 'unsubscribe' link, which takes them to the managing subscription page.

I hope my point is relevant to this issue. If so, what is your thought on this?

allella commented 4 years ago

@madaleneaza-design I think we've been operating on the assumption that a profile / subscription page is not a MVP feature. It's definitely a reasonable expectation to add one to the Roadmap.

So far there's been no explicit MVP user story for a profile page to do anything since authentication will be using Google. Therefore, we don't have an immediate need for users to manage their email, password, profile picture, and such.

Would you agree we can start by allowing subscribing or unsubscribing to an event or a chapter using the MVP interfaces we know are already required?

If we didn't have a profile / manage your subscriptions page, for MVP, then we can still allow users to subscribe and unsubscribe using links or UI elements on these MVP interfaces.

@ceciliaconsta3 posted suggestions on checkbox vs switch vs buttons for the UI on #274

Madalena-15 commented 4 years ago

@allella Yeah I can agree and I cannot see why not (to allow subscribing and unsubscribing using the known MVP features), as long in terms of user experience, the links/ UI elements are easier to navigate and use in the layout (which I am sure it will be).

I will hop onto #274 to post my response :)

allella commented 4 years ago

For the more technical side of the mail sending, we had a good conversation in today's meeting on using nodemailer and SMTP with free / cheap tiers of 3rd party transactional mailing services.

allella commented 4 years ago

@davidals brought up that we'd want a scheduled trigger to check for and send email notifications for event rsvps and other such "X days before" notifications. That's being discussed on #359.

I referred the earlier suggested schema changes to allow for unsubscribing from a specific rsvps' notifications and a specific chapter's notifications.

However, upon reviewing the talk about "Following" or "Unfollowing" a Chapter or RSVPs I found that "Following" an event may not make sense. So, here's a refined view of toggling email notifications on or off.

Toggling rsvp.subscribed rsvp.interested on or off

Toggling _user_chapters.subscribed user_chapters.interested_ on or off

davidals commented 4 years ago

I think it's also valuable to have an account setting for that. Something like notifications_allowed that would override all of the subscribed when set (And default subsequent RSVPs to false), and when a user intentionally chooses to subscribe it would toggle the account level back to on.

allella commented 4 years ago

@ceciliaconsta3 @madaleneaza-design @davidals @Zeko369

One other consideration is the following:

Canceling a RSVP vs Unfollowing a RSVP Toggling off the "Follow this Event" switch on an event page, for users with an existing rsvp, would not necessarily mean cancelling the RSVP.

It's likely an organizer wants to see who cancelled their RSVP, which means we'd need an rsvp.canceled field in the schema to store that value instead of deleting records in the rsvp table. We likely only want a basic cancellation feature for MVP.

The event page would then have a "Cancel my RSVP" (button) to go along with the previously mentioned "Follow this Event" switch. It seems like a fair assumption that cancelling an rsvp would immediately sets the rsvp.canceled to TRUE and rsvp.subscribed rsvp.interested to FALSE.

I was wondering if we should allow someone to follow an event without being subscribed to it, but I feel that could lead to confusion if someone clicks to follow an event and assumes that means they are RSVP'ed. That could be a real problem if people show up to an event and don't have a valid rsvp. So, it's probably best we don't show a "Follow this Event" UI switch unless the user has an active (rsvp.canceled = FALSE) rsvp record.

Thoughts?

davidals commented 4 years ago

I think this is where language get's handy.

Instead of "follow" call it "Interested", and the toggle should say something like "Notify me of updates to this event"

Agree on canceling RSVP makes you stop receiving notifications.

If you think about Facebook Events, there are 3 options "Not going, Interested, Going". We could use a similar approach (and maybe even wording) since people should be familiar with the concept.

allella commented 4 years ago

Sounds good.

So the "RSVP" buttons could be "Going" and "Not Going", depending on if the user already has an rsvp.

Then, an "Interested" UI slider to toggle on/off interest regardless of the rsvp status.

davidals commented 4 years ago

Here's the PR adding those fields: https://github.com/freeCodeCamp/chapter/pull/374

ojeytonwilliams commented 3 years ago

https://github.com/freeCodeCamp/chapter/pull/640 gives us something to work with, but it's far from a complete solution.

Ravichandra-C commented 2 years ago

So the "RSVP" buttons could be "Going" and "Not Going", depending on if the user already has an rsvp. Then, an "Interested" UI slider to toggle on/off interest regardless of the rsvp status.

@allella @ojeytonwilliams Could you please let me know what work is remaining in this issue apart from the above UI changes?

allella commented 2 years ago

@Ravichandra-C

When a new event is created by an organizer for a specific chapter, we will want to query the _user_chapterroles table_ where _user_chapter_roles.chapter_id = events.id (this will be the event id of the newly created event) AND _user_chapterroles.interested = true.

There's a basic example of the email to send to notify users about new events. We'd want to merge in values from the event and chapter tables, as indicated by the { } placeholders in the example in that link.

We have a separate issue to handle the unsubscribe links in the email footer. That issue may require more conversation and it could be somewhat complicated if we are trying to allow opt-out without being logged in. So, for now, we can keep a placeholder where the unsubscribe links will go.

Does that help?

Ravichandra-C commented 2 years ago

@allella Thanks a lot for your help. I've a few questions on your comment.

When a new event is created by an organizer for a specific chapter, we will want to query the user_chapterroles table where >_user_chapter_roles.chapter_id = events.id (this will be the event id of the newly created event) AND >user_chapter_roles.interested >= true.

Currently we have the below functionality.

When a new event is created by organizer in a specific chapter, We query user_chapter_roles table where user_chapter_roles.chapter_id=chapter.id( id of the chapter in which the event is created ) and user_chapter_roles.interested = true and send an email with below text.

image

_user_chapter_roles.chapter_id = events.id

Shouldn't this be assigned with chapter.id instead of event.id?

There's a basic example of the email to send to notify users about new events. We'd want to merge in values from the event >and chapter tables, as indicated by the { } placeholders in the example in that link.

the basic example hyperlink is liked to schema spy. Could you please provide the text that should be used in the email ?

PFB the template of the email that we are currently Sending when a new event is created(Code is already in the repo).

 const subject = `Invitation to ${event.name}.`;
const body =
      `When: ${event.start_at} to ${event.ends_at}<br>` +
      (event.venue ? `Where: ${event.venue?.name}<br>` : '') +
      `Event Details: <a href="${eventURL}">${eventURL}</a><br>
<br>
- Cancel your RSVP: <a href="${eventURL}">${eventURL}</a><br>
- More about ${event.chapter.name} or to unfollow this chapter: <a href="${chapterURL}">${chapterURL}</a><br>
<br>
----------------------------<br>
You received this email because you follow this chapter.<br>
<br>
See the options above to change your notifications.`;

for now, we can keep a placeholder where the unsubscribe links will go.

Sure, I'll add the place holder for unsubscribe link.

ojeytonwilliams commented 2 years ago

@allella @Ravichandra-C I think this is largely done - we are automatically sending the notification emails already. If someone has _user_chapterroles.interested they will be emailed whenever a new event is created on that chapter. However we still need to

We should only set interested to be true if the user doesn't yet have a _user_chapterrole for that chapter.

I think that's all we need for now.

Ravichandra-C commented 2 years ago

@ojeytonwilliams ,In addition to the above changes ,Should I also include these UI changes as part of this issue or will they be worked on as separate issue?

So the "RSVP" buttons could be "Going" and "Not Going", depending on if the user already has an rsvp. Then, an "Interested" UI slider to toggle on/off interest regardless of the rsvp status.

ojeytonwilliams commented 2 years ago

@Ravichandra-C I'll handle that in a separate PR :)

allella commented 2 years ago

@Ravichandra-C I probably had an error above in the logic. I trust you understand what needs to be done on the technical side, so we should be good to proceed with what you have.

Thanks

Ravichandra-C commented 2 years ago

@allella @ojeytonwilliams Thank you for explaining. I understood what needs to be done. I'll be working on it.

Ravichandra-C commented 2 years ago

@ojeytonwilliams , For setting the user_chapter_role.interested=true when an user rsvp to an event, I'm creating a new mutation with name SetUserInterestForChapter which takes the event_id as the parameter. Could you please let me know if we already have this mutation? I searched in the repo and also the generated/graphql.tsx but I did not find it, I just wanted to make sure that I'm not adding duplicate code.

allella commented 2 years ago

It makes sense that most users will be happy to get notified of future events for a chapter, but what if a user had previously toggled _user_chapterrole.interested=false?

It sounds like this user story would set _user_chapterrole.interested=true without asking, but a user may not want to get future notifications.

Would we want to show a toggle field on the RSVP form, set that toggle's default value to match the user's current value for _user_chapterrole.interested, but still allow them to toggle / change it when they RSVP?

There are events in my town that I might only attend once a year, or for a special occasion, but that doesn't mean I necessarily want to be forced to receive future notifications.

Thoughts?

Ravichandra-C commented 2 years ago

@allella , This mutation will check if user already has a preference set in the database, if it is already set, then we are not doing anything.If it is not set then we are by default setting the user_chapter_role.interested = true. So if a user has already set his preference to false then, as we are not updating it, he will not get any future notifications.

ojeytonwilliams commented 2 years ago

It sounds like this user story would set user_chapter_role.interested=true without asking, but a user may not want to get future notifications.

We definitely don't want to do that and Ravi's proposed logic should work as intended.

Would we want to show a toggle field on the RSVP form, set that toggle's default value to match the user's current value for user_chapter_role.interested, but still allow them to toggle / change it when they RSVP?

Seems reasonable, yeah. We could have it default to true when _user_chapterrole.interested is not set and just mirror their settings once interested has a value.

I'm creating a new mutation with name SetUserInterestForChapter which takes the event_id as the parameter. Could you please let me know if we already have this mutation?

We don't have any mutations that change _user_chapterrole.interested, so please go ahead.

I searched in the repo and also the generated/graphql.tsx but I did not find it, I just wanted to make sure that I'm not adding duplicate code.

Cool. Just to aid any future searches: all mutations must be defined in either a queries.ts or a mutations.ts file (ideally the latter!), so if they're not in a file with those names they effectively don't exist.