import React from 'dom-chef'; import cache from 'webext-storage-cache'; import select from 'select-dom'; import * as pageDetect from 'github-url-detection'; import PullRequestIcon from 'octicon/git-pull-request.svg'; import features from '.'; import * as api from '../github-helpers/api'; import getDefaultBranch from '../github-helpers/get-default-branch'; import {buildRepoURL, getRepo} from '../github-helpers'; function getPRUrl(prNumber: number): string { return buildRepoURL('pull', prNumber, 'files'); } function getDropdown(prs: number[]): HTMLElement { // Markup copied from https://primer.style/css/components/dropdown return (
{prs.length}
); } function getSingleButton(prNumber: number, _?: number, prs?: number[]): HTMLElement { return ( #{prNumber} ); } /** @returns prsByFile {"filename1": [10, 3], "filename2": [2]} */ const getPrsByFile = cache.function(async (): Promise> => { const {repository} = await api.v4(` repository() { pullRequests( first: 25, states: OPEN, baseRefName: "${await getDefaultBranch()}", orderBy: { field: UPDATED_AT, direction: DESC } ) { nodes { number files(first: 100) { nodes { path } } } } } `); const files: Record = {}; for (const pr of repository.pullRequests.nodes) { for (const {path} of pr.files.nodes) { files[path] = files[path] || []; if (files[path].length < 10) { files[path].push(pr.number); } } } return files; }, { maxAge: {hours: 2}, staleWhileRevalidate: {days: 9}, cacheKey: () => __filebasename + ':' + getRepo()!.nameWithOwner }); async function init(): Promise { // `clipboard-copy` on blob page, `#blob-edit-path` on edit page const path = select('clipboard-copy, #blob-edit-path')!.getAttribute('value')!; const {[path]: prs} = await getPrsByFile(); if (!prs) { return; } const [prNumber] = prs; // First one or only one if (pageDetect.isEditingFile()) { select('.file')!.after(
{ prs.length === 1 ? <>Careful, PR #{prNumber} is already touching this file : <> Careful, {prs.length} open PRs are already touching this file {prs.map(getSingleButton)} }
); return; } if (prs.length > 1) { select('.breadcrumb')!.before(getDropdown(prs)); return; } const link = getSingleButton(prNumber); link.classList.add('ml-2', 'tooltipped', 'tooltipped-ne'); link.setAttribute('aria-label', `This file is touched by PR #${prNumber}`); select('.breadcrumb')!.before(link); } void features.add(__filebasename, { include: [ pageDetect.isEditingFile, pageDetect.isSingleFile ], init });