Skip to content

Commit

Permalink
Improves draft PR handling and launchpad grouping
Browse files Browse the repository at this point in the history
Adds action to the launchpad status to open Launchpad to the item
  • Loading branch information
eamodio committed Dec 19, 2024
1 parent 509d8f2 commit 03229d2
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 44 deletions.
9 changes: 7 additions & 2 deletions src/plus/integrations/providers/github/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ import { PullRequestMergeMethod } from '../../../../git/models/pullRequest';
import type { Provider } from '../../../../git/models/remoteProvider';
import type { RepositoryMetadata } from '../../../../git/models/repositoryMetadata';
import type { GitRevisionRange } from '../../../../git/models/revision';
import { createRevisionRange , getRevisionRangeParts, isRevisionRange, isSha } from '../../../../git/models/revision.utils';
import {
createRevisionRange,
getRevisionRangeParts,
isRevisionRange,
isSha,
} from '../../../../git/models/revision.utils';
import type { GitUser } from '../../../../git/models/user';
import { getGitHubNoReplyAddressParts } from '../../../../git/remotes/github';
import {
Expand Down Expand Up @@ -98,6 +103,7 @@ headRepository {
url
}
isCrossRepository
isDraft
mergedAt
permalink
repository {
Expand All @@ -122,7 +128,6 @@ assignees(first: 10) {
}
checksUrl
deletions
isDraft
mergeable
mergedBy {
login
Expand Down
3 changes: 2 additions & 1 deletion src/plus/integrations/providers/github/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export interface GitHubPullRequestLite extends Omit<GitHubIssueOrPullRequest, '_
};

isCrossRepository: boolean;
isDraft: boolean;
mergedAt: string | null;
permalink: string;

Expand Down Expand Up @@ -152,7 +153,6 @@ export interface GitHubPullRequest extends GitHubPullRequestLite {
};
checksUrl: string;
deletions: number;
isDraft: boolean;
mergeable: GitHubPullRequestMergeableState;
reviewDecision: GitHubPullRequestReviewDecision;
latestReviews: {
Expand Down Expand Up @@ -218,6 +218,7 @@ export function fromGitHubPullRequestLite(pr: GitHubPullRequestLite, provider: P
},
isCrossRepository: pr.isCrossRepository,
},
pr.isDraft,
);
}

Expand Down
12 changes: 12 additions & 0 deletions src/plus/launchpad/launchpad.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ interface GroupedLaunchpadItem extends LaunchpadItem {
}

