ad_gitlab_code_reviewer_helper

用于CR提效

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

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

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

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

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @name         ad_gitlab_code_reviewer_helper
// @namespace    http://tampermonkey.net/
// @version      1.0.22
// @description  用于CR提效
// @author       You
// @require      http://cdn.bootcss.com/jquery/1.8.3/jquery.min.js
// @match        https://code.byted.org/*/*/merge_requests/*
// @match        https://codebase.byted.org/standalone-page/repository/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=byted.org
// @grant        none
// @license      no
// ==/UserScript==
 
const optionsStrList = [
    '风格问题-lint可修复',
    '风格问题-lint无法自动修复',
    '风格问题-未确定规范',
    '单测问题',
    '逻辑问题',
    'debug代码未还原',
    '存在性能隐患',
    '存在安全隐患',
    '其他'
]
const reg = new RegExp(`^(${optionsStrList.reduce((pre,cur,currentIndex)=>{
    const prefix =currentIndex!==0?`${pre}|`:pre
    return `${prefix}\\[ ${cur} \\]`
},'')})`, 'g')
 
const replaceReg = new RegExp(`(${optionsStrList.reduce((pre,cur,currentIndex)=>{
    const prefix =currentIndex!==0?`${pre}|`:pre
    return `${prefix}\\[ ${cur} \\]`
},'')})`, 'g')
 
 
const disabledStyle = `background-color:#eee!important;
                        cursor:not-allowed!important;
                        color:#b2b2b2!important;
                        border: 1px solid #e5e6e8!important;
                        margin-left: 8px !important;
                        `
const cancelDisableStyle = `background-color:#fafbfc!important;
                            cursor:pointer!important;
                            margin-left: 8px !important;
                            `
 
 
function addCateBtn() {
    const btnContainer = $('.codebase-dv-thread')
 
    btnContainer.each((index, item) => {
        if ($(item).find('.xbw-select-wrap')?.length) {
            $(item).find('textarea').trigger('input')
            return
        }
        let ele = $(`<span class=xbw-select-wrap><select style="width:140px;border-radius:4px;height:20px;font-size:10px;text-overflow: ellipsis;">
        <option value="none" selected disabled hidden>请选择分类</option>
        ${optionsStrList.map((item, index) => {
            return `<option value=${item}>${item}</option>`
        }).join('\n')}</select></span>`);
 
        let selectedValue = ""
        $($(item).find('button')[0]).parent().css('gap', '8px')
        let targetTextValue
        //分类按钮
        ele.on('input', function (e) {
            setTimeout(() => {
                const textarea = $(item).find('textarea')
                const textareaDOM = textarea[0]
                let textareaVal = textarea.val()
                selectedValue = $(item).find('option:selected').val()
                if (selectedValue) {
                    replaceReg.lastIndex = 0
                    targetTextValue = replaceReg.test(textareaVal) ? textareaVal.replace(replaceReg, `[ ${selectedValue} ]`) : `[ ${selectedValue} ]${textareaVal}`
                }
 
                textarea.val(targetTextValue).trigger('input')
                const event = new MouseEvent('mouseup', {
                    bubbles: true,
                    cancelable: true,
                    view: window,
                })
                textareaDOM.dispatchEvent(event);
            })
 
        })
 
        const textareaInput = (e) => {
            setTimeout(() => {
 
                const buttonGroup = $(item).find('button')
                const startReview = buttonGroup[0]
                const commentNow = buttonGroup[1]
                const cancel = buttonGroup[2]
                const isCancel = $($(item).find('button')[1]).html() === 'Cancel'
                const blueBg = ['Start a review', 'Submit', 'Add review comment']
                const isStartAReview = blueBg.includes($(startReview).html())
                reg.lastIndex = 0
                const hasSelect = $(item).find('.xbw-select-wrap').length
 
                if (hasSelect) {
                    if (reg.test(e.target.value)) {
                        $(startReview).attr('disabled', false)
                        $(commentNow).attr('disabled', false)
                    } else {
                        $(startReview).attr({disabled: 'disabled'})
                        $(commentNow).attr('disabled', !isCancel)
                    }
                }
 
                if ($(startReview).attr('disabled')) {  // 禁用状态  样式修改
                    $(startReview).css("cssText", disabledStyle);
 
                    $(startReview).attr({title: "请选择分类"})
                    if (!isCancel) {
                        $(commentNow).css("cssText", disabledStyle);
                        $(commentNow).attr({title: "请选择分类"})
                    }
                } else {
                    $(startReview).css("cssText", cancelDisableStyle);
                    $(startReview).attr({title: ''})
                    if (!isCancel) {
                        $(commentNow).css("cssText", cancelDisableStyle);
                        $(commentNow).attr({title: ''})
                    }
                    if (isStartAReview) {
                        $(startReview).css("cssText", `border: 1px solid #3f51b5!important;background-color: #3f51b5!important;margin-left: 8px!important;`);
                    }
                }
            })
        }
        const writeBtn = $(item).find("[data-name='Write']")
        writeBtn.on('click', () => {
            setTimeout(() => {
                const parent = $(writeBtn).parents('.codebase-dv-thread')[0]
                const textarea = parent.getElementsByTagName('textarea')[0]
                $(textarea).off('input', textareaInput)
                $(textarea).on('input', textareaInput)
            })
        })
        $(item).find('textarea').on('input', textareaInput)
        $(item).find('textarea').trigger('input')
        setTimeout(() => {
            const value = $($(item).find('textarea')[0]).val()
            replaceReg.lastIndex = 0
            if (!$(item).find('.md-preview').length) {
                $($(item).find("[data-name='Preview']").parent()[0]).after(ele)
            } else if (replaceReg.test(value)) {
                $($(item).find("[data-name='Preview']").parent()[0]).after(ele)
            }
        })
    })
}
 
