jira任务板

try to take over the world!

// ==UserScript==
// @name         jira任务板
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @require      https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js
// @require      https://cdn.bootcss.com/lodash.js/4.17.15/lodash.min.js
// @require      https://cdn.bootcss.com/moment.js/2.24.0/moment.min.js
// @match        http://jira.dotfashion.cn/*
// @grant 	     GM_addStyle
// ==/UserScript==

(function() {
    'use strict';
    const pmNameKey = 'customfield_10300'
    const frontEndConfigOptions = [
        {
            title: '前端开始日期',
            key: 'customfield_11811',
        },
        {
            title: '前端结束日期',
            key: 'customfield_11788',
        },
    ]
    const issueConfigOptions = [
        {
            title: '联调日期',
            key: 'customfield_12557',
        },
        {
            title: '测试开始日期',
            key: 'customfield_11806',
        },
        {
            title: '测试结束日期',
            key: 'customfield_11792',
        },
        {
            title: '验收日期',
            key: 'customfield_11790',
        },
        {
            title: '计划上线日期',
            key: 'customfield_10203',
        },
        {
            title: '实际上线日期',
            key: 'customfield_10813',
        },
    ]
    const columns = [
        {
            title: '主需求号',
            key: 'linkKey',
            render: value => `<a href="http://jira.dotfashion.cn/browse/${value}" target="_blank">${value || ''}</a>`,
        },
        {
            title: '个人需求号',
            key: 'key',
            render: value => `<a href="http://jira.dotfashion.cn/browse/${value}" target="_blank">${value || ''}</a>`,
        },
        {
            title: '需求摘要',
            key: 'linkSummary',
            render: (value, item) => value || item.summary || '',
        },
        {
            title: '产品经理',
            key: 'pmName',
        },
    ].concat(frontEndConfigOptions.concat(issueConfigOptions).map(item => Object.assign({}, item, {
        class: value => {
            if (value) {
                const diff = moment(moment().format('YYYY-MM-DD')) - moment(value)
                const className = diff > 0 ? 'jira-m-done' : diff === 0 ? 'jira-m-active' : 'jira-m-wait'
                return className
            }
            return ''
        },
    })))
    const tableTitleTemp = $(`<tr class="table-title">` + columns.map(item => `<th class="table-item">${item.title}</th>`).join('') + `</tr>`)
    $(document).ready(function() {
        GM_addStyle(`
.jira-m-wait { background-color: #dfe1e5; color: #42526e; }
.jira-m-active { background: #0052cc; color: #fff; }
.jira-m-done { background-color: #e3fcef; color: #064; }
.jira-panel-icon { position: fixed; z-index: 101; left: 40px; bottom: 40px; width: 80px; height: 80px; border-radius: 50%; background: #0747a6; color: #fff; display: none; align-items: center; justify-content: center; cursor: pointer; }
.jira-panel-container { position: fixed; width: 100%; height: 100%; left: 0; top: 0; z-index: 100; display: none }
.jira-panel-mask { position: absolute; z-index: -1; width: 100%; height: 100%; left: 0; top: 0; background: rgba(0,0,0,.33); }
.jira-panel-modal-wrap { width: 100%; height: 100%; overflow: auto; }
.jira-panel-modal { width: 90%; margin: 50px auto; background: #fff; border: 1px solid #cecece; border-radius: 8px; }
.jira-panel-modal-title { text-indent: 1em; line-height: 2.8em; border-bottom: 1px solid #cecece; }
.jira-panel-modal-body { padding: 35px; }
.jira-panel-modal-body-content { overflow: auto; max-height: 400px; }
.jira-panel-modal-table .table-item { min-width: 60px; max-width: 250px; padding: 8px; line-height: 2em; text-align: center; }
.jira-panel-modal-table .table-title { font-weight: 600; background: rgba(0,0,0,.15); }
`)
        const panelIconTemp = $(`<div class="jira-panel-icon" id="panelIcon">JIRA面板</div>`)
        const panelContainerTemp = $(`
<div class="jira-panel-container">
    <div class="jira-panel-mask" />
    <div class="jira-panel-modal-wrap">
        <div class="jira-panel-modal">
            <div class="jira-panel-modal-title">JIRA任务-${moment().format('YYYY-MM-DD')}</div>
            <div class="jira-panel-modal-body">
                <div class="jira-panel-modal-body-content">
                    <table class="jira-panel-modal-table" id="panelTable" border="1" cellspacing="0" />
                </div>
            </div>
        </div>
    </div>
</div>
`)
        $('body').append(panelIconTemp)
        $('body').append(panelContainerTemp)
        panelIconTemp.click(() => panelContainerTemp.slideToggle())
        fetch('/rest/api/2/myself')
            .then(res => res.json())
            .then(res => {
            const jql = encodeURIComponent(`project = MLB AND assignee in (${res.name}) order by created DESC`)
            return fetch(`/rest/api/2/search?jql=${jql}`)
        })
            .then(res => res.json())
            .then(res => {
            const data = res.issues.map(item => {
                const { key, fields } = item
                const frontEndConfig = _.pick(fields, frontEndConfigOptions.map(item => item.key))
                const linkOptions = fields.issuelinks.length ? fields.issuelinks[0].outwardIssue : {}
                return Object.assign({}, {
                    key,
                    summary: fields.summary,
                    linkKey: linkOptions.key,
                    linkSummary: linkOptions.fields && linkOptions.fields.summary,
                    linkApi: linkOptions.self,
                }, frontEndConfig)
            })
            return Promise.all(data.map(item => {
                if (item.linkApi) {
                    return fetch(item.linkApi).then(res => res.json())
                }
                return Promise.resolve(null)
            })).then(res => data.map((item, index) => {
                const fields = res[index] ? res[index].fields : {}
                const pmName = fields[pmNameKey] && fields[pmNameKey].name
                return Object.assign({ pmName }, item, _.pick(fields, issueConfigOptions.map(child => child.key)))
            }))
        }).then(res => {
            const rowHtmlStr = res.map(item => {
                const childs = columns.map(sub => {
                    const keyValue = item[sub.key]
                    const value = typeof sub.render === 'function' ? sub.render(keyValue, item) : keyValue
                    const className = typeof sub.class === 'function' ? ` ${sub.class(keyValue, item)}` : ''
                    return `<td class="table-item${className}">${value || ''}</td>`
                })
                return `<tr class="table-row">${childs.join('')}</tr>`
            }).join('')
            $('#panelTable').append(tableTitleTemp)
            $('#panelTable').append($(rowHtmlStr))
            $('#panelIcon').css('display', 'flex').fadeIn()
        })
    });
})();