-
-
Save fuunnx/de64bce091596db4ddba73c6d805d2a7 to your computer and use it in GitHub Desktop.
Test lolilol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Coucou |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name nxtension-bundle | |
// @namespace https://nartex.fr | |
// @version 1.3.3 | |
// @description copy-title-to-clipboard | issue-transfer | iteration-transfer | us_amendments | |
// @author Géraud Henrion, Joël Bohrer | |
// @match https://*.projects.nartex.fr/*/-/* | |
// @match https://*.support.nartex.fr/*/-/* | |
// @icon https://www.nartex.fr/wp-nartex/themes/nartex/favicon.png | |
// @grant none | |
// @updateURL https://gist.github.com/fuunnx/7a76571b259f9c7e05ce8ba09fe07cc7/raw/copy-title-to-clipboard.user.js | |
// @downloadURL https://gist.github.com/fuunnx/7a76571b259f9c7e05ce8ba09fe07cc7/raw/copy-title-to-clipboard.user.js | |
// ==/UserScript== | |
(function () { | |
'use strict'; | |
// ==UserScript== | |
// @name nxtension-copy-title-to-clipboard | |
// @namespace https://projects.nartex.fr/nartex/web/nx-calendar | |
// @version 0.13 | |
// @description Add a "copy title and link" button to Gitlab issues and MR | |
// @author Géraud Henrion | |
// @match https://*.projects.nartex.fr/*/-/* | |
// @match https://*.support.nartex.fr/*/-/* | |
// @icon https://www.nartex.fr/wp-nartex/themes/nartex/favicon.png | |
// @grant none | |
// @updateURL https://gist.github.com/fuunnx/7a76571b259f9c7e05ce8ba09fe07cc7/raw/copy-title-to-clipboard.user.js | |
// @downloadURL https://gist.github.com/fuunnx/7a76571b259f9c7e05ce8ba09fe07cc7/raw/copy-title-to-clipboard.user.js | |
// ==/UserScript== | |
(async function () { | |
const titleElement = document.querySelector('h1'); | |
if (!titleElement) return | |
const title = titleElement.innerText.trim(); | |
const url = window.location.href; | |
const buttonTitle = 'Copier le titre et le lien du ticket'; | |
const container = document.createElement('div'); | |
container.innerHTML = ` | |
<button | |
class="gl-button btn btn-icon btn-sm btn-default btn-default-tertiary gl-display-none! gl-md-display-inline-block!" | |
title=${JSON.stringify(buttonTitle)} | |
aria-label=${JSON.stringify(buttonTitle)} | |
aria-live="polite" | |
data-toggle="tooltip" | |
data-placement="bottom" | |
data-container="body" | |
data-clipboard-text=${JSON.stringify( | |
`[${title.replaceAll('"', '"')}](${url})`, | |
)} | |
type="button" | |
> | |
<svg class="s16 gl-icon gl-button-icon " data-testid="copy-to-clipboard-icon"><use href="/assets/icons-8791a66659d025e0a4c801978c79a1fbd82db1d27d85f044a35728ea7cf0ae80.svg#copy-to-clipboard"></use></svg> | |
</button> | |
`; | |
const button = container.children[0]; | |
if (!button) return | |
titleElement?.appendChild(button); | |
})(); | |
// ==UserScript== | |
// @name nxtension-issue-transfer | |
// @namespace https://projects.nartex.fr/nartex/web/nx-calendar | |
// @version 0.11 | |
// @description Add a transfer button to Gitlab Support | |
// @author Géraud Henrion | |
// @match https://*.support.nartex.fr/*/-/issues/* | |
// @icon https://www.nartex.fr/wp-nartex/themes/nartex/favicon.png | |
// @grant none | |
// @updateURL https://gist.github.com/fuunnx/7a76571b259f9c7e05ce8ba09fe07cc7/raw/issue-transfer.user.js | |
// @downloadURL https://gist.github.com/fuunnx/7a76571b259f9c7e05ce8ba09fe07cc7/raw/issue-transfer.user.js | |
// ==/UserScript== | |
(async function () { | |
addStyle(` | |
.detail-page-header-actions { | |
flex-wrap: wrap; | |
justify-content: flex-end; | |
max-width: 50%; | |
} | |
`); | |
const config = { | |
GITLAB_PROJECTS_URL: 'https://projects.nartex.fr/nartex', | |
API_URL: window.location.origin + '/api/v4', | |
APP_DESIGN_CONFIG_URL: 'https://tests.nartex.fr/nxtension', | |
}; | |
const projectId = document.body.getAttribute('data-project-id'); | |
const issueIid = location.pathname.split('/').slice(-1)[0]; | |
const currentIssue = await fetch( | |
`${config.API_URL}/projects/${projectId}/issues?iids[]=${issueIid}`, | |
) | |
.then((x) => x.json()) | |
.then((x) => x[0]); | |
const projectsMap = await fetch( | |
`${config.APP_DESIGN_CONFIG_URL}/list.json`, | |
).then((res) => res.json()); | |
let targetProjectUrl = projectsMap[projectId]; | |
Button({ | |
label: targetProjectUrl ? 'Transférer' : 'Transférer*', | |
href: targetProjectUrl ? buildHref(targetProjectUrl, currentIssue) : '#', | |
async onClick(event) { | |
if (targetProjectUrl) return | |
else event.preventDefault(); | |
targetProjectUrl = window.prompt(`Quelle est l'url du projet app-design ? | |
Exemple : | |
${config.GITLAB_PROJECTS_URL}/<client>/<projet>/app-design | |
ATTENTION À NE PAS FAIRE D'ERREUR À LA SAISIE :) | |
`); | |
if (!targetProjectUrl) return | |
// TODO check url validity | |
const opened = window.open( | |
buildHref(targetProjectUrl, currentIssue), | |
'_blank', | |
); | |
const body = new FormData(); | |
body.append('support_id', projectId); | |
body.append('url', targetProjectUrl); | |
await fetch(`${config.APP_DESIGN_CONFIG_URL}/nxtension.php`, { | |
method: 'POST', | |
body, | |
}); | |
if (opened) { | |
window.location.reload(); | |
} else { | |
alert("Merci d'autoriser les popups"); | |
} | |
}, | |
}); | |
function buildHref(destUrl, issue) { | |
const title = `[Support] #${issue.iid} : ${issue.title}`; | |
const description = ` | |
${issue.web_url} : | |
${issue.description | |
.split('\n') | |
.map((line) => `> ${line}`) | |
.join('\n')} | |
/label ~"Support" | |
`; | |
return `${destUrl}/-/issues/new?issue[title]=${encodeURIComponent( | |
title, | |
)}&issue[description]=${encodeURIComponent(description)}` | |
} | |
function Button(props) { | |
const { href, label, onClick } = props; | |
const editButton = document.querySelector('[data-testid="edit-button"]'); | |
const transferButton = document.createElement('a'); | |
transferButton.className = editButton.className; | |
transferButton.style.setProperty('display', 'flex', 'important'); | |
transferButton.innerHTML = `<span class="gl-button-text">${label}</span>`; | |
transferButton.title = label; | |
transferButton.setAttribute('aria-label', label); | |
transferButton.onclick = onClick; | |
transferButton.href = href; | |
transferButton.target = '_blank'; | |
editButton.parentElement.insertBefore(transferButton, editButton); | |
} | |
function addStyle(styleSheetContent = '') { | |
const styleTag = document.createElement('style'); | |
styleTag.innerText = styleSheetContent; | |
document.head.appendChild(styleTag); | |
} | |
})(); | |
// ==UserScript== | |
// @name nxtension-iteration-transfer | |
// @namespace https://projects.nartex.fr/nartex/web/nx-calendar | |
// @version 0.16 | |
// @description Add a "transfer to current iteration" button to Gitlab | |
// @author Géraud Henrion | |
// @match https://*.projects.nartex.fr/*/-/issues/* | |
// @icon https://www.nartex.fr/wp-nartex/themes/nartex/favicon.png | |
// @grant none | |
// @updateURL https://gist.github.com/fuunnx/7a76571b259f9c7e05ce8ba09fe07cc7/raw/iteration-transfer.user.js | |
// @downloadURL https://gist.github.com/fuunnx/7a76571b259f9c7e05ce8ba09fe07cc7/raw/iteration-transfer.user.js | |
// ==/UserScript== | |
(async function () { | |
addStyle(` | |
.detail-page-header-actions { | |
flex-wrap: wrap; | |
justify-content: flex-end; | |
max-width: 50%; | |
} | |
`); | |
const context = { | |
projectId: document.body.getAttribute('data-project-id'), | |
issueIid: location.pathname.split('/').slice(-1)[0], | |
projectRootUrl: window.location.pathname.split('/-/')[0], | |
}; | |
const commands = Commands(); | |
const api = Api(window.location.origin + '/api/v4', context); | |
run(); | |
async function run() { | |
let currentIssue = await api.findIssueByIid(context.issueIid); | |
const iterations = await api.getOpenedIterations(); | |
const nextIteration = iterations.find( | |
(iteration) => new Date(iteration.start_date).getTime() > Date.now(), | |
); | |
const currentIteration = iterations.find( | |
(iteration) => new Date(iteration.start_date).getTime() < Date.now(), | |
); | |
const isCurrentIteration = | |
currentIssue.iteration?.id === currentIteration?.id; | |
const isNextIteration = currentIssue.iteration?.id === nextIteration?.id; | |
if (!isCurrentIteration && currentIteration) { | |
TransferButton({ | |
targetIteration: currentIteration, | |
label: '⬇️ Vers itér. courante', | |
}); | |
} | |
if (!isNextIteration && nextIteration) { | |
TransferButton({ | |
targetIteration: nextIteration, | |
label: '⤵️ Itér. suivante', | |
}); | |
} | |
TransferButton({ | |
targetIteration: undefined, | |
addLabels: ['En attente'], | |
label: '⏸️ Mettre en attente', | |
}); | |
function TransferButton(props) { | |
const { targetIteration, label, addLabels } = props; | |
async function runTransfer() { | |
// Get up to date version | |
currentIssue = await api.findIssueByIid(context.issueIid); | |
const totalSpent = currentIssue.time_stats.total_time_spent; | |
const remaining = currentIssue.time_stats.time_estimate - totalSpent; // seconds | |
const shouldClone = | |
totalSpent && (currentIssue.iteration || !targetIteration); | |
if (!shouldClone) { | |
await api.applyCommands(currentIssue.id, [ | |
targetIteration && commands.setIteration(targetIteration.id), | |
]); | |
return | |
} | |
await api.applyCommands(currentIssue.id, [commands.clone()]); | |
await Promise.all([ | |
await api.getLatestClone(currentIssue).then((clonedIssue) => { | |
return api.applyCommands(clonedIssue.id, [ | |
commands.setEstimate(totalSpent), | |
commands.addTimeSpent(totalSpent), | |
commands.close(), | |
]) | |
}), | |
api.applyCommands(currentIssue.id, [ | |
commands.removeTimeSpent(), | |
commands.setEstimate(remaining), | |
targetIteration && commands.setIteration(targetIteration.id), | |
]), | |
]); | |
} | |
const button = Button({ | |
label, | |
async onClick(event) { | |
event.preventDefault(); | |
button.setAttribute('disabled', true); | |
await runTransfer(); | |
await api.applyCommands(currentIssue.id, [ | |
commands.addLabels(addLabels), | |
]); | |
button.removeAttribute('disabled'); | |
if (targetIteration) { | |
button.parentElement.removeChild(button); | |
} | |
}, | |
}); | |
} | |
} | |
function Button(props) { | |
const { label, onClick } = props; | |
const editButton = document.querySelector('[data-testid="edit-button"]'); | |
const transferButton = document.createElement('button'); | |
transferButton.className = editButton.className; | |
transferButton.innerText = label; | |
transferButton.title = label; | |
transferButton.setAttribute('aria-label', label); | |
transferButton.onclick = onClick; | |
transferButton.target = '_blank'; | |
editButton.parentElement.insertBefore(transferButton, editButton); | |
return transferButton | |
} | |
function Api(apiUrl, params) { | |
const instance = { | |
async findIssueByIid(iid) { | |
return await fetch( | |
`${apiUrl}/projects/${params.projectId}/issues?iids[]=${iid}`, | |
) | |
.then((x) => x.json()) | |
.then((x) => x[0]) | |
}, | |
async getOpenedIterations() { | |
return await fetch( | |
`${apiUrl}/projects/${params.projectId}/iterations?state=opened`, | |
).then((x) => x.json()) | |
}, | |
async getLatestClone(issue) { | |
const notes = await fetch(issue._links.notes).then((res) => res.json()); | |
// ordered by "most recent notes first" | |
const clonedIssueNote = notes.find((note) => | |
note.body.startsWith('cloned to #'), | |
); | |
const clonedIssueIid = clonedIssueNote.body.replace('cloned to #', ''); | |
return await instance.findIssueByIid(clonedIssueIid) | |
}, | |
async applyCommands(issueId, commandsToApply) { | |
commandsToApply = commandsToApply.filter(Boolean); | |
if (!commandsToApply.length) return | |
await fetch( | |
`${params.projectRootUrl}/notes?target_id=${issueId}&target_type=issue`, | |
{ | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
'X-CSRF-Token': getCsrf(), | |
}, | |
body: JSON.stringify({ | |
note: { | |
confidential: false, | |
note: commandsToApply.join('\n'), | |
noteable_id: issueId, | |
noteable_type: 'issue', | |
}, | |
}), | |
}, | |
); | |
function getCsrf() { | |
return document | |
.querySelector('meta[name=csrf-token]') | |
?.getAttribute('content') | |
} | |
}, | |
}; | |
return instance | |
} | |
function Commands() { | |
return { | |
setIteration(iterationId) { | |
if (!iterationId) return | |
return `/iteration *iteration:${iterationId}` | |
}, | |
close() { | |
return '/close' | |
}, | |
clone() { | |
return '/clone' | |
}, | |
setEstimate(estimationInSeconds) { | |
if (estimationInSeconds > 0) { | |
return `/estimate ${estimationInSeconds / 60}m` | |
} | |
return '/remove_estimate' | |
}, | |
addTimeSpent(estimationInSeconds) { | |
if (!estimationInSeconds) return | |
return `/spend ${estimationInSeconds / 60}m` | |
}, | |
removeTimeSpent() { | |
return '/remove_time_spent' | |
}, | |
addLabels(labels = []) { | |
if (!labels?.length) return | |
return `/label ${labels.map((l) => `~${JSON.stringify(l)}`)}` | |
}, | |
} | |
} | |
function addStyle(styleSheetContent = '') { | |
const styleTag = document.createElement('style'); | |
styleTag.innerText = styleSheetContent; | |
document.head.appendChild(styleTag); | |
} | |
})(); | |
// ==UserScript== | |
// @name New Userscript | |
// @namespace http://tampermonkey.net/ | |
// @version 2024-10-09 | |
// @description try to take over the world! | |
// @author You | |
// @match https://projects.nartex.fr/nartex/*/*/app-design/-/wikis/us/* | |
// @icon https://www.google.com/s2/favicons?sz=64&domain=freecodecamp.org | |
// @grant none | |
// ==/UserScript== | |
async function check() { | |
const links = document.querySelectorAll('a.gfm-issue'); | |
links.forEach(async (l) => { | |
const project_id = parseInt(l.getAttribute('data-project'), 10); | |
const response = await fetch( | |
`https://projects.nartex.fr/api/v4/projects/${project_id}/issues/${l.getAttribute( | |
'data-iid', | |
)}/links`, | |
); | |
const linked_issues = await response.json(); | |
const amendments = linked_issues | |
.filter((i) => i.project_id === project_id) | |
.map((i) => { | |
return { iid: i.iid, title: i.title, url: i.web_url } | |
}); | |
if (amendments.length) { | |
const p = document.createElement('p'); | |
p.innerHTML = `<b>ATTENTION : les tickets suivants peuvent modifier ces spécifications :</b><ol>${amendments | |
.map( | |
(t) => `<li><a href="${t.url}" target="_blank">${t.title}</a></li>`, | |
) | |
.join('\n')}</ol>`; | |
l.parentElement.after(p); | |
} | |
}); | |
} | |
(function () { | |
setTimeout(check, 3000); | |
})(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment