Accessing toast notifications from custom js functions

We are looking for a way to integrate with the UX toast notification system.

Notifications.message("info", "", "actual data is loading", !1)

The short term plan was to pop relevant notifications when a filter was mutated. We were going to embed this in the jsfunctions-filterbar.service.js. Before we head down this road I wanted to see if anyone has been successful doing something similar.

image

Hi @rdclapp ,

I did a small POC long time ago using the toast notifications.
The idea was to do a validation on the input numbers in the grid, It would pop a notification if the numbers entered were outside the range, and the number wouldn’t be input in the cube.
I used the Custom hook functions, beforeCellUpdate for this, likely you can do similar on the filterbar functions.
It worked great! :slight_smile:

3 Likes

Hi Rodrigo,
This is Hakan from SupplyFocus team. I saw your reply and checked the hook function “beforeCellUpdate” which is great but i need some directions to expand the usage. We would like to use your solution in Supplyfocus so is it possible to send me a sample code that you have created for the PoC or can we setup a meeting in anytime you are available to talk about this? Thank you, great job.

2 Likes

Hi @hakyuz,
Thanks! Sure, happy to help with what I have. I also had the help of Ilia @ishapiro on this one at the time.

Ok, below are the details, for anyone interested. :slight_smile:

The code was done in the file …\apq-c3-custom\js\custom-hook-functions.service.js

  1. First, add the Notifications to the Class for the custom hook functions:

  1. Create a function or use the same as existing “beforeCellUpdate” , the full code of the function, with some comments:
    Note in this code I have a 2 dim cube that I first get the allowed amount ranges, to then do the checks for each input.
    beforeCellUpdate(table, requests) {
        /** CUSTOM FUNCTION ADDED TO CHECK CELL INPUT BASED ON A VALID NUMBER, WARN IF NOT ALLOWED! */

        // this.$log.debug('beforeCellUpdate hook called', requests);
        // return Promise.resolve({});
        let currentRequestArrayIndexToRemove = [];
        let allowed_val;
        let allowed_val_min;


        // Get allowed amounts from cube
        return this.$tm1Ui.cellsetGet([{ instance: 'UX_Demo', cube: 'Sales Quota', cubeElements: ['Budget', 'Min Allowed'] }
            , { instance: 'UX_Demo', cube: 'Sales Quota', cubeElements: ['Budget', 'Max Allowed'] }]).then((val) => {
                allowed_val_min = val[0].Value
                allowed_val = val[1].Value

                console.log("VALUES ALLOWED: ", allowed_val_min, allowed_val);

                /** Check each entry if value is between range, flag otherwise  */ 
                requests.forEach((request, index) => {
                    let currentVal = (request.value + '').split(',').join('')
                    // console.log("value: " + currentVal);

                    if (Number(currentVal) < allowed_val_min || Number(currentVal) > allowed_val) {
                        currentRequestArrayIndexToRemove.push(true)
                    } else {
                        currentRequestArrayIndexToRemove.push(false)
                    }
                })

                /** For each flagged "wrong" input, remove it from request of cube update, and do notification */
                for (var i = currentRequestArrayIndexToRemove.length - 1; i >= 0; i--) {
                    if (currentRequestArrayIndexToRemove[i] === true) {
                        let input_val = requests[i].value;
                        //Remove value from request, so it does not update cube
                        requests.splice(i, 1);

                        this.Notifications.message("danger", "Input Validation", "Value '" + input_val + "' entered is Invalid, amount allowed is between " + allowed_val_min + " and " + allowed_val + "!", false)
                    }
                }
                if (requests.length === 0) {
                    this.$rootScope.$broadcast('updateTable', { "viewKey": table.key, tableId: table.tableId });
                }
                return Promise.resolve({ success: true });
            });
    }
  1. At the end of the custom hook functions file, add the “Notifications” to the list so it can return to the app and the notification works.

  2. Finally, in the UX report View or grid widget you want to do this check, add the function on the
    BeforeCellUpdate functions:

after that, when entering a number, it will do this check and do a notification if the value is out of the allowed range. It will work with 1 single entry or multiple ones, like below:

Hope this helps! let me know you need any more details or would like to setup a call for a chat on this. :slight_smile:

3 Likes

Amazing thanks. I will test this and let you know. :man_dancing:

1 Like

Awesome detailed explanation.:slight_smile:
For initial question @rdclapp you can implement the similar logic with in the jsfunctions-filterbar.service.js

2 Likes

I tried to make some modifications like below more then one row. But it still doesnt get the min and max values from each cell. instead it just takes the min and max values of first row as a reference. Is there anything i am missing?