interface State {
id?: { uuid: string; group: LaunchpadGroup };
item?: GroupedLaunchpadItem;
action?: LaunchpadAction | LaunchpadTargetAction;
initialGroup?: LaunchpadGroup;
Expand Down Expand Up @@ -293,6 +294,17 @@ export class LaunchpadCommand extends QuickCommand<State> {
await updateContextItems(this.container, context, { force: newlyConnected });

if (state.counter < 1 || state.item == null) {
if (state.id != null) {
const item = context.result.items?.find(item => item.uuid === state.id?.uuid);
if (item != null) {
state.item = { ...item, group: state.id.group };
if (state.counter < 1) {
state.counter = 1;
}
continue;
}
}

if (this.container.telemetry.enabled) {
this.container.telemetry.sendEvent(
opened ? 'launchpad/steps/main' : 'launchpad/opened',
Expand Down
75 changes: 38 additions & 37 deletions src/webviews/apps/plus/home/components/branch-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { customElement, property, state } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { when } from 'lit/directives/when.js';
import type { Commands } from '../../../../../constants.commands';
import type { LaunchpadItem } from '../../../../../plus/launchpad/launchpadProvider';
import type { LaunchpadCommandArgs } from '../../../../../plus/launchpad/launchpad';
import {
actionGroupMap,
launchpadCategoryToGroupMap,
Expand Down Expand Up @@ -422,10 +422,7 @@ export abstract class GlBranchCardBase extends GlElement {
}

get cardIndicator() {
if (this.launchpadItem && this.pr?.state === 'opened') {
return getLaunchpadItemGrouping(this.launchpadItem.category) ?? 'base';
}
return 'base';
return getLaunchpadItemGrouping(getLaunchpadItemGroup(this.pr, this.launchpadItem)) ?? 'base';
}

get branchCardIndicator() {
Expand Down Expand Up @@ -715,22 +712,17 @@ export abstract class GlBranchCardBase extends GlElement {
return nothing;
}

let indicator: GlCard['indicator'];
if (this.branch.opened) {
if (this.launchpadItem && this.pr?.state === 'opened') {
indicator = getLaunchpadItemGrouping(this.launchpadItem.category) ?? 'base';
} else {
indicator = 'base';
}
}
const indicator: GlCard['indicator'] = this.branch.opened
? getLaunchpadItemGrouping(getLaunchpadItemGroup(this.pr, this.launchpadItem)) ?? 'base'
: undefined;

const actions = this.renderPrActions();
return html`
<gl-work-item ?expanded=${this.expanded} ?nested=${!this.branch.opened} .indicator=${indicator}>
<div class="branch-item__section">
<p class="branch-item__grouping">
<span class="branch-item__icon">
<pr-icon state=${this.pr.state} pr-id=${this.pr.id}></pr-icon>
<pr-icon ?draft=${this.pr.draft} state=${this.pr.state} pr-id=${this.pr.id}></pr-icon>
</span>
<a href=${this.pr.url} class="branch-item__name branch-item__name--secondary"
>${this.pr.title}</a
Expand All @@ -745,47 +737,43 @@ export abstract class GlBranchCardBase extends GlElement {
}

protected renderLaunchpadItem() {
if (this.launchpadItem == null || this.pr?.state !== 'opened') return nothing;
if (this.launchpadItem == null) return nothing;

const group = launchpadCategoryToGroupMap.get(this.launchpadItem.category);
if (group == null || group === 'other' || group === 'draft' || group === 'current-branch') {
return nothing;
}
const group = getLaunchpadItemGroup(this.pr, this.launchpadItem);
if (group == null) return nothing;

const groupLabel = launchpadGroupLabelMap.get(group);
const groupIcon = launchpadGroupIconMap.get(group);

if (groupLabel == null || groupIcon == null) return nothing;
const groupIconString = groupIcon.match(/\$\((.*?)\)/)![1].replace('gitlens', 'gl');

// <a
// href=${createCommandLink<Omit<LaunchpadCommandArgs, 'command'>>('gitlens.showLaunchpad', {
// source: 'home',
// state: {
// item: { ...this.launchpadItem.item, group: group },
// },
// } satisfies Omit<LaunchpadCommandArgs, 'command'>)}
// class="launchpad__grouping"
// >

const tooltip = interpolate(actionGroupMap.get(this.launchpadItem.category)![1], {
author: this.launchpadItem.author?.username ?? 'unknown',
createdDateRelative: fromNow(new Date(this.launchpadItem.createdDate)),
});

return html`<div class="branch-item__section branch-item__section--details" slot="context">
<p class="launchpad-grouping--${getLaunchpadItemGrouping(this.launchpadItem.category)}">
<p class="launchpad-grouping--${getLaunchpadItemGrouping(group)}">
<gl-tooltip content="${tooltip}">
<code-icon icon="${groupIconString}"></code-icon
><span class="branch-item__category">${groupLabel.toUpperCase()}</span>
<a
href=${createCommandLink<Omit<LaunchpadCommandArgs, 'command'>>('gitlens.showLaunchpad', {
source: 'home',
state: {
id: { uuid: this.launchpadItem.uuid, group: group },
},
} satisfies Omit<LaunchpadCommandArgs, 'command'>)}
class="launchpad__grouping"
>
<code-icon icon="${groupIconString}"></code-icon
><span class="branch-item__category">${groupLabel.toUpperCase()}</span></a
>
</gl-tooltip>
</p>
</div>
${groupIconString
? html`<span
class="branch-item__summary launchpad-grouping--${getLaunchpadItemGrouping(
this.launchpadItem.category,
)}"
class="branch-item__summary launchpad-grouping--${getLaunchpadItemGrouping(group)}"
slot="summary"
><gl-tooltip placement="bottom" content="${groupLabel}"
><code-icon icon="${groupIconString}"></code-icon></gl-tooltip
Expand Down Expand Up @@ -1031,9 +1019,22 @@ export class GlWorkUnit extends LitElement {
}
}

function getLaunchpadItemGrouping(category: LaunchpadItem['actionableCategory']) {
const group = launchpadCategoryToGroupMap.get(category);
function getLaunchpadItemGroup(
pr: Awaited<GetOverviewBranch['pr']>,
launchpadItem: Awaited<NonNullable<Awaited<GetOverviewBranch['pr']>>['launchpad']>,
) {
if (launchpadItem == null || pr?.state !== 'opened') return undefined;
if (pr.draft && launchpadItem.category === 'unassigned-reviewers') return undefined;

const group = launchpadCategoryToGroupMap.get(launchpadItem.category);
if (group == null || group === 'other' || group === 'draft' || group === 'current-branch') {
return undefined;
}

return group;
}

function getLaunchpadItemGrouping(group: ReturnType<typeof getLaunchpadItemGroup>) {
switch (group) {
case 'mergeable':
return 'mergeable';
Expand Down
14 changes: 10 additions & 4 deletions src/webviews/apps/shared/components/rich/pr-icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ export class PrIcon extends LitElement {
@property()
state?: 'merged' | 'opened' | 'closed' | string;

@property({ type: Boolean })
draft = false;

@property({ attribute: 'pr-id' })
prId?: string;

get icon() {
let prIcon = 'git-pull-request';
let prIcon = this.draft ? 'git-pull-request-draft' : 'git-pull-request';
if (this.state) {
switch (this.state) {
case 'merged':
Expand All @@ -31,15 +34,18 @@ export class PrIcon extends LitElement {
}

get classes() {
if (!this.state) return 'pr-icon';
if (!this.state || (this.draft && this.state === 'opened')) {
return 'pr-icon';
}

return `pr-icon pr-icon--${this.state}`;
}

get label() {
if (!this.state) return 'Pull request';
const type = this.draft ? 'Draft pull request' : 'Pull request';
if (!this.state) return type;

return `Pull request ${this.prId ? `#${this.prId}` : ''} is ${this.state}`;
return `${type} ${this.prId ? `#${this.prId}` : ''} is ${this.state}`;
}

override render() {
Expand Down
2 changes: 2 additions & 0 deletions src/webviews/home/homeWebview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1460,6 +1460,7 @@ async function getLaunchpadItemInfo(
if (lpi == null) return undefined;

return {
uuid: lpi.uuid,
category: lpi.actionableCategory,
groups: getLaunchpadItemGroups(lpi),
suggestedActions: lpi.suggestedActions,
Expand Down Expand Up @@ -1498,6 +1499,7 @@ async function getPullRequestInfo(
url: pr.url,
state: pr.state,
title: pr.title,
draft: pr.isDraft,
launchpad: getLaunchpadItemInfo(container, pr, launchpadPromise),
};
}
Expand Down
2 changes: 2 additions & 0 deletions src/webviews/home/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,11 @@ export interface GetOverviewBranch {
title: string;
state: string;
url: string;
draft?: boolean;

launchpad?: Promise<
| {
uuid: string;
category: LaunchpadItem['actionableCategory'];
groups: LaunchpadGroup[];
suggestedActions: LaunchpadItem['suggestedActions'];
Expand Down

0 comments on commit 03229d2

Please sign in to comment.