Hi there AppWorks fans,
Welcome to a new installment of AppWorks tips.
Oh man, how to start on this blog post!? “Notifications”! We want it all, but the AppWorks runtime is not provided with this feature out of the box. At least, not for now; This can always change somewhere in the future!? 🤔 Let’s not wait for it but come in action with our craftsmanship! I normally ask myself questions on how to implement such feature, but…
Let get right into it…
…and introduce an entity with name ‘Notification’ with this set of properties:
Label | Name | Type | Notes |
---|---|---|---|
Trigger type | ntf_trigger_type | Enum text | Static values of ‘Event‘, ‘Time’, and ‘Condition’ |
Message | ntf_message | text | |
Is read | ntf_is_read | Boolean | ‘true’ or ‘false‘ |
Make it all nice and publishable, so you can create instances in runtime by hand (for now).
For this post, we create instances of the notification entity manually, but in the end (out of scope for this post) we would like to automate this. So, notification instances will be created based on events like this:
On 'project' instance creation
When a 'task' is out of its due date
When the budget of a 'project' instance is exceeding its limitation
On any entity instance update where the owner is a certain user
I know…These are advanced conditional events managed via ‘Rule’ BBs triggering BPMs, but it should be possible with an interesting ‘Notification configuration’ entity model. Check the extension thoughts in the end of this post!
Let’s continue our post; Notifications are user related, so we connect them with a ‘toOne’ relation to the ‘User’ “identity entity” of the platform. I also expose the ‘Web service’ BB on this entity with all CRUD operations enabled (just for this demo); this includes the relationship operations. Next to these operations, I created a new ‘NotificationsByUserId’ operation for later usage which includes an ‘Integer’ type of parameter which (later on) equals the identity id of the related ‘toOne’ user…Continue the grind for this one!
You know the drill on that last ‘Web service’ BB task…Yes, it requires a service container of the ‘Application Server’ from the ‘System Resource Manager’ artifact! Comment me if you don’t have a clue what I’m talking about. Ohhhh…Don’t forget to add that relationship to the ‘Create’ form so we ‘see’ what we’re doing in runtime. We can always remove it afterwards.
Also, update the ‘All notifications’ list BB with the related user entity information (the ‘UserId’ and identity ‘Id’). Just like this:
We also save the entity nicely in the ‘entities’ folder of our project…correct? I love you too! 😘
Now, let’s publish it all and create some instances of the notification entity. Make sure to use some variety of data with also other related user accounts. The next step is to assess our ‘NotificationsByUserId’ webservice operation!
…
The ‘All notifications’ list will show all entity instances, but we only would like to get ‘notified’ on our own notifications! Well, we exposed a nice webservice for this which we can evaluate with the ‘Web Service Interface Explorer’ artifact. Find it and try it out with a valid ‘UserId’ as parameter:
1 | <SOAP:Envelope> |
This is our response which is the input for the next step where we built a custom notification ‘Bell’ icon!
1 | <data> |
What about the ‘All notifications’ list at runtime? Well, you can secure it so only the ‘Administration’ role can access it. The end-user only needs a new filtered list for his “own” notifications! This filtering is a bit out of scope for the post as it requires a small workaround trick to make it happen. Why? Well, you need a dynamic filter which can only read a specific value not directly available to make a satisfying check. In small steps to get you a simple glimpse on this thought:
- Create a ‘helper’ property
ntf_user_id
(not shown anywhere!)- We set the value of this property with an event type of Rule BB on the relation change ‘toOneUser’; You can name it
e_on_rel_change_set_user_id
. So, when you “set” a new related user for the notification it will go off!- The rule will start a small short-lived BPM (
bpm_set_user_id
) calling a ‘special’ runtime reference webservice with nameGetUserDetails
of ‘Method Set Notification 1.0’ which will update our ‘helper’ property with a valid value. Why this specific service? Well, it’s the only service returning a valid ‘UserId’ which we can check in the filtered list! A quick double-check BPM from my side:With the “consolidated” view of the message map for your reference:
- Our new list will have a filter like this
ntf_user_id equals to $(targetUser())
. The value of ‘targetUser()’ will return the current logged in UserId, so now you know why we need to do it like this as there is no other way to dynamically check a related user entity instance…Comment me if you don’t agree on this one and if you see another entry?
Nice, everything cleared out. Our notification list is ready; Time for a small customization hack to show a solid bell icon when we have an “unread” notification on our name! 😎
The bell icon
For this part of the post, I follow my own HTML5 post and end up with a structure like this in my project:
This is the start content of the ‘playground.htm’ file:
1 |
|
This is the start content for ‘playground.js’ file:
1 | $(document).ready(function() { |
Other notes:
- Here you can find the bell SVG images; Just download them and upload them to the project folder.
- After publication, you can check these URLs for content validation:
1http://192.168.56.107:8080/home/appworks_tips/nl-bos-gen-assets/html/playground.htm
2http://192.168.56.107:8080/home/appworks_tips/nl-bos-gen-assets/js/playground.js
3http://192.168.56.107:8080/home/appworks_tips/nl-bos-gen-assets/images/svg/bell-regular.svg
4http://192.168.56.107:8080/home/appworks_tips/nl-bos-gen-assets/images/svg/bell-solid.svg
Open the <F12>
developer tools of the browser to double-check the jQuery document ready console log! Once done, we go to the next step where we create a new homepage (name it hp_main
) with ‘Lists’, ‘Results’, and ‘Web Content’ panels; The last one is of height 7%. This homepage will replace the default homepage of the platform.
This is the relative URL (including the current ‘userId’) behind the ‘Web Content’ panel:
./../../../nl-bos-gen-assets/html/playground.htm?userId={User.Identity.Id}
In runtime, you’ll see this result:
If you’re using a regular test account (like we good low-coders do!), you need to set the runtime security on the homepage document context menu!
Next step…A simple one! Show the bell icon! It’s a small update in the body of the HTML file:
1 | <body> |
Publish the file and refresh the browser; Or even better…Use an ‘Incognito’ browser where things just refresh nicer without annoying caches! The only thing left is the JavaScript implementation with this logic in mind:
- Get a grip of the ‘userId’ parameter sent with the homepage ‘Web Content’ panel
- Call our ‘NotificationsUnReadByUserId’ webservice with the ‘userId’ as parameter value
- On success, we can check if an unread notification is found and switch to the ‘solid’ bell icon!
- Finally, we want to poll (every 30 sec.) the webservice for new unread notifications…
Double check this simple and readable implementation (watch the case-sensitivity for ‘userId’!):
1 | $(document).ready(function() { |
This is a copy of the JSON response of my success function for reference:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 {
"notification":{
"notification-id":{
"Id":"327681", "ItemId":"080027c2550fa1ed8caaf031231d98fc.327681"
},
"ntf_trigger_type":"event", "ntf_message":"hello", "ntf_is_read":"false",
"Title":{
"Value":"notification-327681"
},
"to_one_user":{
"Identity-id":{
"Id":"4", "ItemId":"F8B156E1037111E6E9CB0FBF3334FBBF.4"
}
}
},
"notification":{
"notification-id":{
"Id":"655361", "ItemId":"080027c2550fa1ed8caaf031231d98fc.655361"
},
"ntf_trigger_type":"event", "ntf_message":"world", "ntf_is_read":"true",
"Title":{
"Value":"notification-655361"
},
"to_one_user":{
"Identity-id":{
"Id":"3", "ItemId":"F8B156E1037111E6E9CB0FBF3334FBBF.3"
}
}
}
}
Well, looks like the trick is working…at least for my post! 😎
Extension points
This post shows a simple demonstration of a nice notification bell, but off-course we can extend this with these features:
- Use a nice bootstrap badge as notification “Badge” which includes a number of unread items!
- Make the refresh poll interval configurable via the global project configuration entity.
- Make the icon clickable, so it opens a notifications homepage or a panel layout (as modal popup!?).
- Built a notification Entity Relation Diagram like this to make it configurable when notification instances are created. With this implementation you can create ‘Rule’ BBs starting BPMs checking the configurations and create ‘Notification’ instances based on the input. I know…It’s next level and requires BPM craftsmanship with webservice calls but could be an interesting solution for your project!
Use your imagination and creativity!
A niceeeee “DONE” 😎 where we implemented a simple and efficient bell notification for the end-users when and ‘unread’ notification is waiting for action. It’s now all up to you to implement the extensions, so it can fit into your own solution. Have a happy crafting weekend, and I see you in a new post for next week…cheers!
Don’t forget to subscribe to get updates on the activities happening on this site. Have you noticed the quiz where you find out if you are also “The AppWorks guy”?