// Get allowed amounts from cube
        return this.$tm1Ui.cellsetGet([{ instance: 'SupplyFocus_SOP', cube: 'Demand Plan Limit Measure', cubeElements: ['BUD', 'Min Allowed'] }
            , { instance: 'SupplyFocus_SOP', cube: 'Demand Plan Limit Measure', cubeElements: ['BUD', 'Max Allowed'] }
      		, { instance: 'SupplyFocus_SOP', cube: 'Demand Plan Limit Measure', cubeElements: ['FCST', 'Min Allowed'] }
      		, { instance: 'SupplyFocus_SOP', cube: 'Demand Plan Limit Measure', cubeElements: ['FCST', 'Max Allowed'] }
			, { instance: 'SupplyFocus_SOP', cube: 'Demand Plan Limit Measure', cubeElements: ['RFCST', 'Min Allowed'] }
			, { instance: 'SupplyFocus_SOP', cube: 'Demand Plan Limit Measure', cubeElements: ['RFCST', 'Max Allowed'] }]).then((val) => {
                allowed_val_min = val[0].Value
                allowed_val = val[1].Value

                console.log("VALUES ALLOWED: ", allowed_val_min, allowed_val);

                /** Check each entry if value is between range, flag otherwise  */ 
                requests.forEach((request, index) => {
                    let currentVal = (request.value + '').split(',').join('')
                    // console.log("value: " + currentVal);

                    if (Number(currentVal) < allowed_val_min || Number(currentVal) > allowed_val) {
                        currentRequestArrayIndexToRemove.push(true)
                    } else {
                        currentRequestArrayIndexToRemove.push(false)
                    }
                })

                /** For each flagged "wrong" input, remove it from request of cube update, and do notification */
                for (var i = currentRequestArrayIndexToRemove.length - 1; i >= 0; i--) {
                    if (currentRequestArrayIndexToRemove[i] === true) {
                        let input_val = requests[i].value;
                        //Remove value from request, so it does not update cube
                        requests.splice(i, 1);

Hi @hakyuz ,

You will have to get the Values from the Array “val”.
When you added the 6 references on the cellsetGet, they are all assigned to the array “val”, then you need to get the .Value to use, they will be in the same order as how you added in it, meaning the first, which starts from 0, is the BUD Min, the 1 is the BUD Max, 2 is the FCST Min, etc…

Note that on the “allowed_val_min” variable I have used “val[0].Value” to assign the value of the first result of the array to this variable (it starts from 0).

You can use this directly on your code or assign to variables to make it easier to identify, what you would need to do then is something like this:
First declare the variables in the beginning, using the “let”, before the return, then get each variable and assign the value from the array…

        let allowed_val_bud_min;
        let allowed_val_bud_max;
        let allowed_val_fcst_min;
        let allowed_val_fcst_max;
        let allowed_val_rfct_min;
        let allowed_val_rfct_max;
        return this.$tm1Ui.cellsetGet([{ instance: 'SupplyFocus_SOP', cube: 'Demand Plan Limit Measure', cubeElements: ['BUD', 'Min Allowed'] }
            , { instance: 'SupplyFocus_SOP', cube: 'Demand Plan Limit Measure', cubeElements: ['BUD', 'Max Allowed'] }
            , { instance: 'SupplyFocus_SOP', cube: 'Demand Plan Limit Measure', cubeElements: ['FCST', 'Min Allowed'] }
            , { instance: 'SupplyFocus_SOP', cube: 'Demand Plan Limit Measure', cubeElements: ['FCST', 'Max Allowed'] }
            , { instance: 'SupplyFocus_SOP', cube: 'Demand Plan Limit Measure', cubeElements: ['RFCST', 'Min Allowed'] }
            , { instance: 'SupplyFocus_SOP', cube: 'Demand Plan Limit Measure', cubeElements: ['RFCST', 'Max Allowed'] }]).then((val) => {
                allowed_val_bud_min = val[0].Value
                allowed_val_bud_max = val[1].Value
                allowed_val_fcst_min = val[2].Value
                allowed_val_fcst_max = val[3].Value
                allowed_val_rfct_min = val[4].Value
                allowed_val_rfct_max = val[5].Value

you can then use in a IF condition or however you need it.

Hope this helps! cheers!

oh just as a side note, in case you want to see what the code returns or try to debug whats happening, you can add anything to the the console.log and see in the browser when running the report in UX, this can be very helpful to try find things.
For example you can add the “val” in it and see the return:

console.log( val);

In my case, the array has only 2 values.
and If I expand the 0, I can see that it is my “Min” value that I want…