Global Announcements with User Tracking (copyable)

This was inspired by a recent tutorial by @Robert_Petitto (who else? :rofl:)

For an app I am currently working on, there is a requirement to support Global Announcements. The basic requirements are:

  1. An Administrator can create an announcement and target it at a specific group of users
  2. When a user opens the app, any new announcements will be front and centre on their dashboard
  3. The user can view the announcement and mark it as read
  4. Administrators can track how many users have read each announcement, and which users

Requirements 1 to 3 are easy. Just add a User Specific Boolean to the Announcements table and weā€™re done. But requirement 4 is a little trickier. The problem is that you canā€™t get at user specific data for doing things like rollups, etc. So Iā€™ve been mulling this over for a few days, and after watching Bobā€™s tutorial earlier today I had a sudden flash of inspiration :grinning:

Here is how I ended up doing it:

  • Announcements are presented as an Inline List
  • When a user taps an Announcement, a custom action writes their UserID to a USC, and then does a View Details
  • In my Announcements table, I have a ā€œRead Byā€ column. This is a Basic Text column, but actually contains a joined list of the UserIDā€™s of all users that have read the announcement. This list is built dynamically as each user marks the announcement as read
  • I then take that ā€œRead Byā€ column and use a Split Text column to create an array of UserIDā€™s
  • This is in turn used to create a multi-relation back to my Users table (this provides access to a list of users that have read the announcement)
  • And finally, I do a rollup on that relation to get a count of users that read the announcement

Iā€™ve put together a demo and added it to my ā€œCommunity Demoā€™sā€ app. Here is what the demo looks like:

Note that when this goes into my ā€œrealā€ app, Row Owners and Roles will be enabled, so users wonā€™t be able to see the counts or who else read each announcement. But I left those disabled for the purpose of the demo. Also in the demo users can mark announcements as ā€œUnreadā€. This option wonā€™t be available in the ā€œrealā€ app.

The app is copyable, so feel free to grab it and play around with it.

Would also be interested to hear of other approaches to this, and in particular if Iā€™ve missed something obvious and overcomplicated it (which I usually do) :rofl:

17 Likes

Thank you for the tutorial and explaination

1 Like

Well done!

1 Like

Thanks!
Curious to know how you would approach this?
What I have seems to work okay, but Iā€™m always open to learning better/alternative ways to get things done :slightly_smiling_face:

Hi Darren, what does this step look like? I am assuming there is a custom action when they ā€œmark as readā€ but I dont know how to keep adding new values (UserIDs) to a basic text field without overwriting it.

  • When a user taps an announcement, their User ID is written to a User Specific Column (usc-user)
  • Then there are 3 columns in the Announcements table that help dynamically build the list:
    • tp-first-user - this is a Template column that just mirrors the contents of usc-user
    • tp-subsequent-users - another Template column that contains the current contents of Read By, a comma (,), and usc-user
    • ite-new-read-by - an if-then-else column that determines which of the two templates to use when the user marks the announcement as read. If Read By is empty, use the first one, otherwise use the second one.
  • Then when the user taps the ā€˜Mark as Readā€™ button, the Read By column is updated to the result of the if-then-else column.

Note that my method doesnā€™t remove users from the list when they mark an announcement as ā€œUnreadā€ (that wasnā€™t a requirement for my app). But @Lucas_Pires and @Robert_Petitto showed how this can be done with their ā€œTrebuchet Methodā€. If you watch Bobā€™s video, youā€™ll see that he explicitly covers that step.

1 Like

Has anyone ever figured out how to remove a specific chunk of text from a joined list of values? (Assuming that the joined list isnā€™t being dynamically generated and is a static list that has been written to the sheet already)

Closest Iā€™ve seen was @Jeff_Hager doing a bunch replacements using a blank column. But they were very specific use cases. Iā€™ve yet to see a general solution, and I doubt that it will be possible until we get some string manipulation methods in the GDE.

PS. Iā€™d be overjoyed to be proven wrong on this :grin:

1 Like

Yeah, I have a pretty non-user friendly method that I am going to try to make this work. String manipulation would be huge!

Could be that @Lucas_Pires has an ace up his sleeveā€¦

2 Likes

nice! hope so

Was just thinking about this. Iā€™ve seen that a few people have also asked for Regex capability in the GDE. Whilst this would be awesome, it could be a double-edged sword. Regex is incredibly powerful, but if you donā€™t know what youā€™re doing itā€™s very easy to write regular expressions that become huge resource hogs. I can imagine folks going to town with regex in the GDE, and then wondering why their apps are grinding to a halt. So maybe not such a good idea. But vanilla string functions like left(), right(), substr(), etcā€¦ yes please!

2 Likes

Some days I really wish I could switch these two replacement fields around.

image

Sometimes I want to dynamically set the value to be replaced, and sometimes I want to just type in a replacement value instead of creating another column (especially a blank/empty column just for the replacement). Would really help to make a lot of things easier,ā€¦along with a full list of string manipulation options :wink: . Iā€™ve hit a few walls where code is easier than no-code and Iā€™ve had to jump through a few hoops to make something work.

Do you have an example of a list and the value you would want removed? Is the value that you want removed a certain value, or is it kind of unlimited what it could be?

3 Likes

uh-ohā€¦ here we go againā€¦ :fishing_pole_and_fish: :rofl:

3 Likes

hehe, Iā€™m a glutton for punishment.

It would just be a comma separated list of Row IDs that are written to the sheet by an add row action.

ie. QmGPN3dQScStbkkcg8Ebzg, B05-ku22R8qWvbebbysRlQ, DsxAk8YbTp2hX3kRCyEPlw

Removing B05-ku22R8qWvbebbysRlQ, for example.

One idea Iā€™ve considered is to use a multi-step action to clear the column AND write the existing array to another column that then gets turned into an inline list for them to re-select from. That would really only work for small arrays where itā€™s not too cumbersome for the user to have to re-select the correct items.

1 Like

Brilliant! I have an immediate use case for this :clap: :clap: :clap: :clap:

Definitely not easy since itā€™s Row IDs. The only thing I could think of would involve a Split Text column, a relation to a sheet that has those Row IDs in rows, and some variation of the Trebuchet method to rebuild a Joined List of Row IDs minus the Row ID you want removed to overwrite your existing joined list.

1 Like

Should i just delete my post today then haha. Smh. This is what I get for not knowing lingo. The one thing I didnt type to find this yesterday was ā€œglobal announcementsā€ :slight_smile:
Will dive in today and see how I get on!

Ok done! Feel like im learning faster now :slight_smile: So far only a couple errors as opposed to millions ha!
Very pleased with result. Not sure where the duplicate of ā€˜most recentā€™ announcement is coming from though. I posted about 10 msgs as a test and the most recent is always duplicated at the bottom of the inline list for some reason. I tried to reference your community app @Darren_Murphy but by actions are the same, so not quite sure.

If anyone can point me in the direction of a guide to learn how to set up my SMS/Email notifications thats my last step! Ready for this zapier beast