Scouts Membership System (UK) Tweaks

Provide a few tweaks including a role compliance report to the Scouts Website

当前为 2025-05-27 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Scouts Membership System (UK) Tweaks
// @description  Provide a few tweaks including a role compliance report to the Scouts Website
// @namespace    http://tampermonkey.net/
// @version      100000029
// @author       David Breakwell
// @match        https://membership.scouts.org.uk/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=scouts.org.uk
// @grant  GM_xmlhttpRequest
// @grant GM_getResourceURL
// @grant GM_getResourceText
// @grant GM_addStyle
// @grant GM_notification
// @grant GM_log
// @grant GM_setValue
// @grant GM_getValue
// @run-at      document-idle
// @require     http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @require     http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js
// @resource    jqUI_CSS  http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css
// @resource    IconSet1  http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/images/ui-icons_222222_256x240.png
// @resource    IconSet2  http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/images/ui-icons_454545_256x240.png
// @connect tsa-memportal-prod-fun01.azurewebsites.net
// @connect tsauksprodasa001.blob.core.windows.net
// @connect tsauksprodasa001.table.core.windows.net
// @license MIT
// ==/UserScript==

var code_version = "100000029";
var mem = [{}];
var mems= [];
var memsunique = [];
var roles = [];
var role_detail = [];
var dbs_detail = [];
var mem_learning= [];
var learn = [];
var mem_lcount;
var role_max_count;
var respond = false;
var end = false;
var un="";
var debug = false;
var keepalive = null;



var defcolors=['#fafad2','#ffe4b5','#ffa07a','#ff6347'];
var defcolorsT=['#000000','#000000','#000000','#000000'];
var colors=['#fafad2','#ffe4b5','#ffa07a','#ff6347'];
var colorsT=['#000000','#000000','#000000','#000000'];
var colormeanings = ["90 Days","60 Days","30 Days","Expired"];
var daylimits = [90,60,30,0,-99999];

