MiGerritPlus

some extention for miui gerrit

// ==UserScript==
// @name         MiGerritPlus
// @namespace    thbeliefNameSpace
// @icon         https://cnbj1.fds.api.xiaomi.com/info-app-webfile/common-resource/ico/favicon.ico
// @version      2.0.0
// @description  some extention for miui gerrit
// @author       thbelief
// @match        *://gerrit.pt.mioffice.cn/*
// @match        *://corgi.pt.miui.com/*
// @require      https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js
// @resource css2 https://www.layuicdn.com/layui-v2.5.6/css/layui.css
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @grant        GM_deleteValue
// @grant        GM_xmlhttpRequest
// @grant        GM_notification
// @grant        GM_setClipboard
// @grant        GM_addStyle
// @grant        GM_getResourceText
// @grant        GM_getResourceURL
// @grant        GM_openInTab
// @grant        GM.setValue
// @grant        GM.getValue
// @grant        GM.registerMenuCommand
// @grant        GM.deleteValue
// @grant        GM.xmlHttpRequest
// @grant        GM.notification
// @grant        GM.setClipboard
// @grant        unsafeWindow
// @run-at       document-end
// @license      AGPL

// ==/UserScript==
(function () {
    'use strict'

    // code region start

    /**
     * some config
     */
    var TAG = "MiGerritPlus"
    // control is print log
    var isDebug = false
    var dashBoardSelf = "https://gerrit.pt.mioffice.cn/dashboard/self"
    var gerritTask = "https://corgi.pt.miui.com/build/tiny/task?copyId="
    var intervalTime = 150
    var checkboxInsertIndex = 3
    // need hide group array
    var hideGroupArray = new Array("Your Turn", "Incoming reviews", "CCed on", "Recently closed")

    print("origin start")
    toastr().info("welcome to use " + TAG)
    loadCss()
    loadLayui()
    // cur url
    var curHerf = window.location.href
    // reload because not success sometimes
    var isNeedReloadMain = false
    // save checkbox and change
    var selectChangeMap = new Map()
    // main header buttons
    var buttonArray = new Array(getCopyButton(), getPackagingButton(), getPackagingSettingsButton(), getResetButton())
    // settings config table
    var configs = new Array()
    const TABLE_DATA = "TABLE_DATA"
    if (GM_getValue(TABLE_DATA) != null) {
        configs = GM_getValue(TABLE_DATA)
    }
    const PACKAGE_CHANGE_ID = "changeIds"

    window.onload = function () {
        var changeIds = GM_getValue(PACKAGE_CHANGE_ID)
        sleep(300).then(() => {
            if (changeIds != null) {
                GM_setValue(PACKAGE_CHANGE_ID, null)
                if (curHerf.indexOf(gerritTask) !== -1) {
                    var badData = document.body.querySelectorAll('.del-btn')
                    for (var i = 0; i < badData.length; i++) {
                        badData[i].click()
                    }
                    var insertButton = document.body.querySelector('.insert-btn')
                    var inputChangeId = insertButton.parentNode.parentNode.querySelector('input')
                    var taskName = '';
                    for (var change of changeIds) {
                        taskName += change['name'] + " "
                        tryInput(change['id'], inputChangeId)
                        insertButton.click()
                    }
                    var go = document.body.querySelector('.bottom-btn-box').querySelector('button')
                    go.click()
                    sleep(300).then(() => {
                        var dialog = document.body.querySelector(".el-dialog")
                        var dialogInput = dialog.querySelector('input')
                        dialogInput.value = taskName
                        dialog.querySelectorAll('button')[2].click()
                        window.location.href = "about:blank"
                        window.close()
                    })
                }
            }
        });
        main()
    }
    /**
     * History and window.hashchange is not role
     * so use interval
     */
    setInterval(function () {
        if (curHerf != window.location.href || isNeedReloadMain) {
            isNeedReloadMain = false;
            curHerf = window.location.href
            print("cur url = " + curHerf)
            if (curHerf != dashBoardSelf) {
                for (var i = 0; i < buttonArray.length; i++) {
                    buttonArray[i].remove()
                }
                print("Not dashBoardSelf.Remove button")
            }
            main()
        }
    }, intervalTime);

    function sleep(time) {
        return new Promise((resolve) => setTimeout(resolve, time));
    }
    function tryInput(text, tempInput) {
        var evt = new InputEvent('input', {
            inputType: 'insertText',
            data: text,
            dataTransfer: null,
            isComposing: false
        });
        tempInput.value = text;
        tempInput.dispatchEvent(evt);
    }
    function loadCss() {
        var css = ".toast-title{font-weight:bold}.toast-message{-ms-word-wrap:break-word;word-wrap:break-word}.toast-message a,.toast-message label{color:#fff}.toast-message a:hover{color:#ccc;text-decoration:none}.toast-close-button{position:relative;right:-0.3em;top:-0.3em;float:right;font-size:20px;font-weight:bold;color:#fff;-webkit-text-shadow:0 1px 0 #fff;text-shadow:0 1px 0 #fff;opacity:.8;-ms-filter:alpha(opacity=80);filter:alpha(opacity=80)}.toast-close-button:hover,.toast-close-button:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;-ms-filter:alpha(opacity=40);filter:alpha(opacity=40)}button.toast-close-button{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.toast-top-center{top:0;right:0;width:100%}.toast-bottom-center{bottom:0;right:0;width:100%}.toast-top-full-width{top:0;right:0;width:100%}.toast-bottom-full-width{bottom:0;right:0;width:100%}.toast-top-left{top:12px;left:12px}.toast-top-right{top:12px;right:12px}.toast-bottom-right{right:12px;bottom:12px}.toast-bottom-left{bottom:12px;left:12px}#toast-container{position:fixed;z-index:999999}#toast-container *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}#toast-container>div{position:relative;overflow:hidden;margin:0 0 6px;padding:15px 15px 15px 50px;width:300px;-moz-border-radius:3px 3px 3px 3px;-webkit-border-radius:3px 3px 3px 3px;border-radius:3px 3px 3px 3px;background-position:15px center;background-repeat:no-repeat;-moz-box-shadow:0 0 12px #999;-webkit-box-shadow:0 0 12px #999;box-shadow:0 0 12px #999;color:#fff;opacity:.8;-ms-filter:alpha(opacity=80);filter:alpha(opacity=80)}#toast-container>:hover{-moz-box-shadow:0 0 12px #000;-webkit-box-shadow:0 0 12px #000;box-shadow:0 0 12px #000;opacity:1;-ms-filter:alpha(opacity=100);filter:alpha(opacity=100);cursor:pointer}#toast-container.toast-top-center>div,#toast-container.toast-bottom-center>div{width:300px;margin:auto}#toast-container.toast-top-full-width>div,#toast-container.toast-bottom-full-width>div{width:96%;margin:auto}.toast{background-color:#030303}.toast-success{background-color:#51a351}.toast-error{background-color:#bd362f}.toast-info{background-color:#2f96b4}.toast-warning{background-color:#f89406}.toast-progress{position:absolute;left:0;bottom:0;height:4px;background-color:#000;opacity:.4;-ms-filter:alpha(opacity=40);filter:alpha(opacity=40)}@media all and (max-width:240px){#toast-container>div{padding:8px 8px 8px 50px;width:11em}#toast-container .toast-close-button{right:-0.2em;top:-0.2em}}@media all and (min-width:241px) and (max-width:480px){#toast-container>div{padding:8px 8px 8px 50px;width:18em}#toast-container .toast-close-button{right:-0.2em;top:-0.2em}}@media all and (min-width:481px) and (max-width:768px){#toast-container>div{padding:15px 15px 15px 50px;width:25em}}"
        GM_addStyle(css)
    }
    function loadLayui() {
        var jsUrl = "https://www.layuicdn.com/layui-v2.5.6/layui.all.js"
        var cssUrl = "https://www.layuicdn.com/layui-v2.5.6/css/layui.css"
        var link = document.createElement("link")
        link.setAttribute("ref", "stylesheet")
        link.setAttribute("type", "text/css")
        link.setAttribute("href", cssUrl)
        document.head.appendChild(link)
        var script = document.createElement("script")
        script.setAttribute("src", jsUrl)
        document.body.appendChild(script)
        var css2 = GM_getResourceText("css2")
        GM_addStyle(css2)

    }
    function print(content) {
        if (!isDebug) {
            return;
        }
        console.log(TAG + ": " + content)
    }
    function packageTask() {
        toastr().info("test")
    }
    function main() {
        if (curHerf !== dashBoardSelf) {
            return
        }
        print("main")
        var rootDom = document.body.querySelector("gr-app").shadowRoot.getElementById("app-element").shadowRoot.getRootNode();
        var mainHeader = rootDom.querySelector("gr-main-header").shadowRoot.getRootNode()
        // insert copy button
        insertClipIcon(mainHeader.querySelector(".links"))
        // remove footer
        var footerDom = rootDom.querySelector("footer")
        if (footerDom != null) {
            print("remove footer")
            footerDom.remove()
        }
        var mainDom = rootDom.querySelector("main")
        if (mainDom === null) {
            print("main is null")
            return
        }
        var changeDom = mainDom.querySelector("gr-dashboard-view")
        if (changeDom === null) {
            isNeedReloadMain = true
            return
        }
        var changeList = changeDom.shadowRoot.getRootNode().querySelector("gr-change-list").shadowRoot.getRootNode().querySelectorAll("gr-change-list-section")
        // cardArray is per change card
        var cardArray = new Array()
        for (var i = 0; i < changeList.length; i++) {
            cardArray[i] = changeList[i].shadowRoot.getRootNode()
        }
        if (cardArray.length === 0) {
            toastr().warning("operate fail.try to retry")
            isNeedReloadMain = true
        }
        print("cardArray = " + cardArray)
        for (var i = 0; i < cardArray.length; i++) {
            var curGroupDom = cardArray[i].querySelector(".section-name")
            var groupHeaderDom = cardArray[i].querySelector(".groupHeader")
            // hide which need to hide group
            if (curGroupDom != null && hideGroupArray.includes(curGroupDom.innerText)) {
                print("remove " + curGroupDom.innerText)
                if (groupHeaderDom !== null) {
                    groupHeaderDom.remove()
                }
                var groupContentDom = cardArray[i].querySelector(".groupContent")
                if (groupContentDom !== null) {
                    groupContentDom.remove()
                }
                // remove noChanges item
                var noChangesDom = cardArray[i].querySelector(".noChanges")
                if (noChangesDom !== null) {
                    noChangesDom.remove()
                }
                // remove group title
                if (i != 0) {
                    var groupTitleDom = cardArray[i].querySelector(".groupTitle")
                    if (groupTitleDom !== null) {
                        groupTitleDom.remove()
                    }
                }
            }
            var groupContentDom = cardArray[i].querySelector(".groupContent")
            if (groupContentDom !== null) {
                var groupTitleDom = groupContentDom.querySelector(".groupTitle")
                if (groupTitleDom.querySelectorAll(".subject").length <= 1) {
                    insertCheckBoxTitle(groupTitleDom)
                    var list = groupContentDom.querySelectorAll("gr-change-list-item")
                    insertCheckBox(list)
                }
            }
        }
        toastr().success("operate success")
    }
    /**
     * insert checkbox title
     * @param list 
     */
    function insertCheckBoxTitle(groupTitle) {
        var tdList = groupTitle.querySelectorAll("td")
        groupTitle.insertBefore(createCheckBoxTitle(), tdList[checkboxInsertIndex])
    }
    /**
     * create checkbox title
     * @returns 
     */
    function createCheckBoxTitle() {
        var td = document.createElement("td")
        td.className = "subject"
        td.innerText = "Select"
        return td
    }
    /**
     * insert checkbox to every change
     * @param {*} list 
     */
    function insertCheckBox(list) {
        for (var i = 0; i < list.length; i++) {
            var tdList = list[i].shadowRoot.getRootNode().querySelectorAll("td")
            var cellNumberNode = list[i].shadowRoot.getRootNode().querySelector(".number")
            var titleNode = list[i].shadowRoot.getRootNode().querySelector(".content")
            var repoNode = list[i].shadowRoot.getRootNode().querySelector(".fullRepo")
            var branchNode = list[i].shadowRoot.getRootNode().querySelector(".branch")
            const change = new Change(cellNumberNode.querySelector("a").innerText, titleNode.innerText, cellNumberNode.querySelector("a").href, repoNode.innerText, branchNode.querySelector("a").innerText)
            list[i].shadowRoot.getRootNode().insertBefore(createCheckBox(change), tdList[checkboxInsertIndex])
        }
    }
    /**
     * create checkbox
     * @param {*} change 
     * @returns 
     */
    function createCheckBox(change) {
        var td = document.createElement("td")
        var input = document.createElement("input")
        input.type = "checkbox"
        input.setAttribute("style", "width:20px;height:20px;")
        input.onclick = function () {
            selectChangeMap.get(this).setIsChecked(this.checked)
            //console.log(selectChangeMap.get(this))
        }
        td.setAttribute("display", "table-cell")
        td.setAttribute("vertical-align", "middle")
        td.setAttribute("white-space", "nowrap")
        td.setAttribute("style", "padding-top:5px;padding-bottom:5px;padding-left:10px;padding-right:10px;")
        td.appendChild(input)
        selectChangeMap.set(input, change)
        return td
    }
    /**
     * insert copy button
     * @param {*} links 
     */
    function insertClipIcon(links) {
        if (links == null) {
            return
        }
        var button = links.querySelector(".copyToClipboard")
        // just need one
        if (button == null) {
            for (var i = 0; i < buttonArray.length; i++) {
                links.appendChild(buttonArray[i])
            }
        }
    }
    /**
     * get changes which checked by myselef
     * @returns 
     */
    function getCheckedChange() {
        var changes = new Array()
        var index = 0
        selectChangeMap.forEach(function (value, key) {
            if (value.isChecked()) {
                key.click()
                changes[index++] = value
            }
        })
        return changes
    }


    function getAllChanges() {
        var changes = new Array()
        var index = 0
        selectChangeMap.forEach(function (value, key) {
            changes[index++] = value
        })
        return changes
    }

    function getPackagingButton() {
        var button = getBaseButton()
        button.innerHTML = "package"
        button.onclick = function () {
            var array = getCheckedChange()
            if (array.length == 0) {
                toastr().error("not selected")
                print("not select any change")
                return
            }
            var datas = new Array()

            var curRepo = array[0].getRepo()
            var curBranch = array[0].getBranch()
            for (var item of array) {
                if (curRepo !== item.getRepo() || curBranch !== item.getBranch()) {
                    toastr().error("must simple repo and branch")
                    return;
                }
                datas[datas.length] = item.getData()
            }
            layer.open({
                type: 1,
                area: ['1000px', '500px'],
                title: "package",
                content: '<div style="padding:30px"><table id="table" class="layui-table" lay-filter="table"></table><form class="layui-form layui-form-pane" action=""><div class="layui-form-item"><label class="layui-form-label">CopyTask</label><div class="layui-input-block"><select name="copyTask" lay-verify="required" lay-filter="copyTask"></select></div></div><div class="layui-form-item"><button id="package" class="layui-btn" lay-submit lay-filter="package">package</button><button id ="reset" type="reset" class="layui-btn layui-btn-primary">reset</button></div></form></div>'
            })
            document.body.querySelector("#reset").click()
            loadSelectChanges(datas)
            var formItemArray = document.body.querySelectorAll(".layui-form-item")
            var copyTaskDom = formItemArray[0].querySelector("select")
            copyTaskDom.options.length = 0
            for (item of configs) {
                if (item['repo'] !== curRepo || item['branch'] !== curBranch) {
                    continue
                }
                copyTaskDom.add(new Option(item['name'], item['copyTaskId']))
            }
            var form = layui.form;
            form.render()
            form.on('submit(package)', function (data) {
                var copyTask = data.field['copyTask']
                if (copyTask === '') {
                    toastr().error("not select copyTask")
                } else {
                    GM_setValue(PACKAGE_CHANGE_ID, array)
                    GM_openInTab(gerritTask + copyTask)
                    layer.closeAll('page')
                }
                return false;
            });
        }
        var li = document.createElement("li")
        li.appendChild(button)
        return li
    }

    function getPackagingSettingsButton() {
        var button = getBaseButton()
        button.innerHTML = "settings"
        button.onclick = function () {
            // var div = document.createElement("div");
            // div.innerHTML = '<form class="layui-form" action=""><div class="layui-form-item"><label class="layui-form-label">输入框</label><div class="layui-input-block"><input type="text" name="title" required  lay-verify="required" placeholder="请输入标题" autocomplete="off" class="layui-input"></div></div><div class="layui-form-item"><label class="layui-form-label">密码框</label><div class="layui-input-inline"><input type="password" name="password" required lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input"></div><div class="layui-form-mid layui-word-aux">辅助文字</div></div><div class="layui-form-item"><label class="layui-form-label">选择框</label><div class="layui-input-block"><select name="city" lay-verify="required"><option value=""></option><option value="0">北京</option><option value="1">上海</option><option value="2">广州</option><option value="3">深圳</option><option value="4">杭州</option></select></div></div><div class="layui-form-item"><label class="layui-form-label">复选框</label><div class="layui-input-block"><input type="checkbox" name="like[write]" title="写作"><input type="checkbox" name="like[read]" title="阅读" checked><input type="checkbox" name="like[dai]" title="发呆"></div></div><div class="layui-form-item"><label class="layui-form-label">开关</label><div class="layui-input-block"><input type="checkbox" name="switch" lay-skin="switch"></div></div><div class="layui-form-item"><label class="layui-form-label">单选框</label><div class="layui-input-block"><input type="radio" name="sex" value="男" title="男"><input type="radio" name="sex" value="女" title="女" checked></div></div><div class="layui-form-item layui-form-text"><label class="layui-form-label">文本域</label><div class="layui-input-block"><textarea name="desc" placeholder="请输入内容" class="layui-textarea"></textarea></div></div><div class="layui-form-item"><div class="layui-input-block"><button class="layui-btn" lay-submit lay-filter="formDemo">立即提交</button><button type="reset" class="layui-btn layui-btn-primary">重置</button></div></div></form>'
            // console.log( div.childNodes[0])
            // document.body.appendChild( div.childNodes[0])
            layer.open({
                type: 1,
                area: ['1000px', '500px'],
                title: "settings",
                content: '<div style="padding:30px"><table id="table" class="layui-table" lay-filter="table"></table><form class="layui-form layui-form-pane" action=""><div class="layui-form-item"><label class="layui-form-label">Name</label><div class="layui-input-block"><input type="text" name="name" required lay-verify="required" placeholder="please input name" autocomplete="off"                    class="layui-input"></div></div><div class="layui-form-item"><label class="layui-form-label">Repo</label><div class="layui-input-block"><select name="repo" lay-verify="required" lay-filter="repo"></select></div></div><div class="layui-form-item"><label class="layui-form-label">Branch</label><div class="layui-input-block"><select name="branch" lay-verify="required" lay-filter="branch"></select></div></div><div class="layui-form-item layui-form-text"><label class="layui-form-label">CopyTaskId</label><div class="layui-input-block"><textarea name="copyTaskId" placeholder="please input task id" class="layui-textarea"></textarea></div></div><div class="layui-form-item"><div class="layui-input-block"><button id="add" class="layui-btn" lay-submit lay-filter="add">sure to add config</button><button id="reset" type="reset" class="layui-btn layui-btn-primary">reset form</button></div></div></form></div>'
            })
            loadConfigs()
            document.body.querySelector("#reset").click()
            // class use . id use #
            var formItemArray = document.body.querySelectorAll(".layui-form-item")
            var nameDom = formItemArray[0].querySelector("input")
            var repoDom = formItemArray[1].querySelector("select")
            var branchDom = formItemArray[2].querySelector("select")
            var taskidDom = formItemArray[3].querySelector("textarea")

            var allChange = getAllChanges()
            if (allChange.length > 0) {
                selectRepo(allChange[0].getRepo(), true)
            }

            var form = layui.form;
            form.on('select(repo)', function (data) {
                selectRepo(data.value, false)
            });
            form.on('submit(add)', function (data) {
                configs[configs.length] = data.field
                GM_setValue(TABLE_DATA, configs)
                loadConfigs()
                return false;
            });
        }
        var li = document.createElement("li")
        li.appendChild(button)
        return li
    }

    function getResetButton() {
        var button = getBaseButton()
        button.innerHTML = "Reset"
        button.onclick = function () {
            GM_deleteValue(TABLE_DATA, null)
            GM_deleteValue(PACKAGE_CHANGE_ID, null)
            configs = new Array();
            toastr().success("clear all configs")
        }
        var li = document.createElement("li")
        li.appendChild(button)
        return li
    }

    function loadSelectChanges(datas) {
        var table = layui.table;
        // id, title, repo, branch
        print(datas)
        table.render({
            elem: '#table'
            , title: "config"
            , height: 200
            , data: datas
            , page: true
            , cols: [[
                { field: 'id', title: 'Id' }
                , { field: 'title', title: 'Title' }
                , { field: 'repo', title: 'Repo' }
                , { field: 'branch', title: 'Branch' }
            ]]
        });
    }

    function loadConfigs() {
        var table = layui.table;
        table.render({
            elem: '#table'
            , title: "config"
            , height: 200
            , data: configs
            , page: true
            , cols: [[
                { field: 'name', title: 'Name' }
                , { field: 'repo', title: 'Repo' }
                , { field: 'branch', title: 'Branch' }
                , { field: 'copyTaskId', title: 'CopyTaskId' }
            ]]
        });
        table.on('row', function(obj){
            configs.map((value,i) =>{
                if(value['name'] == obj.data['name']){
                    configs.splice(i,1)
                }
            })
            GM_setValue(TABLE_DATA, configs)
            obj.del();
            toastr().info("delete config")
        });
    }

    function selectRepo(repo, isFirst) {
        var formItemArray = document.body.querySelectorAll(".layui-form-item")
        var repoDom = formItemArray[1].querySelector("select")
        var branchDom = formItemArray[2].querySelector("select")
        branchDom.options.length = 0;
        var changes = getAllChanges()
        var tempMap = new Map()
        for (var change of changes) {
            var tempArray = new Array()
            if (!tempMap.has(change.getRepo())) {
                tempArray[0] = change.getBranch()
            } else {
                tempArray = tempMap.get(change.getRepo())
                var isHave = false
                for (var i of tempArray) {
                    if (i === change.getBranch()) {
                        isHave = true
                    }
                }
                if (!isHave) {
                    tempArray[tempArray.length] = change.getBranch()
                }
            }
            tempMap.set(change.getRepo(), tempArray)
        }
        tempMap.forEach(function (value, key) {
            var repoOption = createOption(key, key)
            if (isFirst) {
                repoDom.add(repoOption)
            }
            if (repo === key) {
                for (var item of value) {
                    branchDom.add(createOption(item, item))
                }
            }
        })
        var form = layui.form;
        form.render()
    }

    function createOption(value, text) {
        return new Option(text, value)
    }

    function getCopyButton() {
        var button = getBaseButton()
        button.innerHTML = "copy"
        button.onclick = function () {
            var array = getCheckedChange()
            if (array.length == 0) {
                toastr().error("not selected")
                print("not select any change")
                return
            }
            var result = "";
            for (var i = 0; i < array.length; i++) {
                var extra = ""
                if (i != 0) {
                    extra += "\n"
                }
                result += extra + array[i].getString()
                if (i != array.length - 1) {
                    result += "\n"
                }
            }
            toastr().success("copy selected changes")
            print("copy \n" + result)
            GM_setClipboard(result)
        }
        var li = document.createElement("li")
        li.appendChild(button)
        return li
    }

    function getBaseButton() {
        var targetButton = document.createElement("gr-button")
        var paperButton = document.createElement("paper-button")
        targetButton.setAttribute("class", "copyToClipboard")
        targetButton.setAttribute("role", "button")
        targetButton.setAttribute("aria-disabled", "false")
        targetButton.appendChild(paperButton)
        targetButton.setAttribute("style", "padding:8px;")
        return targetButton
    }

    function removeArray(array, item) {
        var index = 0
        for (a in array) {
            if (item === a) {
                break;
            }
            index = index + 1
        }
        array.splice(index, 1)
    }

    class setting {
        constructor(name, repo, branch, taskid) {
            this.name = name
            this.repo = repo
            this.branch = branch
            this.taskid = taskid
        }

        getName() {
            return this.name
        }

        getrepo() {
            return this.repo
        }

        getBranch() {
            return this.branch
        }

        getTaskId() {
            return this.taskid
        }
    }

    /**
     * change class 
     * save information about change
     */
    class Change {
        constructor(id, title, url, repo, branch) {
            this.id = id.trim()
            this.title = title.trim()
            this.url = url.trim()
            this.repo = repo.trim()
            this.branch = branch.trim()
            this.ischecked = false
        }

        getId() {
            return this.id
        }

        isChecked() {
            return this.ischecked
        }

        setIsChecked(ischecked) {
            this.ischecked = ischecked
        }

        getRepo() {
            return this.repo
        }

        getBranch() {
            return this.branch
        }

        getString() {
            var result = "ChangeId: " + this.id + " Title: " + this.title + " Repo: " + this.repo + " Branch: " + this.branch + "\nUrl: " + this.url
            return result
        }

        getData() {
            var result = { 'id': this.id, 'title': this.title, 'repo': this.repo, 'branch': this.branch }
            return result
        }
    }
    function toastr() {
        var $container;
        var listener;
        var toastId = 0;
        var toastType = {
            error: 'error',
            info: 'info',
            success: 'success',
            warning: 'warning'
        };

        var toastr = {
            clear: clear,
            remove: remove,
            error: error,
            getContainer: getContainer,
            info: info,
            options: {},
            subscribe: subscribe,
            success: success,
            version: '2.1.1',
            warning: warning
        };

        var previousToast;

        return toastr;

        ////////////////

        function error(message, title, optionsOverride) {
            return notify({
                type: toastType.error,
                iconClass: getOptions().iconClasses.error,
                message: message,
                optionsOverride: optionsOverride,
                title: title
            });
        }

        function getContainer(options, create) {
            if (!options) { options = getOptions(); }
            $container = $('#' + options.containerId);
            if ($container.length) {
                return $container;
            }
            if (create) {
                $container = createContainer(options);
            }
            return $container;
        }

        function info(message, title, optionsOverride) {
            return notify({
                type: toastType.info,
                iconClass: getOptions().iconClasses.info,
                message: message,
                optionsOverride: optionsOverride,
                title: title
            });
        }

        function subscribe(callback) {
            listener = callback;
        }

        function success(message, title, optionsOverride) {
            return notify({
                type: toastType.success,
                iconClass: getOptions().iconClasses.success,
                message: message,
                optionsOverride: optionsOverride,
                title: title
            });
        }

        function warning(message, title, optionsOverride) {
            return notify({
                type: toastType.warning,
                iconClass: getOptions().iconClasses.warning,
                message: message,
                optionsOverride: optionsOverride,
                title: title
            });
        }

        function clear($toastElement, clearOptions) {
            var options = getOptions();
            if (!$container) { getContainer(options); }
            if (!clearToast($toastElement, options, clearOptions)) {
                clearContainer(options);
            }
        }

        function remove($toastElement) {
            var options = getOptions();
            if (!$container) { getContainer(options); }
            if ($toastElement && $(':focus', $toastElement).length === 0) {
                removeToast($toastElement);
                return;
            }
            if ($container.children().length) {
                $container.remove();
            }
        }

        // internal functions

        function clearContainer(options) {
            var toastsToClear = $container.children();
            for (var i = toastsToClear.length - 1; i >= 0; i--) {
                clearToast($(toastsToClear[i]), options);
            }
        }

        function clearToast($toastElement, options, clearOptions) {
            var force = clearOptions && clearOptions.force ? clearOptions.force : false;
            if ($toastElement && (force || $(':focus', $toastElement).length === 0)) {
                $toastElement[options.hideMethod]({
                    duration: options.hideDuration,
                    easing: options.hideEasing,
                    complete: function () { removeToast($toastElement); }
                });
                return true;
            }
            return false;
        }

        function createContainer(options) {
            $container = $('<div/>')
                .attr('id', options.containerId)
                .addClass(options.positionClass)
                .attr('aria-live', 'polite')
                .attr('role', 'alert');

            $container.appendTo($(options.target));
            return $container;
        }

        function getDefaults() {
            return {
                tapToDismiss: true,
                toastClass: 'toast',
                containerId: 'toast-container',
                debug: false,

                showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery
                showDuration: 300,
                showEasing: 'swing', //swing and linear are built into jQuery
                onShown: undefined,
                hideMethod: 'fadeOut',
                hideDuration: 1000,
                hideEasing: 'swing',
                onHidden: undefined,

                extendedTimeOut: 1000,
                iconClasses: {
                    error: 'toast-error',
                    info: 'toast-info',
                    success: 'toast-success',
                    warning: 'toast-warning'
                },
                iconClass: 'toast-info',
                positionClass: 'toast-top-right',
                timeOut: 5000, // Set timeOut and extendedTimeOut to 0 to make it sticky
                titleClass: 'toast-title',
                messageClass: 'toast-message',
                target: 'body',
                closeHtml: '<button type="button">&times;</button>',
                newestOnTop: true,
                preventDuplicates: false,
                progressBar: false
            };
        }

        function publish(args) {
            if (!listener) { return; }
            listener(args);
        }

        function notify(map) {
            var options = getOptions();
            var iconClass = map.iconClass || options.iconClass;

            if (typeof (map.optionsOverride) !== 'undefined') {
                options = $.extend(options, map.optionsOverride);
                iconClass = map.optionsOverride.iconClass || iconClass;
            }

            if (shouldExit(options, map)) { return; }

            toastId++;

            $container = getContainer(options, true);

            var intervalId = null;
            var $toastElement = $('<div/>');
            var $titleElement = $('<div/>');
            var $messageElement = $('<div/>');
            var $progressElement = $('<div/>');
            var $closeElement = $(options.closeHtml);
            var progressBar = {
                intervalId: null,
                hideEta: null,
                maxHideTime: null
            };
            var response = {
                toastId: toastId,
                state: 'visible',
                startTime: new Date(),
                options: options,
                map: map
            };

            personalizeToast();

            displayToast();

            handleEvents();

            publish(response);

            if (options.debug && console) {
                console.log(response);
            }

            return $toastElement;

            function personalizeToast() {
                setIcon();
                setTitle();
                setMessage();
                setCloseButton();
                setProgressBar();
                setSequence();
            }

            function handleEvents() {
                $toastElement.hover(stickAround, delayedHideToast);
                if (!options.onclick && options.tapToDismiss) {
                    $toastElement.click(hideToast);
                }

                if (options.closeButton && $closeElement) {
                    $closeElement.click(function (event) {
                        if (event.stopPropagation) {
                            event.stopPropagation();
                        } else if (event.cancelBubble !== undefined && event.cancelBubble !== true) {
                            event.cancelBubble = true;
                        }
                        hideToast(true);
                    });
                }

                if (options.onclick) {
                    $toastElement.click(function () {
                        options.onclick();
                        hideToast();
                    });
                }
            }

            function displayToast() {
                $toastElement.hide();

                $toastElement[options.showMethod](
                    { duration: options.showDuration, easing: options.showEasing, complete: options.onShown }
                );

                if (options.timeOut > 0) {
                    intervalId = setTimeout(hideToast, options.timeOut);
                    progressBar.maxHideTime = parseFloat(options.timeOut);
                    progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime;
                    if (options.progressBar) {
                        progressBar.intervalId = setInterval(updateProgress, 10);
                    }
                }
            }

            function setIcon() {
                if (map.iconClass) {
                    $toastElement.addClass(options.toastClass).addClass(iconClass);
                }
            }

            function setSequence() {
                if (options.newestOnTop) {
                    $container.prepend($toastElement);
                } else {
                    $container.append($toastElement);
                }
            }

            function setTitle() {
                if (map.title) {
                    $titleElement.append(map.title).addClass(options.titleClass);
                    $toastElement.append($titleElement);
                }
            }

            function setMessage() {
                if (map.message) {
                    $messageElement.append(map.message).addClass(options.messageClass);
                    $toastElement.append($messageElement);
                }
            }

            function setCloseButton() {
                if (options.closeButton) {
                    $closeElement.addClass('toast-close-button').attr('role', 'button');
                    $toastElement.prepend($closeElement);
                }
            }

            function setProgressBar() {
                if (options.progressBar) {
                    $progressElement.addClass('toast-progress');
                    $toastElement.prepend($progressElement);
                }
            }

            function shouldExit(options, map) {
                if (options.preventDuplicates) {
                    if (map.message === previousToast) {
                        return true;
                    } else {
                        previousToast = map.message;
                    }
                }
                return false;
            }

            function hideToast(override) {
                if ($(':focus', $toastElement).length && !override) {
                    return;
                }
                clearTimeout(progressBar.intervalId);
                return $toastElement[options.hideMethod]({
                    duration: options.hideDuration,
                    easing: options.hideEasing,
                    complete: function () {
                        removeToast($toastElement);
                        if (options.onHidden && response.state !== 'hidden') {
                            options.onHidden();
                        }
                        response.state = 'hidden';
                        response.endTime = new Date();
                        publish(response);
                    }
                });
            }

            function delayedHideToast() {
                if (options.timeOut > 0 || options.extendedTimeOut > 0) {
                    intervalId = setTimeout(hideToast, options.extendedTimeOut);
                    progressBar.maxHideTime = parseFloat(options.extendedTimeOut);
                    progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime;
                }
            }

            function stickAround() {
                clearTimeout(intervalId);
                progressBar.hideEta = 0;
                $toastElement.stop(true, true)[options.showMethod](
                    { duration: options.showDuration, easing: options.showEasing }
                );
            }

            function updateProgress() {
                var percentage = ((progressBar.hideEta - (new Date().getTime())) / progressBar.maxHideTime) * 100;
                $progressElement.width(percentage + '%');
            }
        }

        function getOptions() {
            return $.extend({}, getDefaults(), toastr.options);
        }

        function removeToast($toastElement) {
            if (!$container) { $container = getContainer(); }
            if ($toastElement.is(':visible')) {
                return;
            }
            $toastElement.remove();
            $toastElement = null;
            if ($container.children().length === 0) {
                $container.remove();
                previousToast = undefined;
            }
        }

    }


    // code region end
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址