2

Comments icon hi-lite like Attachments.

In another post wrt hiliting the paper clip this code was advised:

if count(files(this)) != 0 then
html("
<style>
.i-light-grey.i-attachment {
background-color: #a9a9a9;
border-radius: 4px;
}
</style>
")
end

So - are there any boffins out there that can tweak this code snippet to do the same for the Comments icon that lives next to the paperclip?

Comments is such a handy feature but I suspect underutilised (apart from developers perhaps) for keeping notes for records.

23replies Oldest first
  • Oldest first
  • Newest first
  • Active threads
  • Popular
  • Realistically this is not that far away from toying with the attachment tab and one should be able to change the above script easily to reference the count to comments instead of files and accordingly change the ref in the colour line from attachments to comments- However Ninox claims it cannot define the function if this is tried.. From looking at previous posts re comments tab as a function to call it appears that it is on a wish list/do to ...

    Has me defeated at the moment 😥

    Like
    • Sean
    • Sean
    • 5 mths ago
    • Reported - view

    Without a function for comments like there is for file attachments - files(), I don't know how it would be possible using Ninox's built-in comment feature. It would be easy to duplicate the functionality by creating a child Comments table. You could put the child table information in a Tab and hide the built-in comment icon. Is that something you're interested in?

     

    I don't know why Ninox doesn't display attachment count and comment count next to the icons 🤷‍♂️. For what it's worth, I created a simple database, added some comments and downloaded the archive to my laptop. The comments are stored in a separate database file, but they are easy enough to parse and I don't see why a comment() function would be difficult to implement. If they simply displayed the number of comments next to the icon a function wouldn't be needed.

    Like 1
    • Alan Cooke
    • Alan_Cooke
    • 5 mths ago
    • Reported - view

    I agree - creating a comments table would be a solution and I have considered that.  Thing is one can add comments so easily randomly anywhere without any effort via that icon.  Pretty much a 'Post It' note.  So quick and easy....hopefully the idea will be implemented in time.

    Like 1
  • Yeah I do both colour the tab and tag the files count on most of my forms

    Like Sean's idea. A simple count next to the icon would be great - Even better if Ninox let you colour the tab just like you can with the other tabs

    Like 1
    • Mr. K.
    • Mr_K
    • 5 mths ago
    • Reported - view

    I cannot make this work. The paper clip is gray even when I have attachments. I have iCloud not Ninox cloud. Is that why, or am I suppose to change the code somewhat for my DB?

    Like
  • Good evening everyone,

    following an exchange with Alan I made this. It works well, but it uses JavaScript and could become unstable over time if Ninox changes its code.

    The first code proposed by Alan had several flaws:
    - It had to be added to every page and every tab on every page for it to work all the time.
    - The count(files()) usage returns the total number of files in the record, including those linked to image fields. The tab could is highlighted when there were no files in the list.

     

    For comments, the list, add, edit and delete functions exist and are accessible in JavaScript. They are just not linked to NinoxScript.

    Like
      • Sean
      • Sean
      • 5 mths ago
      • Reported - view

      Jacques TUR It's not just code in JavaScript that can become unstable if they change their code. The http() function for example. 😉

      Like
  • Here is the JavaScript code for the file attachments and comments badges

    The code must be placed in a formula. The display of the badges will start after the first execution of the code. It is therefore advisable to place the formula on the first page that is displayed in the application.

    html("
    <script>
        //style base of badges
        var badgeStyle = `
                        position: absolute;
                        display: flex;
                        top: 0px;
                        right: 0px;
                        background-color: red;
                        height: 15px;
                        line-height: 15px;
                        width: 15px;
                        text-align: center;
                        border-radius: 50%;
                        color: white;
                        justify-content: center;
                        font-size: smaller`;
        // color of selection
        var filesColor = '#4970ff';
        var oldCommentColor = '#999999';
        var newCommentColor = 'red';
        // Threshold of new or old comment in ms. For 1 day = 1000ms * 60s * 60mn * 24h = 86400000ms
        var oldCommentThreshold = 1000 * 60 * 60 * 24;
    
        //event function called when tab changeed or popup opened
        function editorTabChanged(e) {
            //recordver the current editor with links to html components
            var editor = ui.getCurrentEditor();
            if (editor && editor.container) {
                var container = editor.container;
    
                //call the original event fonction editorTabChanged
                Object.getPrototypeOf(container).oldeditorTabChanged(e);
    
                //load files of current record (is async function)
                database.loadFiles(container.nid, (e, i) => {
                    // e = error text
                    // i = files array of id record this.id
    
                    // recover the attached files icon on current editor
                    var files = ui.getCurrentEditor().files.elTab[0];
                    if (files) {
                        //recover or create the badge
                        var badge = files.getElementsByTagName('span')[0];
                        if (!badge) {
                            badge = document.createElement('span');
                            files.appendChild(badge);
                        }
    
                        //reading file list en exclude files connected to fields
                        var n = database.typeOf(container.nid);
                        var r = database.loadNodeSync(container.nid);
                        if (n && r) {
                            var s = {},
                                l = n.fields;
                            for (var c in l) {
                                if (l.hasOwnProperty(c))
                                    if ('file' === l[c].base) {
                                        var d = r[c];
                                        d && (s[d] = !0)
                                    }
                            }
                            let f = []
                            for (var u = 0; u < i.length; u++)
                                s[(d = i[u]).name] || f.push(d);
    
                            //number attached files
                            var cnt = f.length;
    
                            //set the badge
                            badge.style.cssText = badgeStyle;
                            badge.innerText = cnt.toString();
                            badge.style.visibility = (cnt > 0) ? 'visible' : 'hidden';
                            badge.style.backgroundColor = filesColor;
                        }
                    };
                });
    
                //load files of current record (is async function)
                database.loadComments(container.nid, (e, i) => {
                    // e = error text
                    // i = comments array of id record this.id
    
                    // recover the comment icon
                    var comments = editor.comments.elTab[0];
                    if (comments) {
    
                        //recover or create the badge
                        var badge = comments.getElementsByTagName('span')[0];
                        if (!badge) {
                            badge = document.createElement('span');
                            comments.appendChild(badge);
    
                        }
    
                        //get durrent time to compare with comment date
                        var ms = Date.now();
    
                        //count the number of new and old comments
                        var cntNew = i.reduce((total, el) => {
                            if (ms - el[0] < oldCommentThreshold) total += 1;
                            return total;
                        }, 0);
                        var cntAll = i.length;
    
                        //set the badge with different color to indicate if there is new comments
                        badge.style.cssText = badgeStyle;
                        badge.innerText = cntNew ? cntNew.toString() : cntAll.toString();
                        badge.style.visibility = (cntAll + cntNew > 0) ? 'visible' : 'hidden';
                        badge.style.backgroundColor = (cntNew > 0) ? newCommentColor : oldCommentColor;
    
                    };
                })
            }
    
        }
    
        // On first call, put this editorTabChanged in place to Ninox function and save the oldest
        var container = ui.getCurrentEditor().container;
        if (container && !Object.getPrototypeOf(container).oldeditorTabChanged) {
            Object.getPrototypeOf(container).oldeditorTabChanged = Object.getPrototypeOf(container).editorTabChanged;
            Object.getPrototypeOf(container).editorTabChanged = editorTabChanged;
        }
    
    </script>
    ")
    Like 3
      • Sean
      • Sean
      • 5 mths ago
      • Reported - view

      Jacques TUR Fantastic. I'm looking forward to studying this.

      Like
      • Alan Cooke
      • Alan_Cooke
      • 5 mths ago
      • Reported - view

      Sean It's such a treat to have this.  THANK YOU Jacques TUR 
       

      Like
    • Mr. K.
    • Mr_K
    • 5 mths ago
    • Reported - view

    I get this error. How do I fix it? Thanks.

    Like
    • Mr. K. Ninox seems to be trying to interpret the javascript. It is normally enclosed in quotes so that it is not interpreted by Ninox. I guess there must be one too many quotes in the code. 
      Can you copy and paste your code to me privately?

      Like
    • Sean
    • Sean
    • 5 mths ago
    • Reported - view

    I get the same error in the Mac app that Mr. K. got. When I run the code in the browser version, I don't see the badges.

     

    I copied the code using the forum copy button and I tried it using Safari, Firefox and Chrome.

    Like
      • Sean
      • Sean
      • 5 mths ago
      • Reported - view

      Sean I removed the .loadComments method from the editorTabChanged function for the Mac app code since there isn't a Comment tab in the Mac app. The error is gone, but still no badge for attachments.

      Like
    • Sean
    • Sean
    • 4 mths ago
    • Reported - view

    Just an update. I communicated with Jacques and he has a new version that works for me now and I hope that he posts the updated code since it is a great mod. I was also able to make it work in the Mac app for attachments.

    Like
  • Hello to all, 
    and thanks to Sean, Bruce and Alan who kindly did some testing that allowed me to stabilise the code.

    It is now functional on the web and on the Mac application. 

    var divId := "myDiv" + string(this.ID);
    html("
    <div id='" + divId + "'></div>
    <script>
        debugger;
        //create global object to manage badges.
        if (!window.badges) window.badges = {};
    
        //style base of badges
        badges.style = `
                position: absolute;
                display: flex;
                top: 0px;
                right: 0px;
                background-color: red;
                height: 15px;
                line-height: 15px;
                width: 15px;
                text-align: center;
                border-radius: 50%;
                color: white;
                justify-content: center;
                font-size: smaller`;
        // color of selection
        var filesColor = '#4970ff';
        var oldCommentColor = '#999999';
        var newCommentColor = 'red';
        // Threshold of new or old comment in ms. For 1 day = 1000ms * 60s * 60mn * 24h = 86400000ms
        var oldCommentThreshold = 1000 * 60 * 60 * 24;
    
        //event function called when tab changeed or popup opened
        function selectTab(e) {
            //call the original event fonction selectTab
            if (this.oldSelectTab) this.oldSelectTab(e);
            debugger;
            try {
                //recordver the current badges.editor with links to html components
                if (this.container) {
                    console.log('badges : files load')
                    //load files of current record (is async function)
                    database.loadFiles(this.container.nid, (e, i) => {
                        // e = error text
                        // i = files array of id record this.id
    
                        console.log('badges : files refresh')
    
                        // recover the attached files icon on current badges.editor
                        var files = this.files.elTab[0];
                        if (files) {
                            //recover or create the badge
                            var badge = files.getElementsByTagName('span')[0];
                            if (!badge) {
                                badge = document.createElement('span');
                                files.appendChild(badge);
                            }
    
                            //reading file list en exclude files connected to fields
                            var n = database.typeOf(this.container.nid);
                            var r = database.loadNodeSync(this.container.nid);
                            if (n && r) {
                                var s = {},
                                    l = n.fields;
                                for (var c in l) {
                                    if (l.hasOwnProperty(c))
                                        if ('file' === l[c].base) {
                                            var d = r[c];
                                            d && (s[d] = !0)
                                        }
                                }
                                let f = []
                                for (var u = 0; u < i.length; u++)
                                    s[(d = i[u]).name] || f.push(d);
    
                                //number attached files
                                var cnt = f.length;
    
                                //set the badge
                                badge.style.cssText = badges.style;
                                badge.innerText = cnt.toString();
                                badge.style.visibility = (cnt > 0) ? 'visible' : 'hidden';
                                badge.style.backgroundColor = filesColor;
                            }
                        };
                    });
    
                    // load the comment only for the web application.On the Mac application, comments do not exist
                    if (schemas.envConfig.userEnvName != 'mac') {
                        console.log('badges : comments load')
    
                        //load files of current record (is async function)
                        database.loadComments(this.container.nid, (e, i) => {
                            // e = error text
                            // i = comments array of id record this.id
    
                            console.log('badges : comments refresh')
    
                            // recover the comment icon
                            var comments = this.comments ? this.comments.elTab[0] : null;
                            if (comments) {
    
                                //recover or create the badge
                                var badge = comments.getElementsByTagName('span')[0];
                                if (!badge) {
                                    badge = document.createElement('span');
                                    comments.appendChild(badge);
    
                                }
    
                                //get durrent time to compare with comment date
                                var ms = Date.now();
    
                                //count the number of new and old comments
                                var cntNew = i.reduce((total, el) => {
                                    if (ms - el[0] < oldCommentThreshold) total += 1;
                                    return total;
                                }, 0);
                                var cntAll = i.length;
    
                                //set the badge with different color to indicate if there is new comments
                                badge.style.cssText = badges.style;
                                badge.innerText = cntNew ? cntNew.toString() : cntAll.toString();
                                badge.style.visibility = (cntAll + cntNew > 0) ? 'visible' : 'hidden';
                                badge.style.backgroundColor = (cntNew > 0) ? newCommentColor : oldCommentColor;
    
                            };
                        })
                    }
                }
    
            } catch (err) {
                console.log('badges error : ' + String(err.message));
            }
    
        }
    
        // On first call, put this selectTab in place to Ninox function and save the oldest
        function setHook() {
            try {
                //badges.editor = ui.getCurrentEditor();
                if (!badges.editor) {
                    debugger;
                    var div = document.getElementById('" + divId + "');
                    if (div) {
                        var data = $(div).closest('.component').data('component');
                        if (data) {
                            badges.editor = data.container;
                        }
                    }
    
                }
    
                if (badges.editor && badges.editor.container && !Object.getPrototypeOf(badges.editor).oldSelectTab) {
                    if (!Object.getPrototypeOf(badges.editor).oldSelectTab) {
                        Object.getPrototypeOf(badges.editor).oldSelectTab = Object.getPrototypeOf(badges.editor).selectTab;
                        Object.getPrototypeOf(badges.editor).selectTab = selectTab;
                        console.log('badges initalized');
    
                        badges.initalized = true;
                        badges.editor.selectTab(badges.editor.currentTab.id);
    
    
                        if (ui.getCurrentEditor() && ui.getCurrentEditor().currentTab)
                            ui.getCurrentEditor().selectTab(ui.getCurrentEditor().currentTab.id)
                    }
    
                }
                else if (!badges.editor)
                    setTimeout(setHook, 100);
            } catch (err) {
                alert('badges error : ' + String(err.message));
            }
        }
        setHook();
    
        if (badges.initalized) {
            var component = document.getElementById('" + divId + "');
            if (component)
                component.innerText = 'badges initalized';
        }
    
    </script>
    ")
    
    Like 2
      • Alan Cooke
      • Alan_Cooke
      • 4 mths ago
      • Reported - view

      Jacques TUR This is a brilliant script and makes what is normally an avoided feature (attachments and comments) a useful tool.

      Like
      • buy
      • buy
      • 2 mths ago
      • Reported - view

      Jacques TUR such a great and smart code....why did you exclude the Mac comments, i have eliminated the Config.userEnvName != 'mac' condition and it works well on the Mac app, the comments are visible.

      Like
    • buy I'm surprised, because on my Mac application, comments are not visible !?
      Only the attached files appear.

      Like
      • buy
      • buy
      • 2 mths ago
      • Reported - view

      Jacques TUR It looks like you have made your test on a local database, which is by nature, not having the comments feature. If you do open a Ninox cloud database, the mac app will then show you the comments.

      Like
    • buy Thanks very much!

      I don't use the Mac application and I didn't see that it was possible to connect to Ninox Cloud and have access to the comments. 

      I just corrected it. Now it checks if the comments are accessible, either from the application or the web cloud. I put this version 1.03 online.

      Like
  • Hi Jaques

    I had a way of listing the files count and colouring the paperclip icon, but of course like many others could not get at the comments area. 

    Your solution is neat and well executed and I have already taken advantage of it (noting that it might fall apart if Nixon do their thing on the software!)

    I'm on cloud version and it works a treat

    Very useful and practical !

    Like
    • Mel Charles Thank's 😊

      Like
Like2 Follow
  • 2 Likes
  • 2 mths agoLast active
  • 23Replies
  • 253Views
  • 10 Following