NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Gitlab Jobs Auto-width // @namespace http://tampermonkey.net/ // @version 0.12 // @description Redesigns Gitlab Pipeline UI So that Jobs are wide enough to see their full names. // @author mkielar // @license MIT // @match https://gitlab.com/*/-/pipelines/* // @grant GM_addStyle // ==/UserScript== (function() { 'use strict'; GM_addStyle (` .gl-w-full { width: unset !important; } .gl-w-13 { width: unset !important; margin-right: 8px; } span[data-testid="downstream-pipeline-label"]:nth-child(1) { margin-left: 22px; } span[data-testid="downstream-pipeline-label"]:not(:nth-child(1)) { margin-left: 2px; } button[data-qa-selector="expand_pipeline_button"] { right: -33px !important; top: -1px; bottom: -1px; border: 1px solid #dbdbdb !important; } div[data-qa-selector="child_pipeline"] { margin-right: 32px; } .ci-job-component, .ci-job-dropdown-container { margin-left: 40px; } .scrollable-menu .ci-job-component { margin-left: 30px; } button.dropdown-menu-toggle { width: unset !important } button.dropdown-menu-toggle div[data-qa-selector="job_item_container"] { margin-left: 0px; } .big-pipeline-graph-dropdown-menu { width: unset !important; max-width: unset !important; } .gl-ci-action-icon-container { left: 5px; } .gl-pipeline-job-width { width: auto !important; align-self: flex-start !important; } .mw-70p { max-width: unset !important; margin-right: 4px !important; } .gl-display-inline-block { max-width: unset !important; } .gl-w-70p { width: 100% !important; } button.dropdown-menu-toggle > div > div:not(:first-child) { margin-left: 4px; background-color: #f0f0f0; min-width: 24px; min-height: 24px; text-align: center; border-radius: 100% } button.dropdown-menu-toggle > div > div:not(:first-child):hover { background-color: black; color: white; } div[data-testid="stage-column-title"] div { margin-left: 40px; text-transform: lowercase !important; } .stage-name { text-transform: lowercase !important; } div.js-pipeline-graph > div { scroll-behavior: smooth } .gl-button.gl-button.btn-default .gl-icon, .gl-button.gl-button.btn-block.btn-default .gl-icon { color: #666; top: 0px; } `); function scrollToFirstUnfinished() { // The DIV with Scrollbar is actually first child of the 'js-pipeline-graph' DIV. let pipelineGraphContainer = document.getElementsByClassName("js-pipeline-graph")[0].firstChild // Find first element which is marked as failed or in-progress, otherwise find first that's created, then skipped. let target = pipelineGraphContainer.querySelector('[data-testid="status_running-icon"]') || pipelineGraphContainer.querySelector('[data-testid="status_pending-icon"]') || pipelineGraphContainer.querySelector('[data-testid="status_failed-icon"]') || pipelineGraphContainer.querySelector('[data-testid="status_created-icon"]') || pipelineGraphContainer.querySelector('[data-testid="status_skipped-icon"]') if (target) { let targetRect = target.getBoundingClientRect() let pipelineGraphContainerRect = pipelineGraphContainer.getBoundingClientRect() // Make sure we're scrolled vertically target.scrollIntoView({behavior: "smooth", block: "end", inline: "end"}) var isTargetVisible = (targetRect.left >= pipelineGraphContainerRect.left) && (targetRect.left <= pipelineGraphContainerRect.left + pipelineGraphContainer.clientHeight); if (!isTargetVisible) { // Scroll the pipelilne container horizontally pipelineGraphContainer.scrollLeft = (targetRect.left + pipelineGraphContainer.scrollLeft) - pipelineGraphContainerRect.left - 48 - 16 } } } const waitFor = (parent, ...selectors) => new Promise(resolve => { const delay = 500 const f = () => { const elements = selectors.map(selector => parent.querySelector(selector)) if (elements.some(element => element != null)) { resolve(elements) } else { setTimeout(f, delay) } } f() }) waitFor(document, '.js-pipeline-graph').then(([pipelineGraph]) => { waitFor(pipelineGraph, '[data-testid="status_running-icon"]', '[data-testid="status_pending-icon"]', '[data-testid="status_failed-icon"]', '[data-testid="status_created-icon"]', '[data-testid="status_skipped-icon"]').then(() => { scrollToFirstUnfinished() }) }) })();