(function () {
    'use strict';
    const style = document.createElement('style');
    const toast = document.createElement('div');
    style.innerHTML = `
 
    #tampermonkey-toast {
    display: none;
    cursor: pointer;
    position: fixed;
    top: 12%;
    flex-direction: column;
    left: 50%;
    z-index: 99999;
    transform: translate(-50%, -50%);
    background: transparent;
    align-items: center;
    }
    #tampermonkey-toast.none{
        display: none !important;
    }
    .tampermonkey-toast-content{
            color:#353535;
    }
        `;
    const submitReviewText = '还有 Submit review 没有处理'
    const resolveCommentText = '仍存在未Resolve的评论,将不能合并代码'
    let isShowSubmitReviewText = false;
    let isShowResolveCommentText = false;
 
    toast.id = 'tampermonkey-toast'
 
    $('head').append(style)
    $('body').append(toast)
 
    const toastClickHandle = () => {
        toast.classList.add("none");
        toast.removeEventListener('click', toastClickHandle)
    }
 
    toast.addEventListener('click', toastClickHandle)
    const handleToast = (isShowResolveCommentTextParams, isShowSubmitReviewTextParams) => {
        if (isShowResolveCommentTextParams === isShowResolveCommentText && isShowSubmitReviewTextParams === isShowSubmitReviewText) {
            return
        }
        isShowResolveCommentText = isShowResolveCommentTextParams
        isShowSubmitReviewText = isShowSubmitReviewTextParams
        const isShowToast = isShowResolveCommentText || isShowSubmitReviewText
        const toast = $('#tampermonkey-toast')
        toast.css('display', isShowToast ? 'flex' : 'none')
        const submitReviewTextHtml = isShowSubmitReviewText ? `
     <h2 class="tampermonkey-toast-content">
     ${submitReviewText}
     </h2>`
            : ''
        const resolveCommentTextHtml = isShowResolveCommentText ? `
     <h2 class="tampermonkey-toast-content">
     ${resolveCommentText}
     </h2>`
            : ''
        toast.html(`
    ${isShowSubmitReviewText ? submitReviewTextHtml : ''}
    ${isShowResolveCommentText ? resolveCommentTextHtml : ''}
    `)
    }
    let mergeBtn;
    let unResolveBtn;
 
    function findBtn(btn, selectors) {
        if (!btn || btn.length === 0) {
            for (let i = 0; i < selectors.length; i++) {
                btn = $(selectors[i])
                if (btn.length) {
                    break;
                }
            }
        }
        return btn
    }
 
    window.setInterval(() => {
        const mergeBtnSelectOr = [
            '.qa-merge-button',
            '#app > div > div > div.sc-gpHHfC.kVUvJF.codebase-widget-merge > div > div.sc-gHboQg.fHtJmu > div > div > button',
            '#content-body > div > div.merge-request-details.issuable-details > div.mr-state-widget.prepend-top-default > div.mr-section-container > div.mr-widget-section > div > div.space-children.d-flex.append-right-10.widget-status-icon > button'
        ]
        mergeBtn = findBtn(mergeBtn, mergeBtnSelectOr)
 
        const unResolveBtnSelectOr = [
            '#gitlab-diff-viewer > div > div.sc-gPzReC.hzmplu > div:nth-child(2) > button.ant-btn.ant-dropdown-trigger > span',
            '#app > div > div > div.sc-hIVACf.kzuFjX > div > div.sc-dliRfk.ebNhmW > div:nth-child(2) > button.ant-btn.ant-dropdown-trigger',
            '#gitlab-diff-viewer > div > div.sc-jrIrqw.hDMvqZ > div:nth-child(2) > button.ant-btn.ant-dropdown-trigger'
        ]
 
        unResolveBtn = findBtn(unResolveBtn, unResolveBtnSelectOr)
 
 
 
        if (mergeBtn.length && unResolveBtn.length) {
            const unResolveNumber = Number(parseFloat(unResolveBtn[0].innerText))
            const isExistUnResolve = unResolveNumber !== 0
            handleToast(isExistUnResolve, isShowSubmitReviewText)
            mergeBtn.attr({title: isExistUnResolve ? resolveCommentText : ''})
            mergeBtn.attr('disabled', isExistUnResolve)
        }
        const submitReviewSelectOr = [
            '#gitlab-diff-viewer > div > div.sc-gPzReC.hzmplu > div:nth-child(2) > span > div > button:nth-child(1)',
            '#gitlab-diff-viewer > div > div.sc-gPzReC.hzmplu > div:nth-child(2) > div.ant-btn-group > button:nth-child(1)',
            '#codebase-cr-full-screen > div.sc-kXeGPI.iEVqRe > div:nth-child(1) > div.sc-eTpRJs.sc-dxZgTM.gHfWdU > span > div > button:nth-child(1)',
            '#app > div > div > div.sc-hIVACf.kzuFjX > div > div.sc-dliRfk.ebNhmW > div:nth-child(2) > span > div > button:nth-child(1)'
        ]
 
        let submitReviewBtn
        for (let i = 0; i < submitReviewSelectOr.length; i++) {
            submitReviewBtn = $(submitReviewSelectOr[i])
            if (submitReviewBtn.length) {
                break;
            }
        }
        const textNode = submitReviewBtn.find('span:nth-child(1)')
        //是否发生改变
        let isDisabled
        const isSubmitReviewBtn = textNode[0]?.innerText === 'Submit review' || textNode[0]?.innerHTML === 'Submit review'
        if (isSubmitReviewBtn) {
            isDisabled = submitReviewBtn.attr('disabled') ?? false
        }
        handleToast(isShowResolveCommentText, isDisabled === undefined ? false : !isDisabled)
        $('.codebase-dv-tr').filter((index, item) => {
            return !$(item).attr('data-cr-marked')
        }).attr('data-cr-marked', true)
            .click(function () {
                setTimeout(() => {
                    addCateBtn()
                }, 500);
            })
    }, 1000);
})();