(function() {
    'use strict';
    function do_move() {
        console.log(document.getElementById("member-nav").value);
    }
    function dopage() {
        //    if(window.location.href.indexOf("subunitsau")!=-1) {

        setTimeout(function() {
            console.log("After Wait");
            console.log(window.location.href );
            if ((window.location.href == "https://membership.scouts.org.uk/")||(window.location.href == "https://membership.scouts.org.uk/#/")) {
                console.log("Homepage");
                if (document.getElementById("member-nav-list")==null){
                    var gotolist="<datalist id='member-nav-list'><option value='Add a New Member'></option>";
                    gotolist+="<option value='My Units'></option>";
                    gotolist+="</datalist>";

                    gotolist ='<label for="member-nav" style="font-size: 1.5em;font-weight: 600">What do you want to do?&nbsp;</label>' + gotolist;
                    gotolist += '<input style="width: 50%; font-size: 1.5em "list="member-nav-list" id="member-nav" name="member-nav-choice" onchange="do_move"/>';
                    if( document.getElementById("title")!=null) {

                        if (document.getElementById("quick_nav")==null) {
                            gotolist = '<div id="quick_nav">'+gotolist+'</div>';
                            //      document.getElementById("title").outerHTML += (gotolist);

                        } else
                        {
                            //      document.getElementById("quick_nav").innerHTML = (gotolist);
                        }
                    } // title

                } // already dispalyed
            }
            if (window.location.href.indexOf("subunitsau") != -1) {
                //document.body.appendChild(button);
                var htmlToInsert;
                htmlToInsert = '<span id="DavesnewText"><p>There are <a href="';
                htmlToInsert += window.location.href.substring(0, window.location.href.indexOf("subunitsau"));
                htmlToInsert += 'teamsau"><span id="teamcounter"></span></a> Teams at this level</p><span><span id="DavesList"><span>';
                //console.log(document.getElementById("header-main-title-all-units-grid"));

                GM_xmlhttpRequest({
                    method: "POST",
                    url: "https://tsa-memportal-prod-fun01.azurewebsites.net/api/UnitTeamsAndRolesListingAsync",
                    data: '{"unitId" : "' + window.location.href.substring(window.location.href.indexOf("allunits/") + 9, window.location.href.indexOf("subunitsau") - 1) + '", "type" : "team"}',
                    headers: {
                        "Content-Type": "application/json",
                        "Authorization": "Bearer " + JSON.parse(localStorage.getItem("authInfo")).idToken,
                        "Accept": "application/json, text/plain, */*"
                    },
                    onload: function(response) {
                        //    console.log("gut response");
                        //    console.log(response.responseText);
                        //    console.log(JSON.parse(response.responseText));
                        if (JSON.parse(response.responseText).teams.length > 1) {
                            document.getElementById("teamcounter").innerHTML = JSON.parse(response.responseText).teams.length;
                        } else {
                            htmlToInsert = '<p>There is <a href="';
                            htmlToInsert += window.location.href.substring(0, window.location.href.indexOf("subunitsau"));
                            htmlToInsert += 'teamsau/' + JSON.parse(response.responseText).teams[0].teamId + "/teamdashboardaut";
                            htmlToInsert += '"><span id="teamcounter">1</span></a> Team at this level</p>';
                            document.getElementById("DavesnewText").innerHTML = (htmlToInsert);
                        }
                        var elements = document.querySelectorAll('[id^=grid-unit]');
                        var elements2 = document.querySelectorAll('[id^=grid-parentUnit]');
                        for (var loop = 0; loop < elements.length; loop++) {
                            var htmlToInsert2 = '<a href="';
                            htmlToInsert2 += elements[loop].href.substring(0, elements[loop].href.indexOf("subunitsau"));
                            htmlToInsert2 += 'teamsau">&nbsp;&nbsp;&nbsp;<strong style=" display: inline-block;  width: 40px; height: 40px;line-height: 40px;text-align: center; background-color: #007bff;  cursor:pointer; color: white; border-color: #007bff; border-radius: 50%;font-size: 20px;font-weight: bold;">T</strong></a>';
                            elements2[loop].outerHTML += htmlToInsert2;
                        }
                    }
                }); // End of request
                document.getElementById("header-main-title-all-units-grid").innerHTML += (htmlToInsert);
                var button = document.createElement("Button");
                button.innerHTML = "Add a Member";
                button.onclick = () => {

                    window.open(window.location.href.substring(0, window.location.href.indexOf("subunitsau")) + "unitdetailsau/addmemberau", "_self");
                };
                button.style = "background: rgb(0, 97, 205);font-weight: 700;font-family: 'Nunito Sans';font-size: 20px;line-height: 1.5;color: white;min-height: 46px;max-width: 215px; cursor:pointer;vertical-align: middle;padding: 8px 24px;border-color: #007bff;";
                document.getElementById("header-main-title-all-units-grid").appendChild(button);

            }
        })

        if (window.location.href.indexOf("teamdashboardaut") != -1) {
            setTimeout(function() {
                var button = document.createElement("Button");
                button.innerHTML = "Add a Member";
                button.onclick = () => {

                    window.open(window.location.href.substring(0, window.location.href.indexOf("teamsau")) + "unitdetailsau/addmemberau", "_self");
                };
                button.style = "background: rgb(0, 97, 205);font-weight: 700;font-family: 'Nunito Sans';font-size: 20px;line-height: 1.5;color: white;min-height: 46px;max-width: 215px;vertical-align: middle;padding: 8px 24px;border: none; cursor:pointer;";
                document.getElementById("header-button-wrapper-action-list").appendChild(button);
            }, 1000);
        }

    } // dopage

    function addButton(text, onclick, cssObj,pos) {
        if (pos=="T") {
            cssObj = cssObj || {position: 'absolute', top: '63px', left:'50%', 'z-index': 3}
        }
        if (pos=="B") {
            cssObj = cssObj || {position: 'absolute', top: '30px', left:'50%', 'z-index': 3}
        }
        let button = document.createElement('button'), btnStyle = button.style
        document.body.appendChild(button)
        button.innerHTML = text
        button.onclick = onclick
        btnStyle.position = 'absolute'
        Object.keys(cssObj).forEach(key => btnStyle[key] = cssObj[key])
        return button
    }
    function get_data(count){
        var datapass;
        var max = 50;
        un = document.getElementById("gmunitname").value;
        document.getElementById("gmUnit").innerHTML = un;
        $("#gmState")[0].innerText = "Requesting Members for "+un+" ("+count+")"+"Total read "+mems.length;
        if (debug) {GM_log("get_data :Version "+code_version);}
        if (debug) {GM_log("get_data : Collection for Report");}
        if (debug) {GM_log("Unit Request for "+un+" Count "+count);}
        if (debug) {
            GM_log("Unit Request for "+un+" :"+ JSON.parse(localStorage.getItem("authInfo")).idToken.substring(1,50));
            var tokexpDate = new Date( JSON.parse(localStorage.getItem("authInfo")).account.idTokenClaims.exp *1000);
            GM_log("Token expires :"+ tokexpDate.toGMTString());
        }
        //  document.getElementById("gmState").innerText = "Hello World";
        datapass = '{"pagesize":'+max+',"nexttoken":'+count+',"filter":{"global":"","globaland":false,"fieldand":true,"filterfields":[{"field":"unitName","value":"'+un+'"}]},"isSuspended":false}';
        //       console.log(datapass);
        if (debug) {GM_log("Counter for get_data "+count);}
        GM_xmlhttpRequest({
            method: "POST",
            context: count,
            url: "https://tsa-memportal-prod-fun01.azurewebsites.net/api/MemberListingAsync",
            data: datapass,
//            synchronous:    true,
            headers: {
                "Content-Type": "application/json",
                "Authorization": "Bearer " + JSON.parse(localStorage.getItem("authInfo")).idToken,
                "Accept": "application/json, text/plain, */*"
            },

            onload: function(response) { //  console.log(response);console.log(count);
                if (debug) {GM_log("Counter Recieved "+response.context)}
                // console.log(JSON.parse(response.responseText).data[1]);
                var mem = null;
                try { mem=JSON.parse(response.responseText).data} catch {console.log("JSON Error "+response.responseText);}
                //   mem =(JSON.parse(response.responseText).data);
                if (mem!=null) {
                    if (debug) {
                        for (var debugloop=0;debugloop<mem.length;debugloop++){
                            GM_log("Member "+mem[debugloop].firstname+" "+mem[debugloop].unitName+mem[debugloop].Role);
                        }
                    }
                }
                if ((mem==null)&&(debug)) {
                    GM_log("GetData: We got an error collecting data for mems page"+response.context);
                }
                if (mem!=null) {
                    mems = mems.concat(mem);
                }
                if (debug) {GM_log("mems now has length "+mems.length);}

                //      console.log(mem.length);
                //      console.log(JSON.parse(response.responseText).data);
                if (response.status!=200) {GM_log("HTTP error "+response.status); GM_log(JSON.stringify(response));}
                //     console.log(mem);
                //    console.log(JSON.parse(response.responseText).data.length);
                $("#gmState")[0].innerText = "Reading Members for "+un+" ("+response.context+") "+"Total read "+mems.length+"("+mem.length+")";
                if ( JSON.parse(response.responseText).data.length ==50) {get_data(count+1); } else {report2()};},
            onerror:   function(response) { GM_log("ON Error");GM_log(JSON.stringify(response))},
            onabort:  function(response) { GM_log("ON Abort");GM_log(JSON.stringify(response))}
        });

    }

    function clear_mems(){
        //if (1!=1){
        if (debug) {GM_log("Clear Mems entry: mems now has length "+mems.length);}
        if(document.getElementById("gmmissing").checked) {
            var onlymems = [];
            var act = ['managerDisclosureCheck','dataProtectionTrainingComplete','signDeclaration','updateMemberProfile','referenceRequest','safeguardconfidentialEnquiryCheck','managerWelcomeConversation','coreLearning','managerTrusteeCheck'];

            for (var i = 0; i < role_detail.length; i++) {
                var displine=true;

                if (document.getElementById("gmmissing").checked) {
                    var any_missing = false;
                    for (var j = 0; j < act.length; j++) {
                        if (role_detail[i].actions.find((element)=>element.typeid==act[j])) {
                            var value = role_detail[i].actions.find((element)=>element.typeid==act[j]).status;
                            if ((value!="Satisfactory")&&(value!="Completed")&&(value!="Held - Satisfactory")){ any_missing=true;}
                        }
                    }
                    if (any_missing==false) {displine=false}
                }
                if (displine) {
                    var memobj = new Object();
                    memobj = mems.find((element) => element.id == roles.find((element) => element.Id==role_detail[i].roleApprovalMemberShipId).ContactId);
                    onlymems.push(memobj);
                }
            }
            //roles.find((element) => element.Id==role_detail[i].roleApprovalMemberShipId).RoleName)
            // mems = mems.filter( function(v) {return v.id == onlymems.find((element)=>element.id== v.id)})
            mems = onlymems;
            if (debug) {GM_log("Clear Mems exit: mems now has length "+mems.length);}
        }
        //       }
        if (mems.length==0) { alert('The report will not be generated as your filters have resulted in no members being selected')}
    }


    function report2() {
        //  console.log(mem[1]);
        //      console.log(mems);

        if (debug) {GM_log("report2 : Collection for Report");}
        if (debug) {GM_log("report2 : Number of Members"+mems.length);}
        if (document.getElementById("gmwelcome").checked) {
            if (document.getElementById("gmhelper").checked) {
             mems = mems.filter( function(v) {return v.Role!="Non Member - Needs disclosure";})
               mems = mems.filter( function(v) {return v.Role!="Holding";})
            if (debug) {GM_log("Report 2: Remove Helpers roles now has length "+roles.length);}
        }

        }
        if (debug) {GM_log("mems now has length "+mems.length);}
         if (document.getElementById("gmteamname").value !=""){
                if (debug) {GM_log("Match team "+document.getElementById("gmteamname").value);}
                mems = mems.filter( function(v) {return v.Team.includes(document.getElementById("gmteamname").value);})
                if (debug) {GM_log("mems now has length "+mems.length);}

            }
        if (document.getElementById("gmpersonname").value !=""){
            if (debug) {GM_log("Match Names "+document.getElementById("gmpersonname").value);}
            mems = mems.filter( function(v) {return v.fullname.toLowerCase().includes(document.getElementById("gmpersonname").value.toLowerCase());})
            if (debug) {GM_log("mems now has length "+mems.length);}

        }
        if (mems.length==0) { alert('The report will not be generated as your filters have resulted in no members being selected')}
           if (debug) {GM_log("Check for Duplicates ");}
        var seen = {};
        var out = [];
        var len = mems.length;
        var j = 0;
        for(var i = 0; i < len; i++) {
            var item = mems[i];
            if(seen[item.id] !== 1) {
                seen[item.id] = 1;
                out[j++] = item;
            }
        }
         if (!document.getElementById("gmwelcome").checked) {
        mems = out;
         }
        memsunique = out;
        if (document.getElementById("gmwelcome").checked) {
            if (document.getElementById("gmhelper").checked) {
             mems = mems.filter( function(v) {return v.Role!="Non Member - Needs disclosure";})
               mems = mems.filter( function(v) {return v.Role!="Holding";})
            if (debug) {GM_log("Report 2: Remove Helpers roles now has length "+roles.length);}
        }
            mem_lcount = 0;
            clear_mems();
            report5()
        } else {



            if (mems.length==0) { alert('The report will not be generated as your filters have resulted in no members being selected')}
            $("#gmState")[0].innerText = "Number of Members "+mems.length;
            for(var loop = 0;loop<memsunique.length; loop++) {
                if (debug) {GM_log("Request Roles for "+loop+" "+memsunique[loop].firstname+" "+memsunique[loop].unitName);}

                GM_xmlhttpRequest({
                    method: "POST",
                    context: loop+1,
                    url: "https://tsa-memportal-prod-fun01.azurewebsites.net/api/GetMemberRolesAsync",
                    data: '{"contactId": "'+memsunique[loop].id+'"}',
                    headers: {
                        "Content-Type": "application/json",
                        "Authorization": "Bearer " + JSON.parse(localStorage.getItem("authInfo")).idToken,
                        "Accept": "application/json, text/plain, */*"
                    },
                    onload: function(response) {//console.log(response.context);
                        $("#gmState")[0].innerText = "Number of Members "+memsunique.length+" reading roles for number "+response.context;
                        //     console.log(mems.length);
                        if (response.status!=200) {GM_log("HTTP error "+response.status); GM_log(JSON.stringify(response));}
                        if (debug) {GM_log("Request Roles recieved for "+response.context+" "+memsunique[response.context-1].firstname+" "+memsunique[response.context-1].unitName);}
                        var jrole= null;
                        try { jrole=JSON.parse(response.responseText).data} catch {console.log("JSON Error "+response.responseText);}
                        if (jrole!=null) {
                            roles=roles.concat(jrole);
                        }
                        if ((jrole==null)&&(debug)) {
                            GM_log("GetData: We got an error collecting roles for member "+response.context+mems[response.context-1].firstname);
                        }
                        if (debug) {GM_log("Context "+response.context+" mems length"+mems.length+" roles length"+roles.length);}
                        // console.log(JSON.parse(response.responseText));
                        if (response.context-1==mems.length-1){console.log(roles);console.log(mems);report3();} },
                    onerror:   function(response) { GM_log("ON Error");GM_log(JSON.stringify(response))},
                    onabort:  function(response) { GM_log("ON Abort");GM_log(JSON.stringify(response))}
                });
            };
        }
    }


    function report3() {
        console.log(roles);
        if (debug) {GM_log("Report 3: mems now has length "+mems.length);}
        if (debug) {GM_log("Report 3: roles now has length "+roles.length);}
        if (document.getElementById("gmhelper").checked) {

            roles = roles.filter( function(v) {return !v.RoleName.includes("Non Member - Needs disclosure");})
            roles = roles.filter( function(v) {return !v.RoleName.includes("Holding");})
            if (debug) {GM_log("Report 3: Remove Helpers roles now has length "+roles.length);}
        }
        if (document.getElementById("gmclosed").checked) {
            roles = roles.filter( function(v) {return v.Closed});
            roles = roles.filter( function(v) {return v.EndDate==null});
            roles = roles.filter( function(v) {return !v.IsSecondaryLevel});
            if (debug) {GM_log("Report 3: Remove Closed roles now has length "+roles.length);}
            console.log(roles);

        }
        if (document.getElementById("gmteamname").value !=""){
            roles = roles.filter( function(v) {if( v.Team==null){return false} else {return v.Team.includes(document.getElementById("gmteamname").value);}})
            if (roles.length==0) { alert('There were no roles in Units matching the Unit Name maybe check you have a % at the end to get all the sub Units')}
            if (debug) {GM_log("Report 3: Filter by Team roles now has length "+roles.length);}
        }
        if (document.getElementById("gmteamonly").checked){
            var  filter = document.getElementById("gmunitname").value.replaceAll("%", "*");
            let w = filter.replace(/[.+^${}()|[\]\\]/g, '\\$&'); // regexp escape
            const re = new RegExp(`^${w.replace(/\*/g,'.*').replace(/\?/g,'.')}$`,'i');
            roles = roles.filter( function(v) {return re.test(v.UnitId)});
            if (debug) {GM_log("Report 3: Filter by for Unit only roles now has length "+roles.length);}
        }

        var xml = 0; var nullc=0;

        if (roles.length==0) { alert('The report will not be generated as your filters have resulted in no roles being selected')}

        for(var loop=0;loop<roles.length;loop++) {
            if (debug) {GM_log("Report 3: Roles Loop request for "+roles[loop].RoleName+" "+roles[loop].Team)+" "+loop;}
            //  console.log(roles[loop].EndDate);
            $("#gmState")[0].innerText = "Checking Role "+loop+" of "+roles.length;
            if ((roles[loop].EndDate==null)||(roles[loop].Status!=null)) {
                //   console.log("OK");
                role_max_count = loop;
                GM_xmlhttpRequest({
                    method: "POST",

                    context: loop+1,
                    url: "https://tsa-memportal-prod-fun01.azurewebsites.net/api/GenerateSASTokenAsync",
                    data: '{container: "contacts", permissions: "R", file: "'+roles[loop].ContactId+'/membership/'+roles[loop].Id+'/audit/data.json"}',
  //                  synchronous:    true,
                    headers: {
                        "Content-Type": "application/json",
                        "Authorization": "Bearer " + JSON.parse(localStorage.getItem("authInfo")).idToken,
                        "Accept": "application/json, text/plain, */*"
                    },
                    onload: function(response) {
                         if (debug) {GM_log("Report 3: Roles Blob request for "+response.context+" ")}
                        $("#gmState")[0].innerText = "Fetching Role "+response.context+" of "+roles.length;
                        GM_xmlhttpRequest({
                            method: "GET",
                            Accept: "application/json;odata=minimalmetadata",
                            context: response.context+1,
                            url: JSON.parse(response.responseText).token,

                            onload: function(response) { // console.log(response.responseText);
                                // console.log(JSON.parse(response.responseText));
                                // console.log("Total"+(role_detail.length + nullc + xml));
                                //  console.log("Aim"+(roles.length-1));
                                if (debug) {GM_log("Report 3: Roles Loop recieved for "+(response.context-1));}
                                if (response.status!=200) {GM_log("HTTP error "+response.status); GM_log(JSON.stringify(response));}
                                $("#gmState")[0].innerText = "Checking Role "+response.context;
                                if(!response.responseText.includes("xml")) { role_detail.push(JSON.parse(response.responseText));} else {xml++};
                                if (role_detail.length+nullc+xml>=roles.length){console.log(role_detail); mem_lcount = 0;clear_mems();report5()}},
                            onerror:   function(response) { GM_log("ON Error");GM_log(JSON.stringify(response))},
                            onabort:  function(response) { GM_log("ON Abort");GM_log(JSON.stringify(response))}

                        })

                    }
                });
            } else { nullc++}
        }
    }



    function report5() {

        if (document.getElementById("gmlearning").checked) {

            if (debug) {GM_log("Report 5: Get Learning for "+memsunique[mem_lcount].firstname+" "+memsunique[mem_lcount].Team)+" "+mem_lcount;}
            GM_xmlhttpRequest({
                method: "POST",

                url: "https://tsa-memportal-prod-fun01.azurewebsites.net/api/GetLmsDetailsAsync",
                data: '{"contactId": "'+memsunique[mem_lcount].id+'"}',
                context:  mem_lcount+1,
                headers: {
                    "Content-Type": "application/json",
                    "Authorization": "Bearer " + JSON.parse(localStorage.getItem("authInfo")).idToken,
                    "Accept": "application/json, text/plain, */*"
                },
                onload: function(response) {
                    $("#gmState")[0].innerText = "Number of Members "+memsunique.length+" reading learning for number "+mem_lcount;
                    if (debug) {GM_log("Report 5: Learning received for "+(response.context-1));}
                    var l = new Object;
                    l.id = memsunique[ mem_lcount].id;
                    l.learn = [];
                    try { l.learn=JSON.parse(response.responseText)} catch {console.log("JSON Error "+response.responseText);}
                    mem_learning[mem_lcount] = l;
                    // console.log(JSON.parse(response.responseText));
                    if ( mem_lcount==memsunique.length-1){console.log(mem_learning);report6();}else{ mem_lcount++;report5()}},
                onerror:   function(response) { GM_log("ON Error");GM_log(JSON.stringify(response))},
                onabort:  function(response) { GM_log("ON Abort");GM_log(JSON.stringify(response))}
            });

        } else {report6() }
    }

    function xmlToJson(xml) {
        // Create the return object
        var obj = {};

        if (xml.nodeType == 1) {
            // element
            // do attributes
            if (xml.attributes.length > 0) {
                obj["@attributes"] = {};
                for (var j = 0; j < xml.attributes.length; j++) {
                    var attribute = xml.attributes.item(j);
                    obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
                }
            }
        } else if (xml.nodeType == 3) {
            // text
            obj = xml.nodeValue;
        }

        // do children
        // If all text nodes inside, get concatenated text from them.
        var textNodes = [].slice.call(xml.childNodes).filter(function(node) {
            return node.nodeType === 3;
        });
        if (xml.hasChildNodes() && xml.childNodes.length === textNodes.length) {
            obj = [].slice.call(xml.childNodes).reduce(function(text, node) {
                return text + node.nodeValue;
            }, "");
        } else if (xml.hasChildNodes()) {
            for (var i = 0; i < xml.childNodes.length; i++) {
                var item = xml.childNodes.item(i);
                var nodeName = item.nodeName;
                //  if (nodeName=="m:properties") {nodeName = "m_properties"}
                if (nodeName[1]==":") {nodeName = nodeName.replace(":", "_")};
                if (typeof obj[nodeName] == "undefined") {
                    obj[nodeName] = xmlToJson(item);
                } else {
                    if (typeof obj[nodeName].push == "undefined") {
                        var old = obj[nodeName];
                        obj[nodeName] = [];
                        obj[nodeName].push(old);
                    }
                    obj[nodeName].push(xmlToJson(item));
                }
            }
        }
        return obj;
    }

    function report6() {
        var xmlURL ="";
        var xml = 0; var nullc=0;

        if (document.getElementById("gmdbs").checked) {

            for(var loop=0;loop<memsunique.length;loop++) {
                if (debug) {GM_log("Report 6: DBS requested for "+loop+" "+memsunique[loop].firstname);}
                //  console.log(roles[loop].EndDate);
                $("#gmState")[0].innerText = "Checking Disclosure "+loop+" of "+memsunique.length;
                GM_xmlhttpRequest({
                    method: "POST",
                    context: loop+1,
                    url: "https://tsa-memportal-prod-fun01.azurewebsites.net/api/GenerateSASTokenAsync",
                    data: '{"table": "Disclosures", "permissions": "R", "partitionkey" : "'+memsunique[loop].id+'"}',
                    synchronous:    true,
                    headers: {
                        "Content-Type": "application/json",
                        "Type" : "table",
                        "accept-language" : "en-GB,en;q=0.9",
                        "sec-fetch-site" : "cross-site",
                        "Origin" : "https://membership.scouts.org.uk",
                        "content-encoding" : "gzip",
                        "Authorization": "Bearer " + JSON.parse(localStorage.getItem("authInfo")).idToken,
                        "Accept": "application/json, text/plain, */*"
                    },
                    onload: function(response) {
                        xmlURL = "";
                        if (debug) {GM_log("Report 6: DBS Blob URL Received for "+(response.context-1)+" "+memsunique[response.context-1].firstname);}
                        try { xmlURL =  JSON.parse(response.responseText) } catch {console.log(response.responseText)};
                        if (xmlURL=="") { if (debug) {GM_log("Report 6: DBS Blob URL JSON Error " +response.responseText);} }
                        if (xmlURL!="") {
                            $("#gmState")[0].innerText = "Fetching DBS "+response.context+" of "+memsunique.length;
                            GM_xmlhttpRequest({
                                method: "GET",
                                context: response.context,
                                url: JSON.parse(response.responseText).token,

                                onload: function(response) {
                                    if (debug) {GM_log("Report 6: DBS received for "+(response.context-1)+" "+memsunique[response.context-1].firstname);}
                                    if (response.status!=200) {GM_log("HTTP error "+response.status); GM_log(JSON.stringify(response));}
                                    $("#gmState")[0].innerText = "Checking DBS "+response.context;
                                    if(response.responseText.includes("xml")) { var XmlNode = new DOMParser().parseFromString(response.responseText, 'text/xml');
                                                                               var dbsxml = xmlToJson(XmlNode); dbsxml.id = memsunique[response.context-1].id;
                                                                               dbsxml.firstname = memsunique[response.context-1].firstname;
                                                                               dbs_detail.push(dbsxml);} else {xml++};
                                    if (dbs_detail.length+xml>=memsunique.length){console.log(dbs_detail); report4()}},
                                onerror:   function(response) { GM_log("ON Error");GM_log(JSON.stringify(response))},
                                onabort:  function(response) { GM_log("ON Abort");GM_log(JSON.stringify(response))}

                            }) } else {xml++; if (dbs_detail.length+xml>=memsunique.length){console.log(dbs_detail); report4()}}

                    }
                });

            }
        } else {report4()}

    }

    function report_headers(table) {
        var expirytext = "Expiry";
        var expirytextdays = "Expiry Days";
        var act = ['managerDisclosureCheck','dataProtectionTrainingComplete','signDeclaration','updateMemberProfile','referenceRequest','safeguardconfidentialEnquiryCheck','managerWelcomeConversation','coreLearning','managerTrusteeCheck'];
        var title = ['Role','Unit','Team','Name','Number','Status','Start Date','Days','Disclosure','GDPR','Declaration','Profile','References','CE Check','Welcome','Learning','Trustee'];
        var learn = ['Creating Inclusion','Data Protection in Scouts','Who We Are and What We Do','Safeguarding','Safety','First Response','Delivering a Great Programme','Being a Trustee in Scouts','Leading Scout Volunteers'];
        var tr = document.createElement('TR');
        table.appendChild(tr);

        for (var i=0; i<title.length;i++){
            var td = document.createElement('TD');

            if (i>7) { td.style.writingMode = "vertical-lr"; td.style.backgroundColor='lightcyan';}
            //  td.style.writingmode = 'vertical-lr';
            td.appendChild(document.createTextNode(title[i]));
            var visible = true;
            if ((i>4)&&(document.getElementById("gmwelcome").checked)){visible=false};
            if ((i==4)&&(!document.getElementById("gmnumber").checked)){visible=false};
            if (visible) { tr.appendChild(td); }
        }

        if (document.getElementById("gmlearning").checked) {
            for ( i=0; i<learn.length;i++){
                td = document.createElement('TD');
                td.style.writingMode = "vertical-lr";
                td.style.backgroundColor = 'LightGray';
                td.appendChild(document.createTextNode(learn[i]));
                tr.appendChild(td);
                if (((i==3)||(i==4)||(i==5))&&(document.getElementById("gmdates").checked)) {
                    td = document.createElement('TD');
                    td.style.writingMode = "vertical-lr";
                    td.style.backgroundColor = 'LightGray';
                    td.appendChild(document.createTextNode(learn[i]+" "+expirytext));
                    tr.appendChild(td);
                }
                if (((i==3)||(i==4)||(i==5))&&(document.getElementById("gmdays").checked)) {
                    td = document.createElement('TD');
                    td.style.writingMode = "vertical-lr";
                    td.style.backgroundColor = 'LightGray';
                    td.appendChild(document.createTextNode(learn[i]+" "+expirytextdays));
                    tr.appendChild(td);
                }
            }
        }
        if (document.getElementById("gmdbs").checked) {
            td = document.createElement('TD');
            td.style.backgroundColor = 'LightGray';
            td.appendChild(document.createTextNode("DBS Expiry"));

            tr.appendChild(td);
            td = document.createElement('TD');
            td.style.writingMode = "vertical-lr";
            td.style.backgroundColor = 'LightGray';
            td.appendChild(document.createTextNode("DBS Days Remaining"));

            tr.appendChild(td);
             if (document.getElementById("gmdbsip").checked){
                             td = document.createElement('TD');
            td.style.backgroundColor = 'LightGray';
            td.appendChild(document.createTextNode("DBS Status"));

            tr.appendChild(td);
             }
        }
    }


    function report4() {
        if (debug) {GM_log("Report 4 : Data Collected - generate report ");}
        if (debug) {GM_log("Report 4 : Roles Detail "+role_detail.length);}
        if (debug) {GM_log("Report 4 : Mems  "+mems.length);}
        if (debug) {GM_log("Report 4 : Roles  "+roles.length);}
        if (debug) {GM_log("Report 4 : Learning  "+mem_learning.length);}
        if (debug) {GM_log("Report 4 : DBS  "+ dbs_detail.length);}
        var expirytext = "Expiry";
        var expirytextdays = "Expiry Days";
        var act = ['managerDisclosureCheck','dataProtectionTrainingComplete','signDeclaration','updateMemberProfile','referenceRequest','safeguardconfidentialEnquiryCheck','managerWelcomeConversation','coreLearning','managerTrusteeCheck'];
        var title = ['Role','Unit','Team','Name','Status','Start Date','Days','Disclosure','GDPR','Declaration','Profile','References','CE Check','Welcome','Learning','Trustee'];
        var learn = ['Creating Inclusion','Data Protection in Scouts','Who We Are and What We Do','Safeguarding','Safety','First Response','Delivering a Great Programme','Being a Trustee in Scouts','Leading Scout Volunteers'];

        $("#gmState")[0].innerText = "Data Collection Completed";
        var myTableDiv = document.getElementById("gmTable");
        var table = document.createElement('TABLE');
        table.border = '1';
        table.id = "GMourreport";
        var tableBody = document.createElement('TBODY');
        table.appendChild(tableBody);
        var tr = document.createElement('TR');
        tableBody.appendChild(tr);
        report_headers(tableBody);

        if (!(document.getElementById("gmwelcome").checked)) {
            for (i = 0; i < role_detail.length; i++) {
                var displine=true;

                if (document.getElementById("gmmissing").checked) {
                    var any_missing = false;
                    for (var j = 0; j < act.length; j++) {
                        if (role_detail[i].actions.find((element)=>element.typeid==act[j])) {
                            var value = role_detail[i].actions.find((element)=>element.typeid==act[j]).status;
                            if ((value!="Satisfactory")&&(value!="Completed")&&(value!="Held - Satisfactory")){ any_missing=true;}
                        }
                    }
                    if (any_missing==false) {displine=false}
                }
                if (displine) {
              //      tr = document.createElement('TR');
              //      tableBody.appendChild(tr);

                    output_report_line(tableBody,i,mems.findIndex( (element) => element.id == roles.find( (element) => element.Id == role_detail[i].roleApprovalMemberShipId).ContactId));

                }
            }
        }
        else
        {
            for (var i = 0; i < mems.length; i++) {
                if (mems[i].Role!=null) {
                output_report_line(tableBody,-1,i);
                }
            }
        }
        table.style.fontSize = "10pt";
        document.getElementById("gmTable").innerHTML="";
        myTableDiv.appendChild(table);



    }

    // *****************************************************************
    /// This is used for the refresh but no new data
    /// *****************************************************************
    function output_report_line(table,role_index,mem_index) {
        var act = ['managerDisclosureCheck','dataProtectionTrainingComplete','signDeclaration','updateMemberProfile','referenceRequest','safeguardconfidentialEnquiryCheck','managerWelcomeConversation','coreLearning','managerTrusteeCheck'];
        var title = ['Role','Unit','Team','Name','Status','Start Date','Days','Disclosure','GDPR','Declaration','Profile','References','CE Check','Welcome','Learning','Trustee'];
        var learn = ['Creating Inclusion','Data Protection in Scouts','Who We Are and What We Do','Safeguarding','Safety','First Response','Delivering a Great Programme','Being a Trustee in Scouts','Leading Scout Volunteers'];

        var tr = document.createElement('TR');
        table.appendChild(tr);
        // Name
        if (role_index>=0) {
            var td = document.createElement('TD');
            td.appendChild(document.createTextNode(roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).RoleName));
            tr.appendChild(td);
            td = document.createElement('TD');
            td.appendChild(document.createTextNode(roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).UnitId));
            tr.appendChild(td);
            td = document.createElement('TD');
            td.appendChild(document.createTextNode(roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).Team));
            tr.appendChild(td);
        } else
        {
            td = document.createElement('TD');
            td.appendChild(document.createTextNode(mems[mem_index].Role));
            tr.appendChild(td);
            td = document.createElement('TD');
            td.appendChild(document.createTextNode(mems[mem_index].unitName));
            tr.appendChild(td);
            td = document.createElement('TD');
            td.appendChild(document.createTextNode(mems[mem_index].Team));
            tr.appendChild(td);
        }
        td = document.createElement('TD');
        var fullname = mems[mem_index].fullname;
        //  var nameid = mems.find((element) => element.id == roles.find((element) => element.Id==role_detail[i].roleApprovalMemberShipId).ContactId).id;
        var nameid = mems[mem_index].id;
        var memhtml = '<a href="https://membership.scouts.org.uk/#/membersearch/'+nameid+'/viewmember" target="_blank">'+fullname+'</a>';
        tr.appendChild(td);
        td.innerHTML=(memhtml);
        if (document.getElementById("gmnumber").checked) {
        td = document.createElement('TD');
        td.appendChild(document.createTextNode(mems[mem_index].membershipnumber));
        tr.appendChild(td);
        };
        if (role_index>=0) {

            // Role
            td = document.createElement('TD');
            td.appendChild(document.createTextNode(role_detail[role_index].rolestatus));
            tr.appendChild(td);
            td = document.createElement('TD');
            var sdate = new Date(roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).StartDate);
            td.appendChild(document.createTextNode(sdate.toLocaleDateString('en-GB')));
            var days  = Math.round((new Date() - sdate) / (1000 * 60 * 60 * 24));
            tr.appendChild(td);

            td = document.createElement('TD');
            td.appendChild(document.createTextNode(days));
            tr.appendChild(td);

            for (var j = 0; j < act.length; j++) {
                td = document.createElement('TD');
                //   td.width = '75';
                if (role_detail[role_index].actions.find((element)=>element.typeid==act[j])) {

                    var state= 0x274C;
                    var value = role_detail[role_index].actions.find((element)=>element.typeid==act[j]).status;
                    if ((value=="Satisfactory")||(value=="Completed")||(value=="Held - Satisfactory")){state= 0x2705;}

                    //  td.appendChild(document.createTextNode(role_detail[i].actions.find((element)=>element.typeid==act[j]).status+String.fromCodePoint(state)));
                    td.appendChild(document.createTextNode(String.fromCodePoint(state)));

                    //   td.appendChild(document.createTextNode(String.fromCodePoint(state)));
                } else {td.appendChild(document.createTextNode(" "))}
                td.style.backgroundColor='lightcyan';
                tr.appendChild(td);
            }
        } else {

        }
        // Learning

        if (document.getElementById("gmlearning").checked) {
            for ( j = 0; j < learn.length; j++) {
                td = document.createElement('TD');
                state= 0x274C;
                var lr = mem_learning.find((element) => element.id == mems[mem_index].id);
                if (lr.learn.find((object)=>object.title==learn[j])){
                    state= 0x2705;
                }
                // Check Expiry x26A1
                if (lr.learn.find((object)=>object.title==learn[j])){
                    if (lr.learn.find( (object) => object.title == learn[j]).expiryDate !=null) {
                        sdate = new Date(lr.learn.find((object)=>object.title==learn[j]).expiryDate);
                        days  = Math.round((sdate - new Date()) / (1000 * 60 * 60 * 24));
                        if (days<=90) {state = 0x26A1;
                                      }
                    }
                } else {days=0;sdate = new Date("1000-01-01T00:00:01Z") ;}
                if (role_index>0) {
                    if (j==7) {
                        // Trustee
                        if ((!roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).RoleName.includes('Lead Volunteer'))&&(roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).RoleName!='Trustee')) {

                            if(state==0x2705) {
                                state=0x2714;}
                            else {
                                state = 0x0020;
                            }
                        }
                    }
                    if (j==8) {
                        // Team Lead
                        if ((roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).RoleName.includes('Lead Volunteer'))||(roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).RoleName=='Team Leader')&&((roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).UnitType!='Group Section')&&(roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).UnitType!='District Section'))) {

                        } else {if(state==0x2705) {
                            state=0x2714;}
                                else {
                                    state = 0x0020;
                                }}
                    }
                    if (j==8) {
                        // Team Lead
                        if ((roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).ParentTeamId==null)) {

                        } else {if((state==0x2705)||(state == 0x2714)) {
                            state=0x2714;}
                                else {
                                    state = 0x0020;
                                }}
                    }
                    if (j==6) {
                        // programme - only section roles
                        if ((roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).UnitType!='Group Section')&&(roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).UnitType!='District Section')) {
                            if(state==0x2705) {
                                state=0x2714;}
                            else {
                                state = 0x0020;
                            }
                        }
                    }
                    if (j==5) {
                        // First Response
                        if ((roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).UnitType=='Group Section')||(roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).UnitType=='District Section')||(roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).RoleName=='Group Lead Volunteer')||((roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).RoleName=='Team Leader'))&&(roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).Team=='14-24 Team')) {

                        } else { if(state==0x2705) {
                            state=0x2714;}
                                else {
                                    state = 0x0020;
                                } }
                    }
                    // Check for those not needing training
                    var rn = roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).RoleName;
                    if ((rn=='Non Member - Needs disclosure')||(rn=='President')||(rn=='Vice President')||(rn=='Holding')||(rn=='Retired Member')) {
                        if ((state == 0x26A1)||(state == 0x2705)||(state == 0x2714)) {
                            state=0x2714;}
                        else {
                            state = 0x0020;
                        }
                    }

                } else {

                    if ((j==7)&&(mems[mem_index].Role!=null)) {
                        // Trustee
                        if ((!mems[mem_index].Role.includes('Lead Volunteer'))&&(mems[mem_index].RoleName!='Trustee')) {

                            if(state==0x2705) {
                                state=0x2714;}
                            else {
                                state = 0x0020;
                            }
                        }
                    }
                    if ((j==8)&&(mems[mem_index].Role!=null)) {
                        // Team Lead
                        if ((mems[mem_index].Role.includes('Lead Volunteer'))||(mems[mem_index].Role=='Team Leader')&&((mems[mem_index].unittype!='Group Section')&&(mems[mem_index].unittype!='District Section'))) {

                        } else {if(state==0x2705) {
                            state=0x2714;}
                                else {
                                    state = 0x0020;
                                }}
                    }
                    if (j==8) {
                        var mainteams = ['Leadership Team','Volunteering Development Team','Support Team','Programme Team','14-24 Team'];
                        // Team Lead for Sub teams
                        if (mainteams.find((element)=>element==mems[mem_index].Team!=undefined)
) {

                        } else {if((state==0x2705)||(state == 0x2714)) {
                            state=0x2714;}
                                else {
                                    state = 0x0020;
                                }}
                    }
                    if (j==6) {
                        // programme - only section roles
                        if ((mems[mem_index].unittype!='Group Section')&&(mems[mem_index].unittype!='District Section')) {
                            if(state==0x2705) {
                                state=0x2714;}
                            else {
                                state = 0x0020;
                            }
                        }
                    }
                    if ((j==5)&&(mems[mem_index].Role!=null)) {
                        // First Response
                        if ((mems[mem_index].unittype=='Group Section')||(mems[mem_index].unittype=='District Section')||(mems[mem_index].Role=='Group Lead Volunteer')||((mems[mem_index].Role=='Team Leader'))&&(mems[mem_index].Team=='14-24 Team')) {

                        } else { if(state==0x2705) {
                            state=0x2714;}
                                else {
                                    state = 0x0020;
                                } }
                    }
                    // Check for those not needing training
                    rn = mems[mem_index].Role;
                    if (rn!=null) {
                    if ((rn=='Non Member - Needs disclosure')||(rn=='President')||(rn=='Vice President')||(rn=='Holding')||(rn=='Retired Member')) {
                        if ((state == 0x26A1)||(state == 0x2705)||(state == 0x2714)) {
                            state=0x2714;}
                        else {
                            state = 0x0020;
                        }
                    }
                    }

                }
                td.appendChild(document.createTextNode(String.fromCodePoint(state)));
                td.style.backgroundColor = 'LightGray';
                tr.appendChild(td);

                if ((document.getElementById("gmdates").checked)&&((j==3)||(j==4)||(j==5))) {
                    td = document.createElement('TD');
                    if (lr.learn.find( (object) => object.title == learn[j])) {
                        if (sdate!= new Date("1000-01-01T00:00:01Z")) {
                            td.style.backgroundColor = 'LightGray';
                            if (( state != 0x0020)&&(document.getElementById("gmcolor").checked)){
                            for(var cloop=0;cloop<4;cloop++) {
                            if ((days<=daylimits[cloop])&&(days>daylimits[cloop+1])) {
                                 td.style.backgroundColor = colors[cloop];
                                 td.style.textColor = colorsT[cloop];
                    }}}
                            td.appendChild(document.createTextNode(sdate.toLocaleDateString('en-GB')));
                        }
                    } else {
                        if (( state != 0x0020)&&(document.getElementById("gmcolor").checked)){
                            for(cloop=0;cloop<4;cloop++) {
                            if ((days<=daylimits[cloop])&&(days>daylimits[cloop+1])) {
                                 td.style.backgroundColor = colors[cloop];
                                 td.style.textColor = colorsT[cloop];
                    }}}
                    }
                   
                    tr.appendChild(td);
                }
                if (((j==3)||(j==4)||(j==5))&&(document.getElementById("gmdays").checked)) {
                    td = document.createElement('TD');
                    td.style.backgroundColor = 'LightGray';
                    if (!document.getElementById("gmwelcome").checked) {
                        if ((j!=3)||(((roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).UnitType=='Group Section')||(roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).UnitType=='District Section')||(roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).RoleName=='Group Lead Volunteer')||((roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).RoleName=='Team Leader'))&&(roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).Team=='14-24 Team'))&&j==3)) {

                            if (sdate!= new Date("1000-01-01T00:00:01Z")) {
                                td.appendChild(document.createTextNode(days));

                            }
                        }
                    } else {  if (sdate!= new Date("1000-01-01T00:00:01Z")) {
                        td.appendChild(document.createTextNode(days));

                    }}
                     if (( state != 0x0020)&&(document.getElementById("gmcolor").checked)){
                     for(cloop=0;cloop<4;cloop++) {
                            if ((days<=daylimits[cloop])&&(days>daylimits[cloop+1])) {
                                 td.style.backgroundColor = colors[cloop];
                                 td.style.textColor = colorsT[cloop];
                    }}}
                    tr.appendChild(td);
                }

            }
        }
        if (document.getElementById("gmdbs").checked) {
            if (role_index>=0) {
                rn = roles.find((element) => element.Id==role_detail[role_index].roleApprovalMemberShipId).RoleName;
            } else { rn=mems[mem_index].Role;}
            if ((rn=='President')||(rn=='Vice President')||(rn=='Holding')||(rn=='Retired Member')) {
                // No DBS Needed
                td = document.createElement('TD');
                tr.appendChild(td);
                td = document.createElement('TD');
                tr.appendChild(td);

            } else {
                var mindex = dbs_detail.findIndex((element)=> element.id == mems[mem_index].id)
                if (mindex>=0) {
                    var time = new Date("1000-01-01T00:00:01Z") ;
                    var timel = new Date("1000-01-01T00:00:01Z") ;
                    var dbs_status = "";
                    if (dbs_detail[mindex].feed.entry != undefined) {
                     if ( dbs_detail[mindex].feed.entry.length != undefined ) {
                    for(var dbsloop=0;dbsloop<dbs_detail[mindex].feed.entry.length;dbsloop++) {
                        sdate = new Date(dbs_detail[mindex].feed.entry[dbsloop].content.m_properties.d_ExpiryDate);
                        if (sdate>time) { time = sdate;}
                         sdate = new Date(dbs_detail[mindex].feed.entry[dbsloop].content.m_properties.d_IssuedDate);
                         if (sdate>timel) { timel = sdate;dbs_status=dbs_detail[mindex].feed.entry[dbsloop].content.m_properties.d_Status; if (dbs_status!="Disclosure issued"){dbs_status+=" "+timel.toLocaleDateString('en-GB')}}
                    }
                     }
                    if (dbs_detail[mindex].feed.entry.length == undefined) {
                        // Single DBS
                        sdate = new Date(dbs_detail[mindex].feed.entry.content.m_properties.d_ExpiryDate);
                        if (sdate>time) { time = sdate;}
                        sdate = new Date(dbs_detail[mindex].feed.entry.content.m_properties.d_DateModified);
                         dbs_status=dbs_detail[mindex].feed.entry.content.m_properties.d_Status;
                         if (dbs_status!="Disclosure issued"){dbs_status+=" "+sdate.toLocaleDateString('en-GB')}
                    }
                    }
                    td = document.createElement('TD');
                    var dbsdatedisp = time.toLocaleDateString('en-GB');
                    if (time<new Date()) {dbsdatedisp=String.fromCodePoint(0x274C)};
                    var expdays  = Math.round((time-new Date()) / (1000 * 60 * 60 * 24));
                    if ((expdays<=90)&&(expdays>0)) {dbsdatedisp+=String.fromCodePoint(0x26A1)}
                    if ((document.getElementById("gmcolor").checked)){
                            for(cloop=0;cloop<4;cloop++) {
                            if ((expdays<=daylimits[cloop])&&(expdays>daylimits[cloop+1])) {
                                 td.style.backgroundColor = colors[cloop];
                                 td.style.textColor = colorsT[cloop];
                    }}}
                    td.appendChild(document.createTextNode(dbsdatedisp));

                    tr.appendChild(td);
                    td = document.createElement('TD');
                    if ((document.getElementById("gmcolor").checked)){
                            for(cloop=0;cloop<4;cloop++) {
                            if ((expdays<=daylimits[cloop])&&(expdays>daylimits[cloop+1])) {
                                 td.style.backgroundColor = colors[cloop];
                                 td.style.textColor = colorsT[cloop];
                    }}}
                    if(expdays>0) {
                    td.appendChild(document.createTextNode(expdays));
                    }
                    tr.appendChild(td);
                     if (document.getElementById("gmdbsip").checked){
                    td = document.createElement('TD');
                    td.appendChild(document.createTextNode(dbs_status));
                    tr.appendChild(td);
                }
                } else {td = document.createElement('TD');td.appendChild(document.createTextNode(String.fromCodePoint(0x274C))); tr.appendChild(td);td = document.createElement('TD');tr.appendChild(td);
                        if (document.getElementById("gmdbsip").checked) { td = document.createElement('TD');tr.appendChild(td); }
                       }
            }
        }
    }











    function report_filter() {
        var expirytext = "Expiry";
        var expirytextdays = "Expiry Days";
        var act = ['managerDisclosureCheck','dataProtectionTrainingComplete','signDeclaration','updateMemberProfile','referenceRequest','safeguardconfidentialEnquiryCheck','managerWelcomeConversation','coreLearning','managerTrusteeCheck'];
        var title = ['Role','Unit','Team','Name','Status','Start Date','Days','Disclosure','GDPR','Declaration','Profile','References','CE Check','Welcome','Learning','Trustee'];
        var learn = ['Creating Inclusion','Data Protection in Scouts','Who We Are and What We Do','Safeguarding','Safety','First Response','Delivering a Great Programme','Being a Trustee in Scouts','Leading Scout Volunteers'];
        $("#gmState")[0].innerText = "Data Collection Completed";
        var myTableDiv = document.getElementById("gmTable");
        var table = document.createElement('TABLE');
        table.border = '1';
        table.id = "GMourreport";
        var tableBody = document.createElement('TBODY');
        table.appendChild(tableBody);
        var tr = document.createElement('TR');
        tableBody.appendChild(tr);
        report_headers(tableBody);

        if (!(document.getElementById("gmwelcome").checked)) {
            for (i = 0; i < role_detail.length; i++) {
                var displine=true;

                if (document.getElementById("gmmissing").checked) {
                    var any_missing = false;
                    for (var j = 0; j < act.length; j++) {
                        if (role_detail[i].actions.find((element)=>element.typeid==act[j])) {
                            var value = role_detail[i].actions.find((element)=>element.typeid==act[j]).status;
                            if ((value!="Satisfactory")&&(value!="Completed")&&(value!="Held - Satisfactory")){ any_missing=true;}
                        }
                    }
                    if (any_missing==false) {displine=false}
                }
                //
                if (document.getElementById("gmteamonly").checked) {
                    var  filter = document.getElementById("gmunitname").value.replaceAll("%", "*");
                    let w = filter.replace(/[.+^${}()|[\]\\]/g, '\\$&'); // regexp escape
                    const re = new RegExp(`^${w.replace(/\*/g,'.*').replace(/\?/g,'.')}$`,'i');
                    if(!re.test(roles.find((element) => element.Id==role_detail[i].roleApprovalMemberShipId).UnitId)){displine=false}
                }

                if (mems.find((element) => element.id == roles.find((element) => element.Id==role_detail[i].roleApprovalMemberShipId).ContactId)!=undefined){

                    var fullname = mems.find((element) => element.id == roles.find((element) => element.Id==role_detail[i].roleApprovalMemberShipId).ContactId).fullname;
                    if (document.getElementById("gmpersonname").value!="") {
                        if(!fullname.toLowerCase().includes(document.getElementById("gmpersonname").value.toLowerCase())){displine=false}
                    }
                } else {displine=false;}

                if (document.getElementById("gmteamname").value!="") {
                    if (!roles.find((element) => element.Id==role_detail[i].roleApprovalMemberShipId).Team.toLowerCase().includes(document.getElementById("gmteamname").value.toLowerCase())){displine=false}
                }

                if (document.getElementById("gmhelper").checked) {
                    var rolename = roles.find((element) => element.Id==role_detail[i].roleApprovalMemberShipId).RoleName;
                    if (rolename.includes("Non Member - Needs disclosure")) {displine=false;}
                    if (rolename.includes("Holding")) {displine=false;}
                }
                if (displine) {
                    output_report_line(tableBody,i,mems.findIndex( (element) => element.id == roles.find( (element) => element.Id == role_detail[i].roleApprovalMemberShipId).ContactId));

                }
            }
        }
        else
        {
            for (var i = 0; i < mems.length; i++) {
                  displine = true;
                  fullname = mems[i].fullname;
                    if (document.getElementById("gmpersonname").value!="") {
                        if(!fullname.toLowerCase().includes(document.getElementById("gmpersonname").value.toLowerCase())){displine=false}
                    }
                if (mems[i].Role==null) { displine=false}
                if (displine) {
                output_report_line(tableBody,-1,i);
                }
            }
        }
        table.style.fontSize = "10pt";
        document.getElementById("gmTable").innerHTML="";
        myTableDiv.appendChild(table);


        //var tf = new TableFilter('GMourreport',filtersConfig );
        //t
    }



    function report_onclick() {
        // RUn Report
        //     console.log("Report");
        if   (document.getElementById("gmdebug").checked) {
            debug = true;
        }
        var count = 1;
        mem="";
        //  $("#gmpopup").dialog ( {modal: true, height: 500, width: "100%"} );
        mems = [];
        role_detail=[];
        roles=[];
        document.getElementById("gmTable").innerHTML="Table will appear here....";
        //   document.getElementById("gmUnit").innerHTML = "UKJDKJD";
        var responsetext = "";
        var datapass;
        mem_learning= [];
        learn = [];
        dbs_detail=[];
        var tokexpDate = new Date( JSON.parse(localStorage.getItem("authInfo")).account.idTokenClaims.exp *1000);

   /*     var clicked = GM_notification({
            text: "The logon cookie will expire at "+tokexpDate.toGMTString(),
            title: "Logon Cookie Expiry",
            url: 'https:/example.com/',
            onclick: (event) => {
                //The userscript is still running, so don't open example.com
                event.preventDefault();
                // Display an alert message instead
                //    alert('I was clicked!')
            }
        }); */
        get_data(count);

    }

    function report_onclick2() {
        // Open Dialog
        console.log("Report");
        var count = 1;
        mem="";
        var h = $( window ).height();
        $("#gmpopup").dialog ( {modal: true, height: (h*0.75), width: "100%"} );
        mems = [];
        role_detail=[];
        roles=[];
        memsunique=[];
        //   document.getElementById("gmTable").innerHTML="Table will appear here....";
        var responsetext = "";
        var datapass;
        mem_learning= [];
        keepalive = window.setInterval(function () {
        if (window.location.href=='https://membership.scouts.org.uk/#/learning') {
        var ul = document.getElementById('menu-list-item-left-nav-homePageTile');
            ul.click();
        }
        else {
            ul = document.getElementById('menu-list-item-left-nav-learning');
            ul.click();
        }

            console.log("Keep Alive Active");
}, 25000);  //5000 is 5 Seconds
 $('#gmpopup').on('dialogclose', function(event) {
    // alert('closed');
     clearInterval(keepalive);
     console.log("Keep Alive Cancelled");
 });

    }

    function report_print() {

        var prtContent = document.getElementById("GMourreport");
        var WinPrint = window.open('', '', 'left=0,top=0,width=800,height=900,toolbar=0,scrollbars=0,status=0');
        WinPrint.document.write(prtContent.outerHTML);
        WinPrint.document.close();
        WinPrint.focus();
        WinPrint.print();
        WinPrint.close();
    }

    function savecolors() {
          GM_setValue("colors", JSON.stringify(colors));
         GM_setValue("colorsT", JSON.stringify(colorsT));
    }
     function resetcolors() {
         colors = defcolors;
         colorsT = defcolorsT;
         for(cloop=0; cloop<colors.length;cloop++){
                document.getElementById("cpreview"+cloop).style.backgroundColor = colors[cloop];
                document.getElementById("cpreview"+cloop).style.color = colorsT[cloop];
                document.getElementById("back"+cloop).value = colors[cloop];
               document.getElementById("fore"+cloop).value = colorsT[cloop];
         }

    }
    function updateFirstC(event) {
        console.log("Update First");
        if (event.target.name.includes("back")) {
            document.getElementById("cpreview"+event.target.name[4]).style.backgroundColor = event.target.value;
            colors[event.target.name[4]] = event.target.value;
        }
        if (event.target.name.includes("fore")) {
            document.getElementById("cpreview"+event.target.name[4]).style.color = event.target.value;
            colorsT[event.target.name[4]] = event.target.value;
        }

        console.log(event);
    }

    function watchColorPicker(event) {
        console.log("Watch CP");
        console.log(event);
    }

    function clear_cookies() {
        var cookies = document.cookie.split("; ");
        for (var c = 0; c < cookies.length; c++) {
            var d = window.location.hostname.split(".");
            while (d.length > 0) {
                var cookieBase = encodeURIComponent(cookies[c].split(";")[0].split("=")[0]) + '=; expires=Thu, 01-Jan-1970 00:00:01 GMT; domain=' + d.join('.') + ' ;path=';
                var p = location.pathname.split('/');
                document.cookie = cookieBase + '/';
                while (p.length > 0) {
                    document.cookie = cookieBase + p.join('/');
                    p.pop();
                };
                d.shift();
            }
        }
    }

    function report_download() {
        /* var location = 'data:application/vnd.ms-excel;base64,';
	var excelTemplate = '<html> ' +
		'<head> ' +
		'<meta http-equiv="content-type" content="text/plain; charset=UTF-8"/> ' +
		'</head> ' +
		'<body> ' +
		document.getElementById("GMourreport").innerHTML +
		'</body> ' +
		'</html>'
	window.location.href = location + window.btoa(unescape(encodeURIComponent(excelTemplate)));*/
        const clipboardItem = new ClipboardItem({
            'text/html': new Blob([document.getElementById("GMourreport").outerHTML], { type: 'text/html' }),
            'text/plain': new Blob([document.getElementById("GMourreport").innerText], { type: 'text/plain' })
        });
        navigator.clipboard.write([clipboardItem]);
    }
    // Navigation Watcher
