您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds colored sections, extra functionality, and avatars to Gitlab. For avatars, detects locally-running image server to use for replacements of avatars. Use http-server (https://www.npmjs.com/package/http-server) for node.js for simple image hosting. Recommend image size of 100x100.
当前为
// ==UserScript== // @name Gitlab Mods // @namespace COMDSPDSA // @version 1.4 // @description Adds colored sections, extra functionality, and avatars to Gitlab. For avatars, detects locally-running image server to use for replacements of avatars. Use http-server (https://www.npmjs.com/package/http-server) for node.js for simple image hosting. Recommend image size of 100x100. // @author Dan Overlander // @include */gitlab.dell.com* // @require https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js // @require https://greasyfork.org/scripts/23115-tampermonkey-support-library/code/Tampermonkey%20Support%20Library.js // @require https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js // @require https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment-with-locales.min.js // @grant GM_setValue // @grant GM_getValue // ==/UserScript== // Since v01.3: Re-enables the Tampericon // Since v01.2: Adds "hide tree" button (looks like a coffee cup) // Since v01.1: Updates document title with countdown timer indication. Adds hourly reminder of existing TODOs. Removes conversation button from non-conversation pages. // Since v01.0: Added the countdown indicator to the page title for TODO indication; cancelling reverts the title to original // Since v00.0: init, copying from GIT Avatars script /* * tm is an object included via @require from DorkForce's Tampermonkey Assist script */ (function() { 'use strict'; var TIMEOUT = 750, avatarHost = 'localhost:8080/', // for setPhoto pingPhoto = '!none', // pinging for setPhoto imageExt = '.png', global = { scriptName: 'Gitlab Mods', areClassesAdded: false, areButtonsAdded: false, todoMonitorInitialized: false, todoTimer: undefined, isMouseMoved: false, prefs: GM_getValue('gitlabPrefs') != null ? JSON.parse(GM_getValue('gitlabPrefs')) : {}, reload: { lapsed: 0, timespan: 10000, title: document.title } }, properName = function(thisName) { var firstName = '', lastName = '', midName = ''; thisName = thisName .replace('https://gitlab.dell.com/', '') .replace(' - Dell Team', '') .replace('@', '') .replace(/@/g, '') .replace(/\//g, '') .replace(/_/g, '-'); firstName = thisName.substring(0, thisName.indexOf('-')); lastName = thisName.substring(thisName.indexOf('-')+1, thisName.length); if ((firstName.length === 0 || lastName.length === 0) && thisName.indexOf(',') < 0) { return; } if (thisName.indexOf(',') < 0) { thisName = lastName + ', ' + firstName; } if (thisName.indexOf('-') > 0) { midName = thisName.substring(0, thisName.indexOf('-')); thisName = thisName.substring(thisName.indexOf('-')+1, thisName.length); thisName = thisName + ' ' + midName; } thisName = thisName .replace(/(\r\n\t|\n|\r\t)/gm,'') // no line breaks or tabs .replace(/\s\s/, '') // no double spaces .replace(/ ,/, ',') // no spaces before commas .replace(/\%20/, '') // no %20 characters .replace(/,[a-z|0-9]/, ', ') // no commas without spaces behind them .trim(); // seriously, no extra spaces return thisName; }, updateImg = function(img, thisName) { if (thisName != null) { if (thisName !== ', ') { $(img).prop('src', 'http://' + avatarHost + thisName + imageExt); } else { tm.log('updateImg: invalid user name for ' + img.src + ': ' + thisName + '(' + thisName.length + ' chars)'); } } }, page = { initialize: function () { setTimeout(function () { page.setPrefs(); page.addClasses(); page.adjustStyles(); page.setTamperIcon(); page.addButtons(); page.setAvatars(); page.monitorTodos(); }, TIMEOUT); }, setPrefs: function() { if (global.prefs.todosCount == null) global.prefs.todosCount = '0'; if (global.prefs.todosTimestamp == null) { global.prefs.todosTimestamp = moment(); } }, addClasses: function () { if (!global.areClassesAdded) { global.areClassesAdded = true; // colored backgrounds tm.addGlobalStyle('.merge-request-tabs-container {background:bisque;}'); tm.addGlobalStyle('.merge-request-tabs {background:burlywood;}'); tm.addGlobalStyle('.mr-widget-content {background:cornflowerblue;}'); // UI-sizing tm.addGlobalStyle('.approvals-required-text .avatar {width:24px; height:24px;}'); tm.addGlobalStyle('.note-text ul {margin:0px !important;}'); tm.addGlobalStyle('.system-note {font-size:0.7em; padding:0; margin:10px 0px 0px 0px;}'); tm.addGlobalStyle('.timeline-entry:hover {background:aliceblue;}'); tm.addGlobalStyle('.note-text .gfm-merge_request {background:aliceblue; padding:10px; float:right; position:relative; top:-23px; margin-bottom:-28px;}'); tm.addGlobalStyle('.tamperNewIcon {position:relative; top:-10px;'); } }, adjustStyles: function() { $('.discussion-headline-light').each(function(discussion) { if($(this).text().indexOf('Resolved') > 0){ $(this).parent().css('background-color', 'palegreen'); } else { $(this).parent().css('background-color', 'orange'); } } ); }, setTamperIcon: function () { // Add Tampermonkey Icon with label to identify this script if($('.tamperlabel').length > 0) { tm.log($('.tamperlabel').prop('title')); if ($('.tamperlabel').prop('title').indexOf(global.scriptName) === -1) { $('.tamperlabel').prop('title', $('.tamperlabel').prop('title') + ' | ' + global.scriptName); } } else { $('body').append('<span class="tamperlabel" title="Tampermonkey scripts: ' + global.scriptName + '"><i class="fa fa-battery-three-quarters tamperNewIcon"></i></span>'); } }, addButtons: function() { var idConversations = 'Talk', addConversationsButton = function () { var buttonAnchor = $('.header-new'); var talkElement = function () { $('html, body').animate({ scrollTop: $('.approvals-components').offset().top -100 }, 500); return false; }; buttonAnchor.before('<i id="' + idConversations + '" class="fa fa-stack-exchange" style="padding:13px; cursor:pointer;"></i>'); $('#' + idConversations).click(talkElement); }, idTreeToggle = 'TreeToggle', addTreeToggleButton = function() { var buttonAnchor = $('.merge-request-tabs-holder'); var toggleTree = function () { if ($('.diff-tree-list').css('width') === '0px') { $('.diff-tree-list').show(); $('.diff-tree-list').animate({ width: '320px'}, 500); } else { $('.diff-tree-list').animate({ width: '0px'}, 'slow', function(){ $('.diff-tree-list').hide(); }); } return false; }; buttonAnchor.prepend('<button id="' + idTreeToggle + '" aria-label="Hide List Tree" type="button" class="btn btn-default pt-0 pb-0 d-flex align-items-center active" data-original-title="Hide List Tree" style="width:36px; height:36px; position:relative; top:44px;"> <i title="Toggle Tree Visibility" class="fa fa-coffee"></i> </button>'); $('#' + idTreeToggle).click(toggleTree); }; if (document.URL.indexOf('merge_requests') < 0) { $('#' + idConversations).remove(); $('#' + idTreeToggle).remove(); global.areButtonsAdded = false; } else { if (!global.areButtonsAdded) { global.areButtonsAdded = true; addConversationsButton(); tm.getContainer({ 'el': '.merge-request-tabs-holder', 'max': 100, 'spd': 1000 }).then(function($container){ addTreeToggleButton(); }); } } }, setAvatars: function () { tm.ping(avatarHost + pingPhoto + imageExt, function callback (response) { if (response === 'responded') { var avatarArray = [], thisName = 'none'; tm.getContainer({ 'el': '.participants-author' }).then(function($container){ _.each($('.participants-author img'), function (img) { thisName = properName( $(img).next().find('div').text() ); updateImg(img, thisName); }); }); tm.getContainer({ 'el': '.issuable-meta .author-link' }).then(function($container){ _.each($('.issuable-meta .author-link img'), function (img) { thisName = properName( $(img).next().text() ); updateImg(img, thisName); }); }); tm.getContainer({ 'el': '.author-link.inline' }).then(function($container){ _.each($('.author-link.inline img'), function (img) { thisName = properName( $(img).parent().prop('title') ); updateImg(img, thisName); }); }); tm.getContainer({ 'el': '.user-avatar-link' }).then(function($container){ _.each($('.user-avatar-link img'), function (img) { thisName = properName( $(img).prop('alt') ); updateImg(img, thisName); }); }); tm.getContainer({ 'el': '.header-user-dropdown-global' }).then(function($container){ _.each($('.header-user-dropdown-global img'), function (img) { thisName = properName( $(img).parent().prop('href') ); updateImg(img, thisName); }); }); tm.getContainer({ 'el': '.avatar-cell' }).then(function($container){ _.each($('.avatar-cell img'), function (img) { thisName = properName( $(img).prop('title') ); updateImg(img, thisName); }); }); tm.getContainer({ 'el': '.avatar-holder' }).then(function($container){ _.each($('.avatar-holder img'), function (img) { thisName = properName( $(img).parent().parent().next().find('.cover-title').text() ); updateImg(img, thisName); }); }); tm.getContainer({ 'el': '.list-item-name' }).then(function($container){ _.each($('.list-item-name img'), function (img) { thisName = properName( $(img).next().find('.member').text() ); updateImg(img, thisName); }); }); tm.getContainer({ 'el': '.user-popover' }).then(function($container){ _.each($('.user-popover img'), function (img) { thisName = properName( $(img).parent().parent().next().find('h5').text() ); updateImg(img, thisName); }); }); tm.getContainer({ 'el': '.system-note-image' }).then(function($container){ _.each($('.system-note-image img'), function (img) { thisName = properName( $(img).parent().prop('href') ); updateImg(img, thisName); }); }); } }); }, savePreferences: function () { GM_setValue('gitlabPrefs', JSON.stringify(global.prefs)); }, monitorTodos: function () { if (document.URL.indexOf('todos') < 0) return; // leave if not on the TODO page var indicateSecondsTimer, todosCount = $('.todos-count').text().replace(/(\r\n\t|\n|\r\t)/gm,''), notificationIcon = 'https://gitlab.dell.com/assets/favicon-7901bd695fb93edb07975966062049829afb56cf11511236e61bcf425070e36e.png', indicateSeconds = function() { document.title = todosCount + ' : (' + (Math.floor(global.reload.timespan/1000) - global.reload.lapsed) + ')'; global.reload.lapsed++; indicateSecondsTimer = setTimeout(indicateSeconds, 1000); }, triggerNotification = function(notifyMessage) { var notification = new Notification(notifyMessage, { icon: notificationIcon, body: todosCount }); } if (!global.todoMonitorInitialized) { global.todoMonitorInitialized = true; global.reload.lapsed = 0; var duration = moment.duration(moment().diff(global.prefs.todosTimestamp)); var hours = duration.asHours(); if (Number(todosCount) > 0 && hours > 1) { // trigger notification on hourly timeout if there ARE any triggerNotification('Reminder- GitLab TODOs:'); global.prefs.todosTimestamp = moment(); page.savePreferences(); } else if (Notification.permission === 'granted' && todosCount !== global.prefs.todosCount) { // trigger notification on TODO count change triggerNotification('TODOs on GitLab:'); } // update stored count if(todosCount !== global.prefs.todosCount) { global.prefs.todosCount = todosCount; page.savePreferences(); } // Reload in X seconds global.todoTimer = setTimeout(function() {window.location.reload(false);}, global.reload.timespan); var buttonAnchor = $('.page-title'); var buttonCancelReload = 'Cancel-Reload'; var timeoutElement = function () { clearTimeout(global.todoTimer); clearTimeout(indicateSecondsTimer); $('#' + buttonCancelReload).css('display', 'none'); document.title = global.reload.title; return false; }; buttonAnchor.after('<button id="' + buttonCancelReload + '" style="margin-left:50px; border-radius:15px; border:0px; background:lightgoldenrodyellow; padding:5px 15px; ">' + buttonCancelReload + '</button>'); $('#' + buttonCancelReload).click(timeoutElement); var buttonNotifyMe = 'Notify-Me'; var notifyMe = function() { if (Notification.permission !== "granted") Notification.requestPermission(); else { var notification = new Notification('Permission Granted', { icon: notificationIcon, body: "Notifications have been allowed.", }); // notification.onclick = function () { // window.open("http://stackoverflow.com/a/13328397/1269037"); // }; } $('#' + buttonNotifyMe).css('display', 'none'); return false; } if (Notification.permission !== 'granted') { buttonAnchor.after('<button id="' + buttonNotifyMe + '" style="margin-left:50px; border-radius:15px; border:0px; background:lightgrey; padding:5px 15px; ">' + buttonNotifyMe + '</button>'); $('#' + buttonNotifyMe).click(notifyMe); } setTimeout(indicateSeconds, 1000); } } }; /* * Global functions */ function initScript () { tm.getContainer({ 'el': '.content', 'max': 100, 'spd': 1000 }).then(function($container){ page.initialize(); }); } initScript(); $(document).mousemove(function(e) { if (!global.isMouseMoved) { global.isMouseMoved = true; setTimeout(function() { global.isMouseMoved = false; }, TIMEOUT * 2); initScript(); } }); })();