Zeigt alle Projekte für alle Organisationen
Verze ze dne
- // ==UserScript==
- // @name DevOps Projects Overview
- // @namespace Violentmonkey Scripts
- // @match https://dev.azure.com/*
- // @grant none
- // @version 1.0.2
- // @author Der_Floh
- // @description Zeigt alle Projekte für alle Organisationen
- // @license MIT
- // @icon https://www.svgrepo.com/show/448271/azure-devops.svg
- // @homepageURL https://greatest.deepsurf.us/de/scripts/469631-evalea-dsgvo-test-solver
- // @supportURL https://greatest.deepsurf.us/de/scripts/469631-evalea-dsgvo-test-solver/feedback
- // ==/UserScript==
- // jshint esversion: 8
- window.addEventListener('load', async () => {
- if (window.location.toString().endsWith('?projectonly')) {
- addErrorHideCss();
- convertToProjectOnly();
- } else if (window.location.toString().endsWith('?default')) {
- return;
- } else {
- addErrorHideCss();
- showAllProjects();
- }
- });
- async function showAllProjects() {
- const navigation = await waitForElementToExistQuery(document.body, 'div[class*="top-level-navigation"][role="navigation"]');
- const showMoreButton = await waitForElementToExistQuery(navigation, 'span[class*="action-link top-navigation-item"][role="button"]');
- if (showMoreButton)
- showMoreButton.click();
- const projectsContainer = await waitForElementToExistId('skip-to-main-content');
- const currentProject = await waitForElementToExistQuery(projectsContainer, 'li[class="project-card flex-row flex-grow"]');
- const container = currentProject.parentNode;
- container.classList.add('wrap-ul');
- addWrapUlCss();
- await addProjectCards(container);
- }
- function addWrapUlCss() {
- const css = `
- ul.wrap-ul {
- display: flex;
- flex-wrap: wrap;
- padding: 0;
- list-style-type: none;
- margin: 0;
- }
- ul.wrap-ul li,
- ul.wrap-ul iframe {
- flex: 1 1 auto;
- margin: 5px;
- box-sizing: border-box;
- }
- `;
- const style = document.createElement('style');
- style.type = 'text/css';
- style.innerHTML = css;
- document.head.appendChild(style);
- }
- function addErrorHideCss() {
- const css = `
- .tfs-unhandled-error {
- display: none;
- }
- `;
- const style = document.createElement('style');
- style.type = 'text/css';
- style.innerHTML = css;
- document.head.appendChild(style);
- }
- async function convertToProjectOnly() {
- const projectsContainer = await waitForElementToExistId('skip-to-main-content');
- const currentProject = await waitForElementToExistQuery(projectsContainer, 'li[class="project-card flex-row flex-grow"]');
- const container = currentProject.parentNode.parentNode;
- container.style.height = '100%';
- container.firstChild.style.height = '100%';
- container.firstChild.firstChild.style.height = '100%';
- container.firstChild.firstChild.firstChild.style.height = '100%';
- container.firstChild.firstChild.firstChild.firstChild.style.height = '100%';
- const projectName = currentProject.querySelector('div[class*="project-name"]').textContent;
- container.onclick = (event) => {
- event.preventDefault();
- const url = `https://dev.azure.com/${window.frameElement.getAttribute('name')}/${projectName}`;
- window.open(url, '_blank');
- };
- keepOnlyElementAndAncestors(container);
- }
- function keepOnlyElementAndAncestors(element) {
- const elementsToKeep = new Set();
- let currentElement = element;
- while (currentElement) {
- elementsToKeep.add(currentElement);
- currentElement = currentElement.parentElement;
- }
- function addDescendantsToSet(element) {
- elementsToKeep.add(element);
- Array.from(element.children).forEach(child => {
- addDescendantsToSet(child);
- });
- }
- addDescendantsToSet(element);
- const allElements = document.body.getElementsByTagName('*');
- Array.from(allElements).forEach(el => {
- if (!elementsToKeep.has(el)) {
- el.remove();
- }
- });
- }
- async function addProjectCards(baseNode) {
- const projectCards = [];
- await waitForElementToExistQuery(document.body, 'a[class*="host-link navigation-link"][role="option"]');
- const projects = Array.from(document.body.querySelectorAll('a[class*="host-link navigation-link"][role="option"]'));
- projects.shift();
- for (const project of projects) {
- if (project.href.startsWith('https://dev.azure.com'))
- createIFrameForProject(baseNode, project);
- }
- }
- function createIFrameForProject(baseNode, project) {
- const iframe = document.createElement('iframe');
- iframe.id = project.id.replace('__bolt-host-', 'project_');
- iframe.setAttribute('name', project.querySelector('span').textContent);
- iframe.src = project.href + '?projectonly';
- iframe.style.border = 'none';
- baseNode.appendChild(iframe);
- }
- async function waitForElementToExistId(elementId) {
- return new Promise(async (resolve) => {
- async function checkElement() {
- const element = document.getElementById(elementId);
- if (element !== null)
- resolve(element);
- else
- setTimeout(checkElement, 100);
- }
- await checkElement();
- });
- }
- async function waitForElementToExistQuery(baseNode, query, timeout = 2000) {
- return new Promise((resolve, reject) => {
- const startTime = Date.now();
- async function checkElement() {
- const element = baseNode.querySelector(query);
- if (element !== null) {
- resolve(element);
- } else {
- if (Date.now() - startTime > timeout) {
- reject(new Error(`Timeout: Element with query '${query}' did not appear within ${timeout}ms`));
- } else {
- setTimeout(checkElement, 100);
- }
- }
- }
- checkElement();
- });
- }