gitlab duplicate button

a simply tool to rapidly duplicate pipeline schedule

Versione datata 13/03/2025. Vedi la nuova versione l'ultima versione.

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name         gitlab duplicate button
// @description  a simply tool to rapidly duplicate pipeline schedule
// @match        https://gitlab.com/*/pipeline_schedules*
// @match        https://*.gitlab.com/*/pipeline_schedules*
// @grant        GM_log
// @author       FrogChopi
// @version      1
// @run-at       document-end
// @license GNU
// @namespace https://greasyfork.org/users/1445314
// ==/UserScript==

!async function(){"use strict";let e=document.createElement("style");e.innerText="\n        .modal {\n            position: fixed;\n            top: 0;\n            left: 0;\n            z-index: 1050;\n            width: 100%;\n            height: 100%;\n            overflow: hidden;\n            outline: 0;\n            background-color: rgba(0, 0, 0, 0.5);\n            display: flex;\n            align-items: center;\n            justify-content: center;\n        }\n\n        .modal-dialog {\n            position: relative;\n            width: auto;\n            margin: 0.5rem;\n            pointer-events: none;\n            max-width: 500px;\n        }\n\n        .modal-content {\n            position: relative;\n            display: flex;\n            flex-direction: column;\n            width: 100%;\n            pointer-events: auto;\n            background-color: #fff;\n            background-clip: padding-box;\n            border: 1px solid rgba(0, 0, 0, 0.2);\n            border-radius: 0.3rem;\n            outline: 0;\n        }\n\n        .modal-header {\n            display: flex;\n            align-items: flex-start;\n            justify-content: space-between;\n            padding: 1rem;\n            border-bottom: 1px solid #dee2e6;\n            border-top-left-radius: 0.3rem;\n            border-top-right-radius: 0.3rem;\n        }\n\n        .modal-title {\n            margin-bottom: 0;\n            line-height: 1.5;\n            font-size: 1.25rem;\n        }\n\n        .close {\n            float: right;\n            font-size: 1.5rem;\n            font-weight: 700;\n            line-height: 1;\n            color: #000;\n            text-shadow: 0 1px 0 #fff;\n            opacity: .5;\n            padding: 1rem;\n            margin: -1rem -1rem -1rem auto;\n            background-color: transparent;\n            border: 0;\n        }\n\n        .modal-body {\n            position: relative;\n            flex: 1 1 auto;\n            padding: 1rem;\n        }\n\n        .modal-footer {\n            display: flex;\n            flex-wrap: wrap;\n            align-items: center;\n            justify-content: flex-end;\n            padding: 0.75rem;\n            border-top: 1px solid #dee2e6;\n            border-bottom-right-radius: 0.3rem;\n            border-bottom-left-radius: 0.3rem;\n        }\n    ",document.head.appendChild(e);let n=async function(e,n,t,o,a){return new Promise(((i,l)=>{let d={method:e,headers:o,credentials:"same-origin"};a&&(d.body=JSON.stringify(a)),fetch(`https://${n}${t}`,d).then((e=>e.json())).then((e=>{i(e)})).catch((e=>l(e)))}))};var t;await(t='a[data-testid="edit-pipeline-schedule-btn"]',new Promise((e=>{const o=new MutationObserver((a=>{document.querySelector(t)&&(document.querySelectorAll('a[data-testid="edit-pipeline-schedule-btn"]').forEach((e=>{let t=e.href.match(/(\d+)$/)[1];var o=document.createElement("BUTTON"),a=document.createElement("IMG");o.className="btn btn-default btn-md gl-button btn-icon",a.className="gl-button-icon gl-icon s16 gl-fill-current",a.src="https://cdn-icons-png.flaticon.com/512/1621/1621635.png",o.appendChild(a),o.id=t,o.title="Duplicate scheduled pipeline",o.ariaLabel="Duplicate scheduled pipeline",o.onclick=async()=>{let e=await n("GET",document.location.host,`/api/v4/projects/${+document.body.getAttribute("data-project-id")}/pipeline_schedules/${t}`,{"Content-Type":"application/json"},void 0),o=document.createElement("DIV");o.innerHTML=`\n                  <div class="modal" tabindex="-1" role="dialog">\n            <div class="modal-dialog" role="document">\n                <div class="modal-content">\n                <div class="modal-header">\n                    <h5 class="modal-title">Modal title</h5>\n                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">\n                    <span aria-hidden="true">&times;</span>\n                    </button>\n                </div>\n                <div class="modal-body">\n                    <h5>New schedule name</h5>\n                    <div class="input-group mb-3">\n                        <div class="input-group-prepend">\n                            <span class="input-group-text" id="basic-addon1">@</span>\n                        </div>\n                        <input type="text" class="form-control" placeholder="New schedule name" aria-label="New schedule name" value="${e.description}" aria-describedby="basic-addon1">\n                    </div>\n                    <h6>Are you sure you want to duplicate this scheduled pipeline?</h6>\n                </div>\n                <div class="modal-footer">\n                    <button type="button" aria-label="Duplicate" class="btn btn-primary">Duplicate scheduled pipeline</button>\n                    <button type="button" aria-label="Cancel" class="btn btn-secondary" data-dismiss="modal">Cancel</button>\n                </div>\n                </div>\n            </div>\n            </div>\n            `,o.querySelector('button[aria-label="Close"]').onclick=()=>o.remove(),o.querySelector('button[aria-label="Cancel"]').onclick=()=>o.remove(),o.querySelector('button[aria-label="Duplicate"]').onclick=async()=>{if(o.querySelector('input[aria-label="New schedule name"]').value==e.description)alert("The new schedule name can't be the same !");else{let t={description:o.querySelector('input[aria-label="New schedule name"]').value,ref:e.ref,cron:e.cron,cron_timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,active:!1,variables:e.variables},a=(await n("POST",document.location.host,`/api/v4/projects/${document.body.getAttribute("data-project-id")}/pipeline_schedules`,{"Content-Type":"application/json","X-CSRF-Token":document.querySelector('meta[name="csrf-token"]').content},t)).id;for(let t=0;t<e.variables.length;t++)n("POST",document.location.host,`/api/v4/projects/${document.body.getAttribute("data-project-id")}/pipeline_schedules/${a}/variables`,{"Content-Type":"application/json","X-CSRF-Token":document.querySelector('meta[name="csrf-token"]').content},e.variables[t]);window.location.replace(`${window.location.origin}${window.location.pathname}/${a}/edit?id=${a}`)}},document.body.appendChild(o)},e.parentNode.insertBefore(o,e.parentNode.lastChild)})),e(document.querySelector(t)),o.disconnect())}));o.observe(document.body,{childList:!0,subtree:!0})})))}();