Skip to content

Commit 0632faa

Browse files
committed
fix(tabs): clarify custom PR state filters
1 parent d68d8f4 commit 0632faa

7 files changed

Lines changed: 192 additions & 17 deletions

File tree

app/components/dashboard/tabs-settings/TabsEditorPanel.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ const {
6464
useAutoSubtitle,
6565
setActiveSource,
6666
setNewTabGroup,
67+
setSearchType,
68+
setQueryState,
6769
toggleScope,
6870
addLabel,
6971
handleLabelEnter,
@@ -206,7 +208,7 @@ const {
206208
: {}
207209
"
208210
type="button"
209-
@click="newTab.query.type = option.value"
211+
@click="setSearchType(option.value)"
210212
>
211213
<component
212214
:is="filterIconMap[option.value]?.icon"
@@ -234,7 +236,7 @@ const {
234236
: {}
235237
"
236238
type="button"
237-
@click="newTab.query.state = option.value"
239+
@click="setQueryState(option.value)"
238240
>
239241
<component
240242
:is="filterIconMap[option.value]?.icon"

app/composables/useCustomTabSettingsOptions.ts

Lines changed: 70 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
import type {
88
CustomTabArchived,
99
CustomTabDraft,
10+
CustomTabMerged,
1011
CustomTabOrder,
1112
CustomTabQuery,
1213
CustomTabReview,
@@ -32,6 +33,8 @@ export interface CustomTabToggleOption<T extends string> {
3233
value: T;
3334
}
3435

36+
export type CustomTabEditorState = CustomTabState | 'merged';
37+
3538
export const customTabSourceOptions: CustomTabSourceOption[] = [
3639
{
3740
id: 'github-search',
@@ -57,11 +60,17 @@ export const customTabTypeOptions: Array<CustomTabToggleOption<CustomTabSearchTy
5760
{ labelKey: 'dashboard.tabsSettings.options.pullRequests', value: 'pulls' },
5861
];
5962

60-
export const customTabStateOptions: Array<CustomTabToggleOption<CustomTabState | 'any'>> = [
61-
{ labelKey: 'dashboard.tabsSettings.options.any', value: 'any' },
63+
export const customTabIssueStateOptions: Array<CustomTabToggleOption<CustomTabState>> = [
6264
{ labelKey: 'dashboard.tabsSettings.options.open', value: 'open' },
6365
{ labelKey: 'dashboard.tabsSettings.options.closed', value: 'closed' },
64-
{ labelKey: 'dashboard.tabsSettings.options.all', value: 'all' },
66+
{ labelKey: 'dashboard.tabsSettings.options.allStates', value: 'all' },
67+
];
68+
69+
export const customTabPullStateOptions: Array<CustomTabToggleOption<CustomTabEditorState>> = [
70+
{ labelKey: 'dashboard.tabsSettings.options.open', value: 'open' },
71+
{ labelKey: 'dashboard.tabsSettings.options.closed', value: 'closed' },
72+
{ labelKey: 'dashboard.tabsSettings.options.merged', value: 'merged' },
73+
{ labelKey: 'dashboard.tabsSettings.options.allStates', value: 'all' },
6574
];
6675

6776
export const customTabScopeOptions: Array<CustomTabToggleOption<CustomTabSearchScope>> = [
@@ -140,6 +149,59 @@ export function createGitHubCustomTabPreviewUrl(query: CustomTabQuery) {
140149
return createGitHubIssueSearchUrl(query, buildCustomTabSearchQuery(query));
141150
}
142151

152+
export function getCustomTabEditorState(query: CustomTabQuery): CustomTabEditorState {
153+
if (query.type === 'pulls' && query.merged === 'merged') {
154+
return 'merged';
155+
}
156+
157+
if (query.state === 'open' || query.state === 'closed' || query.state === 'all') {
158+
return query.state;
159+
}
160+
161+
return 'all';
162+
}
163+
164+
export function applyCustomTabEditorState(
165+
query: CustomTabQuery,
166+
editorState: CustomTabEditorState
167+
): CustomTabQuery {
168+
const nextQuery: CustomTabQuery = { ...query };
169+
const isPullRequest = nextQuery.type === 'pulls';
170+
const state: CustomTabState = editorState === 'merged' ? 'closed' : editorState;
171+
let merged: CustomTabMerged | undefined;
172+
173+
nextQuery.state = state;
174+
175+
if (isPullRequest && editorState === 'merged') {
176+
merged = 'merged';
177+
} else if (isPullRequest && editorState === 'closed') {
178+
merged = 'unmerged';
179+
}
180+
181+
if (merged) {
182+
nextQuery.merged = merged;
183+
} else {
184+
delete nextQuery.merged;
185+
}
186+
187+
return nextQuery;
188+
}
189+
190+
function getCustomTabStateSummary(query: CustomTabQuery, t: Translate) {
191+
const editorState = getCustomTabEditorState(query);
192+
193+
if (editorState === 'all') {
194+
return '';
195+
}
196+
197+
const labelKey =
198+
editorState === 'merged'
199+
? 'dashboard.tabsSettings.options.merged'
200+
: `dashboard.tabsSettings.options.${editorState}`;
201+
202+
return t(labelKey);
203+
}
204+
143205
export function buildCustomTabHumanPreview(query: CustomTabQuery, t: Translate) {
144206
const chunks = [];
145207
chunks.push(getCustomTabTypeSummary(query.type ?? 'issues', t));
@@ -154,8 +216,9 @@ export function buildCustomTabHumanPreview(query: CustomTabQuery, t: Translate)
154216
chunks.push(t('dashboard.tabsSettings.summary.involving', { value: query.involves.trim() }));
155217
if (query.labels && query.labels.length > 0)
156218
chunks.push(t('dashboard.tabsSettings.summary.labeled', { value: query.labels.join(', ') }));
157-
if (query.state && query.state !== 'any')
158-
chunks.push(t('dashboard.tabsSettings.summary.state', { value: query.state }));
219+
220+
const stateSummary = getCustomTabStateSummary(query, t);
221+
if (stateSummary) chunks.push(t('dashboard.tabsSettings.summary.state', { value: stateSummary }));
159222

160223
return t('dashboard.tabsSettings.summary.showing', { value: chunks.join(', ') });
161224
}
@@ -165,9 +228,8 @@ export function buildCustomTabSummary(query: CustomTabQuery, t: Translate) {
165228
const type = query.type ?? 'issues';
166229
chunks.push(getCustomTabTypeSummary(type, t));
167230

168-
if (query.state && query.state !== 'all') {
169-
chunks.push(t('dashboard.tabsSettings.summary.state', { value: query.state }));
170-
}
231+
const stateSummary = getCustomTabStateSummary(query, t);
232+
if (stateSummary) chunks.push(t('dashboard.tabsSettings.summary.state', { value: stateSummary }));
171233
if (query.repo) chunks.push(t('dashboard.tabsSettings.summary.inRepo', { value: query.repo }));
172234
if (query.author)
173235
chunks.push(t('dashboard.tabsSettings.summary.authoredBy', { value: query.author }));

app/composables/useCustomTabs.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type {
22
CustomTab,
33
CustomTabArchived,
44
CustomTabDraft,
5+
CustomTabMerged,
56
CustomTabOrder,
67
CustomTabQuery,
78
CustomTabReview,
@@ -18,6 +19,7 @@ export type {
1819
CustomTab,
1920
CustomTabArchived,
2021
CustomTabDraft,
22+
CustomTabMerged,
2123
CustomTabOrder,
2224
CustomTabQuery,
2325
CustomTabReview,

app/composables/useTabsSettingsPage.ts

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
CircleDotIcon,
66
CircleMinusIcon,
77
FilePenLineIcon,
8+
GitMergeIcon,
89
GitPullRequestIcon,
910
ShieldAlertIcon,
1011
XCircleIcon,
@@ -27,6 +28,7 @@ import {
2728
useCustomTabs,
2829
} from '~/composables/useCustomTabs';
2930
import {
31+
applyCustomTabEditorState,
3032
buildCustomTabHumanPreview,
3133
buildCustomTabSearchParts,
3234
buildCustomTabSearchQuery,
@@ -35,13 +37,16 @@ import {
3537
createGitHubCustomTabPreviewUrl,
3638
customTabArchivedOptions,
3739
customTabDraftOptions,
40+
type CustomTabEditorState,
41+
getCustomTabEditorState,
42+
customTabIssueStateOptions,
3843
customTabOrderOptions,
44+
customTabPullStateOptions,
3945
customTabReviewOptions,
4046
customTabScopeOptions,
4147
customTabSortOptions,
4248
customTabSourceOptions,
4349
type CustomTabSourceOption,
44-
customTabStateOptions,
4550
customTabTypeOptions,
4651
customTabVisibilityOptions,
4752
} from '~/composables/useCustomTabSettingsOptions';
@@ -103,7 +108,6 @@ export const useTabsSettingsPage = () => {
103108

104109
const sourceOptions = customTabSourceOptions;
105110
const typeOptions = customTabTypeOptions;
106-
const stateOptions = customTabStateOptions;
107111
const scopeOptions = customTabScopeOptions;
108112
const sortOptions = customTabSortOptions;
109113
const orderOptions = customTabOrderOptions;
@@ -120,6 +124,7 @@ export const useTabsSettingsPage = () => {
120124
pulls: { icon: GitPullRequestIcon, activeColor: 'var(--gitpulse-purple)' },
121125
open: { icon: CircleDotIcon, activeColor: 'var(--gitpulse-success-solid)' },
122126
closed: { icon: CircleMinusIcon, activeColor: 'var(--gitpulse-danger-solid)' },
127+
merged: { icon: GitMergeIcon, activeColor: 'var(--gitpulse-purple)' },
123128
draft: { icon: FilePenLineIcon, activeColor: 'var(--gitpulse-warning-solid)' },
124129
ready: { icon: CheckCircle2Icon, activeColor: 'var(--gitpulse-success-solid)' },
125130
approved: { icon: CheckCircle2Icon, activeColor: 'var(--gitpulse-success-solid)' },
@@ -159,7 +164,7 @@ export const useTabsSettingsPage = () => {
159164
commenter: '',
160165
involves: '',
161166
milestone: '',
162-
state: 'open' as CustomTabState | 'any',
167+
state: 'open' as CustomTabEditorState,
163168
scopes: ['title', 'body'] as CustomTabSearchScope[],
164169
labels: [] as string[],
165170
visibility: 'any' as CustomTabVisibility,
@@ -309,6 +314,10 @@ export const useTabsSettingsPage = () => {
309314
return newTab.query.type === 'pulls';
310315
});
311316

317+
const stateOptions = computed(() => {
318+
return isPullRequestSearch.value ? customTabPullStateOptions : customTabIssueStateOptions;
319+
});
320+
312321
const advancedFilterCount = computed(() => {
313322
let count = 0;
314323
if (newTab.query.repo.trim()) count++;
@@ -390,7 +399,7 @@ export const useTabsSettingsPage = () => {
390399
const buildCurrentQuery = (): CustomTabQuery => {
391400
const labels = cleanLabels();
392401

393-
return {
402+
const query: CustomTabQuery = {
394403
text: newTab.query.text.trim() || undefined,
395404
type: newTab.query.type,
396405
repo: newTab.query.repo.trim() || undefined,
@@ -402,7 +411,6 @@ export const useTabsSettingsPage = () => {
402411
commenter: newTab.query.commenter.trim() || undefined,
403412
involves: newTab.query.involves.trim() || undefined,
404413
milestone: newTab.query.milestone.trim() || undefined,
405-
state: newTab.query.state === 'any' ? undefined : newTab.query.state,
406414
scopes: newTab.query.scopes.length > 0 ? [...newTab.query.scopes] : undefined,
407415
labels: labels.length > 0 ? labels : undefined,
408416
visibility: newTab.query.visibility === 'any' ? undefined : newTab.query.visibility,
@@ -415,6 +423,8 @@ export const useTabsSettingsPage = () => {
415423
order: newTab.query.order,
416424
perPage: newTab.query.perPage,
417425
};
426+
427+
return applyCustomTabEditorState(query, newTab.query.state);
418428
};
419429

420430
const searchQueryParts = computed(() => {
@@ -559,6 +569,17 @@ export const useTabsSettingsPage = () => {
559569
newTab.query.scopes = [...newTab.query.scopes, scope];
560570
};
561571

572+
const setSearchType = (type: CustomTabSearchType) => {
573+
newTab.query.type = type;
574+
if (type !== 'pulls' && newTab.query.state === 'merged') {
575+
newTab.query.state = 'closed';
576+
}
577+
};
578+
579+
const setQueryState = (state: CustomTabEditorState) => {
580+
newTab.query.state = state;
581+
};
582+
562583
const addLabel = (label: string) => {
563584
const normalized = label.trim();
564585
if (!normalized || newTab.query.labels.includes(normalized)) {
@@ -755,7 +776,7 @@ export const useTabsSettingsPage = () => {
755776
newTab.groupId = tab.groupId;
756777
newTab.source = tab.source ?? 'github-search';
757778

758-
const q = tab.query ?? {};
779+
const q: CustomTabQuery = tab.query ?? {};
759780
newTab.query.text = q.text ?? '';
760781
newTab.query.type = q.type ?? 'issues';
761782
newTab.query.repo = q.repo ?? '';
@@ -767,7 +788,7 @@ export const useTabsSettingsPage = () => {
767788
newTab.query.commenter = q.commenter ?? '';
768789
newTab.query.involves = q.involves ?? '';
769790
newTab.query.milestone = q.milestone ?? '';
770-
newTab.query.state = q.state ?? 'open';
791+
newTab.query.state = getCustomTabEditorState(q);
771792
newTab.query.scopes = q.scopes ?? ['title', 'body'];
772793
newTab.query.labels = q.labels ?? [];
773794
newTab.query.visibility = q.visibility ?? 'any';
@@ -990,6 +1011,8 @@ export const useTabsSettingsPage = () => {
9901011
confirmDeleteGroup,
9911012
setActiveSource,
9921013
setNewTabGroup,
1014+
setSearchType,
1015+
setQueryState,
9931016
toggleScope,
9941017
addLabel,
9951018
handleLabelEnter,

i18n/locales/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,9 @@
448448
"any": "Any",
449449
"open": "Open",
450450
"closed": "Closed",
451+
"merged": "Merged",
451452
"all": "All",
453+
"allStates": "All states",
452454
"title": "Title",
453455
"body": "Body",
454456
"comments": "Comments",

i18n/locales/zh-cn.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,9 @@
448448
"any": "任意",
449449
"open": "开启",
450450
"closed": "关闭",
451+
"merged": "已合并",
451452
"all": "全部",
453+
"allStates": "全部状态",
452454
"title": "标题",
453455
"body": "正文",
454456
"comments": "评论",

0 commit comments

Comments
 (0)