/*
    navigation.addEventListener("navigate", e => {
        console.log("EventLstener");
        console.log(e);

        if (document.getElementById("quick_nav")!=null){console.log("remove");document.getElementById("quick_nav").innerHTML ="";}

        setTimeout(function() {

        }, 2000);

    }) // Event listener
*/
 /*   setTimeout(function() {
        console.log("New Page");
        //    dopage(); Deactive Unit/Teams
    }, 2000);
 */
    // Your code here...
    var newHTML         = document.createElement ('div');
    // <p>Exclude Welcome Information <input  type="checkbox" id="gmexc" name="gmtexc" /><p> \
    //<p><input   type="checkbox" id="gmtraffic" name="gmtraffic" /> Show 90 Day Traffic LIghts  \
    newHTML.innerHTML   = '             \
<div id="gmpopup" title="Roles Report">   \
<p>      \
Unit <input   type="text" id="gmunitname" size=30 name="gmunitname"  placeholder="Enter Unit Name (% =wildcard)"/>  <button id="gmRunReport">Run Report</button> <button id="gmFilterReport">Apply New Filters</button></p> \
<p>Include Roles for matching Unit Only <input  type="checkbox" id="gmteamonly" name="gmteamonly" /><p> \
<p>Name Filter <input   type="text" id="gmpersonname" name="gmpersonname" /> Team Filter <input   type="text" id="gmteamname" name="gmteamname" /><p> \
<input   type="checkbox" id="gmmissing" name="gmmissing" /> Show volunteers missing  Welcome elements only \
<p><input   type="checkbox" id="gmwelcome" name="gmwelcome" /> Exclude Role Audit</p> \
<p> <input   type="checkbox" id="gmhelper" name="gmhelper" /> Exclude Helpers/Holding Roles <input   type="checkbox" id="gmclosed" name="gmclosed" checked/> Exclude Closed Roles <p> \
<p><input   type="checkbox" id="gmlearning" name="gmlearning" /> Show Detailed learning  \
<input   type="checkbox" id="gmdates" name="gmdates" /> Show Expiry Dates \
<input   type="checkbox" id="gmdays" name="gmdays" /> Show Days to Expiry </p> \
<p><input   type="checkbox" id="gmdbs" name="gmdbs" /> Show DBS Information <input   type="checkbox" id="gmdbsip" name="gmdbsip" /> Show DBS Status</p>  \
<p><input   type="checkbox" id="gmnumber" name="gmnumber" /> Show Membership Number<input   type="checkbox" id="gmcolor" name="gmcolor" /> Use Colour</p>\
<strongb>Run Status : </strong> <span id="gmState">Enter Unit Name above (can include % wildcard) and run report</span>  \
<p>Showing All Roles for members of <span id="gmUnit"></span></p>       \
<span id="gmTablex"><button id="gmXLS">Copy to Clipboard</button></span>  \
<span id="gmTablep"><button id="gmPrint">Print</button></span>  \
<span id="gmTable">Report will appear here!</span>  \
<p><input   type="checkbox" id="gmdebug" name="gmdebug" /> Debug Info - usually this should be off</p> \
<p><button id="gmsavecolors">Save Colors</button> <button id="gmresetcolors">Reset Colors</button></p> \
<div id="htmlset" style=""></div> \
</div> ';
    // Add Color Selectors
    document.body.appendChild (newHTML);
    var colors_JSON = GM_getValue("colors", JSON.stringify(defcolors));
    var colorsT_JSON = GM_getValue("colorsT", JSON.stringify(defcolorsT));
    colors = JSON.parse(colors_JSON);
     colorsT = JSON.parse(colorsT_JSON);
    var  HTMLSettings         = document.createElement ('div');
    for (var cloop=0;cloop<4;cloop+=1){
        HTMLSettings.innerHTML   += '<p><span style="display: inline-block; width :75px">'+colormeanings[cloop]+'</span> '+'<input type="color" id="back'+cloop+'" name="back'+cloop+'" value="'+colors[cloop]+'" />'+'<span> <input type="color" id="fore'+cloop+'" name="fore'+cloop+'" value="'+colorsT[cloop]+'" /></span>   <span id="cpreview'+cloop+'">1000</span></p>';
    }
    document.getElementById("htmlset").appendChild (HTMLSettings);
    for (cloop=0;cloop<4;cloop+=1){
        document.getElementById("back"+cloop).addEventListener("input", updateFirstC, false);
        document.getElementById("back"+cloop).addEventListener("change", watchColorPicker, false);
        document.getElementById("fore"+cloop).addEventListener("input", updateFirstC, false);
        document.getElementById("fore"+cloop).addEventListener("change", watchColorPicker, false);
        document.getElementById("cpreview"+cloop).style.backgroundColor = colors[cloop];
        document.getElementById("cpreview"+cloop).style.color = colorsT[cloop];
        document.getElementById("cpreview"+cloop).style.padding = "10px";
    }
    $("#gmpopup").hide();
    var iconSet1    = GM_getResourceURL ("IconSet1");
    var iconSet2    = GM_getResourceURL ("IconSet2");
    var jqUI_CssSrc = GM_getResourceText ("jqUI_CSS");

    jqUI_CssSrc     = jqUI_CssSrc.replace (/url\(images\/ui\-bg_.*00\.png\)/g, "");
    jqUI_CssSrc     = jqUI_CssSrc.replace (/images\/ui-icons_222222_256x240\.png/g, iconSet1);
    jqUI_CssSrc     = jqUI_CssSrc.replace (/images\/ui-icons_454545_256x240\.png/g, iconSet2);
    //  var testing = GM_info();
    GM_addStyle (jqUI_CssSrc);

    addButton("Role Report", report_onclick2, "","T");
    addButton("Clear Cookies", clear_cookies,"", "B");
    document.getElementById("gmRunReport").onclick = report_onclick;
    document.getElementById("gmFilterReport").onclick = report_filter;
    document.getElementById("gmsavecolors").onclick = savecolors;
    document.getElementById("gmresetcolors").onclick = resetcolors;
    document.getElementById("gmXLS").onclick = report_download;
    document.getElementById("gmPrint").onclick = report_print;
    document.getElementById("gmunitname").value = un;
    document.getElementById("gmpopup").style.fontSize = "10pt";
    var blkrs = GM_info.script.options.override.use_blockers;
    if (blkrs.length>0) {
        var clicked = GM_notification({
            text: "There maybe an issue with your XHR blacklist this may stop things running - check the plugin settings",
            title: "Scout Membership Plugin",
            url: 'https:/example.com/',
            onclick: (event) => {
                //The userscript is still running, so don't open example.com
                event.preventDefault();
                // Display an alert message instead
                //    alert('I was clicked!')
            }
        });
    }



})();