summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--readme.md2
-rw-r--r--source/features/first-published-tag-for-merged-pr.tsx72
-rw-r--r--source/features/quick-comment-edit.tsx3
-rw-r--r--source/github-events/on-pr-merge.ts12
-rw-r--r--source/github-helpers/timeline-item.tsx6
5 files changed, 81 insertions, 14 deletions
diff --git a/readme.md b/readme.md
index 2409c8db..33dc5908 100644
--- a/readme.md
+++ b/readme.md
@@ -271,7 +271,7 @@ Thanks for contributing! 🦋🙌
- [](# "pr-commit-lines-changed") [Adds diff stats on PR commits.](https://user-images.githubusercontent.com/16872793/76107253-48deeb00-5fa6-11ea-9931-721cde553bdf.png)
- [](# "cross-deleted-pr-branches") [Adds a line-through to the deleted branches in PRs.](https://user-images.githubusercontent.com/16872793/75619638-9bef1300-5b4c-11ea-850e-3a8f95c86d83.png)
- [](# "batch-mark-files-as-viewed") [Mark/unmark multiple files as “Viewed” in the PR Files tab. Click on the first checkbox you want to mark/unmark and then `shift`-click another one; all the files between the two checkboxes will be marked/unmarked as “Viewed”.](https://user-images.githubusercontent.com/1402241/79343285-854f2080-7f2e-11ea-8d4c-a9dc163be9be.gif)
-- [](# "first-published-tag-for-merged-pr") 🔥 [Shows the first Git tag a merged PR was included in.](https://user-images.githubusercontent.com/1402241/169497171-85d4a97f-413a-41b4-84ba-885dca2b51cf.png)
+- [](# "first-published-tag-for-merged-pr") 🔥 [Shows the first Git tag a merged PR was included in or suggests creating a release if not yet released.](https://user-images.githubusercontent.com/1402241/169497171-85d4a97f-413a-41b4-84ba-885dca2b51cf.png)
- [](# "pr-jump-to-first-non-viewed-file") [Jumps to first non-viewed file in a pull request when clicking on the progress bar.](https://user-images.githubusercontent.com/16872793/85226580-3bf3d500-b3a6-11ea-8494-3d9b6280d033.gif)
- [](# "git-checkout-pr") [Adds copy-pastable git commands to checkout a PR.](https://user-images.githubusercontent.com/16872793/96938908-8e024f80-1499-11eb-8976-0caf95175dd6.png)
- [](# "jump-to-change-requested-comment") [Adds a link to jump to the latest changed requested comment.](https://user-images.githubusercontent.com/19198931/98718312-418b9f00-23c9-11eb-8da2-dfb616e95eb6.gif)
diff --git a/source/features/first-published-tag-for-merged-pr.tsx b/source/features/first-published-tag-for-merged-pr.tsx
index 5b7f683e..75310ea8 100644
--- a/source/features/first-published-tag-for-merged-pr.tsx
+++ b/source/features/first-published-tag-for-merged-pr.tsx
@@ -6,9 +6,16 @@ import * as pageDetect from 'github-url-detection';
import features from '.';
import fetchDom from '../helpers/fetch-dom';
+import onPrMerge from '../github-events/on-pr-merge';
+import TimelineItem from '../github-helpers/timeline-item';
+import attachElement from '../helpers/attach-element';
+import {canEditEveryComment} from './quick-comment-edit';
import {buildRepoURL, getRepo} from '../github-helpers';
import onConversationHeaderUpdate from '../github-events/on-conversation-header-update';
+// TODO: Not an exact match; Moderators can edit comments but not create releases
+const canCreateRelease = canEditEveryComment;
+
const getFirstTag = cache.function(async (commit: string): Promise<string | undefined> => {
const firstTag = await fetchDom(
buildRepoURL('branch_commits', commit),
@@ -24,10 +31,14 @@ async function init(): Promise<void> {
const mergeCommit = select(`.TimelineItem.js-details-container.Details a[href^="/${getRepo()!.nameWithOwner}/commit/" i] > code`)!.textContent!;
const tagName = await getFirstTag(mergeCommit);
- if (!tagName) {
- return;
+ if (tagName) {
+ addExistingTagLink(tagName);
+ } else if (canCreateRelease()) {
+ addLinkToCreateRelease('This PR doesn’t appear to have been released yet');
}
+}
+function addExistingTagLink(tagName: string): void {
const tagUrl = buildRepoURL('releases/tag', tagName);
// Select the PR header and sticky header
@@ -48,25 +59,62 @@ async function init(): Promise<void> {
);
}
- select(':not(.rgh-first-tag) + #issue-comment-box')?.before(
- <div className="flash mt-3 flash-success rgh-first-tag">
- The PR first appeared in <span className="text-mono text-small">{tagName}</span>
- <a href={tagUrl} className="btn btn-sm flash-action">
- <TagIcon/> See release
- </a>
- </div>,
- );
+ attachElement({
+ anchor: '#issue-comment-box',
+ position: 'before',
+ getNewElement: () => (
+ <TimelineItem>
+ <div className="flash flash-success">
+ The PR first appeared in <span className="text-mono text-small">{tagName}</span>
+ <a href={tagUrl} className="btn btn-sm flash-action">
+ <TagIcon/> See release
+ </a>
+ </div>
+ </TimelineItem>
+ ),
+ });
+}
+
+function addLinkToCreateRelease(text = 'Now you can release this change'): void {
+ attachElement({
+ anchor: '#issue-comment-box',
+ position: 'before',
+ getNewElement: () => (
+ <TimelineItem>
+ <div className="flash">
+ {text}
+ <a href={buildRepoURL('releases/new')} className="btn btn-sm flash-action">
+ <TagIcon/> Draft a new release
+ </a>
+ </div>
+ </TimelineItem>
+ ),
+ });
}
void features.add(import.meta.url, {
- include: [
- () => pageDetect.isPRConversation() && pageDetect.isMergedPR(),
+ asLongAs: [
+ pageDetect.isPRConversation,
+ pageDetect.isMergedPR,
],
additionalListeners: [
onConversationHeaderUpdate,
],
deduplicate: 'has-rgh-inner',
init,
+}, {
+ asLongAs: [
+ pageDetect.isPRConversation,
+ pageDetect.isOpenPR,
+ canCreateRelease,
+ ],
+ additionalListeners: [
+ onPrMerge,
+ ],
+ onlyAdditionalListeners: true,
+ init() {
+ addLinkToCreateRelease();
+ },
});
/*
diff --git a/source/features/quick-comment-edit.tsx b/source/features/quick-comment-edit.tsx
index ec2ec9ca..9e9e4957 100644
--- a/source/features/quick-comment-edit.tsx
+++ b/source/features/quick-comment-edit.tsx
@@ -28,7 +28,8 @@ function addQuickEditButton(commentForm: Element): void {
);
}
-function canEditEveryComment(): boolean {
+// eslint-disable-next-line import/prefer-default-export
+export function canEditEveryComment(): boolean {
return select.exists([
// If you can lock conversations, you have write access
'.lock-toggle-link > .octicon-lock',
diff --git a/source/github-events/on-pr-merge.ts b/source/github-events/on-pr-merge.ts
new file mode 100644
index 00000000..7d76c2ad
--- /dev/null
+++ b/source/github-events/on-pr-merge.ts
@@ -0,0 +1,12 @@
+import select from 'select-dom';
+
+import observeElement from '../helpers/simplified-element-observer';
+
+export default function onPrMerge(callback: VoidFunction): Deinit {
+ return observeElement('.discussion-timeline-actions', (_, observer) => {
+ if (select.exists('.TimelineItem-badge .octicon-git-merge')) {
+ observer.disconnect();
+ callback();
+ }
+ }, {childList: true});
+}
diff --git a/source/github-helpers/timeline-item.tsx b/source/github-helpers/timeline-item.tsx
new file mode 100644
index 00000000..f1b2212d
--- /dev/null
+++ b/source/github-helpers/timeline-item.tsx
@@ -0,0 +1,6 @@
+import React from 'dom-chef';
+
+export default function TimelineItem(): JSX.Element {
+ // Classes copied from #issuecomment-new + mt-3 added
+ return <div className="ml-0 pl-0 ml-md-6 pl-md-3 mt-3"/>;
+}