дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 19:25:54 +02:00
feat(github): show every open pull request by default (#506)
The list opened filtered to pull requests assigned to the user, which is empty on most repositories. A search already used in the project is still restored.
Цей коміт міститься в:
1 джерело
059fd8a69b
коміт
c0c9553550
5 files changed
+29
-24
No files matched your search
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* IntelliJ's pull request search history (`GHPRListPersistentSearchHistory`), per project:
|
||||
* the last 10 searches (newest first) and the last search used, which the list restores.
|
||||
* On first run the list shows the Quick Filter "Assigned to you" (`initialSearch`).
|
||||
* On first run the list shows the Quick Filter "Open" (`initialSearch`).
|
||||
*/
|
||||
import { useProject } from "@/platform/project";
|
||||
import { DEFAULT_SEARCH, filterCount, normalizeSearch, sameSearch, type PrSearchValue } from "./model";
|
||||
@@ -30,7 +30,7 @@ function save(key: string, value: unknown) {
|
||||
|
||||
/**
|
||||
* `history` with `v` first (moved up when already there). Searches without filters and
|
||||
* `defaultSearch` are not kept (the list passes its first-run filter, "Assigned to you").
|
||||
* `defaultSearch` are not kept (the list passes its first-run filter, "Open").
|
||||
*/
|
||||
export function withSearch(
|
||||
history: readonly PrSearchValue[],
|
||||
@@ -63,7 +63,7 @@ export function saveLastSearch(v: PrSearchValue, root = projectRoot()) {
|
||||
if (root) save(lastKey(root), v);
|
||||
}
|
||||
|
||||
/** The list's search when the tool window opens: the last one, else "Assigned to you". */
|
||||
export function initialSearch(currentUserLogin: string, root = projectRoot()): PrSearchValue {
|
||||
return loadLastSearch(root) ?? { state: "OPEN", assignee: currentUserLogin };
|
||||
/** The list's search when the tool window opens: the last one, else every open pull request. */
|
||||
export function initialSearch(root = projectRoot()): PrSearchValue {
|
||||
return loadLastSearch(root) ?? { state: "OPEN" };
|
||||
}
|
||||
@@ -45,15 +45,15 @@ function useApplySearch(login: string | undefined): (v: PrSearchValue) => void {
|
||||
const recorder = useRef<SearchHistoryRecorder | null>(null);
|
||||
useEffect(() => {
|
||||
if (!login) return;
|
||||
const defaultSearch = defaultFilter(login);
|
||||
const defaultSearch = defaultFilter();
|
||||
const r = createSearchHistoryRecorder({
|
||||
defaultSearch,
|
||||
saveLast: (v) => saveLastSearch(v),
|
||||
remember: (v) => rememberSearch(v, undefined, defaultSearch),
|
||||
});
|
||||
recorder.current = r;
|
||||
r.onChange(initialSearch(login));
|
||||
void setListSearch(initialSearch(login));
|
||||
r.onChange(initialSearch());
|
||||
void setListSearch(initialSearch());
|
||||
return () => {
|
||||
r.dispose();
|
||||
if (recorder.current === r) recorder.current = null;
|
||||
|
||||
@@ -224,7 +224,7 @@ describe("ListPanel", () => {
|
||||
});
|
||||
};
|
||||
|
||||
it("starts with Assigned to you and renders the rows", async () => {
|
||||
it("starts with every open pull request and renders the rows", async () => {
|
||||
pages = [
|
||||
[
|
||||
pr(7, {
|
||||
@@ -244,7 +244,7 @@ describe("ListPanel", () => {
|
||||
],
|
||||
];
|
||||
await mount();
|
||||
expect(queries[0]).toBe("type:pr repo:org/app is:open assignee:me");
|
||||
expect(queries[0]).toBe("type:pr repo:org/app is:open");
|
||||
const rows = screen.getAllByRole("option");
|
||||
expect(rows).toHaveLength(2);
|
||||
const first = within(rows[0]!);
|
||||
@@ -259,7 +259,7 @@ describe("ListPanel", () => {
|
||||
expect(within(rows[1]!).getByText("MERGED")).toBeTruthy();
|
||||
expect(within(rows[1]!).getByText(/^#8 · created /).textContent).not.toContain(", by");
|
||||
expect(rows[1]!.querySelector("[data-unread]")).toBeNull();
|
||||
expect(loadLastSearch()).toEqual({ state: "OPEN", assignee: "me" });
|
||||
expect(loadLastSearch()).toEqual({ state: "OPEN" });
|
||||
});
|
||||
|
||||
it("opens the context menu with IntelliJ's items on the clicked row", async () => {
|
||||
@@ -303,28 +303,33 @@ describe("ListPanel", () => {
|
||||
const field = screen.getByRole("textbox", { name: "Search pull requests" });
|
||||
fireEvent.change(field, { target: { value: "crash" } });
|
||||
await act(async () => fireEvent.keyDown(field, { key: "Enter" }));
|
||||
expect(queries[1]).toBe("type:pr repo:org/app (crash) is:open assignee:me");
|
||||
expect(loadSearchHistory()).toEqual([{ state: "OPEN", assignee: "me", searchQuery: "crash" }]);
|
||||
expect(queries[1]).toBe("type:pr repo:org/app (crash) is:open");
|
||||
expect(loadSearchHistory()).toEqual([{ state: "OPEN", searchQuery: "crash" }]);
|
||||
});
|
||||
|
||||
it("resets a chip with its ✕ and with Delete, and shows the quick filter badge", async () => {
|
||||
pages = [[], [], []];
|
||||
it("resets a chip with its ✕ and shows the quick filter badge", async () => {
|
||||
pages = [[], []];
|
||||
await mount();
|
||||
expect(document.querySelector("[data-badge]")).toBeTruthy();
|
||||
const assignee = screen.getByText("me").closest("button")!;
|
||||
await act(async () => fireEvent.keyDown(assignee, { key: "Delete" }));
|
||||
expect(queries[1]).toBe("type:pr repo:org/app is:open");
|
||||
await act(async () => fireEvent.click(screen.getByRole("button", { name: "Reset State" })));
|
||||
expect(queries[2]).toBe("type:pr repo:org/app");
|
||||
expect(queries[1]).toBe("type:pr repo:org/app");
|
||||
expect(document.querySelector("[data-badge]")).toBeNull();
|
||||
expect(screen.getByText("State")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("resets a chip with Delete", async () => {
|
||||
pages = [[], []];
|
||||
await mount();
|
||||
const state = screen.getByText("Open").closest("button")!;
|
||||
await act(async () => fireEvent.keyDown(state, { key: "Delete" }));
|
||||
expect(queries[1]).toBe("type:pr repo:org/app");
|
||||
});
|
||||
|
||||
it("chooses a chip value from its popup", async () => {
|
||||
pages = [[], []];
|
||||
await mount();
|
||||
await act(async () => fireEvent.click(screen.getByText("Sort")));
|
||||
await act(async () => fireEvent.click(screen.getByText("Least recently updated")));
|
||||
expect(queries[1]).toBe("type:pr repo:org/app is:open assignee:me sort:updated-asc");
|
||||
expect(queries[1]).toBe("type:pr repo:org/app is:open sort:updated-asc");
|
||||
});
|
||||
});
|
||||
@@ -39,8 +39,8 @@ export function quickFilters(login: string): QuickFilter[] {
|
||||
];
|
||||
}
|
||||
|
||||
/** The list's first-run filter and the one the history never keeps: "Assigned to you". */
|
||||
export const defaultFilter = (login: string): PrSearchValue => ({ state: "OPEN", assignee: login });
|
||||
/** The list's first-run filter and the one the history never keeps: every open pull request. */
|
||||
export const defaultFilter = (): PrSearchValue => ({ state: "OPEN" });
|
||||
|
||||
/** A quick filter is checked only when the search is exactly it. */
|
||||
export const isQuickFilterSelected = (search: PrSearchValue, q: QuickFilter) => sameSearch(search, q.filter);
|
||||
|
||||
@@ -162,8 +162,8 @@ describe("tool window", () => {
|
||||
expect(screen.getByRole("tab", { name: /app/ })).toBeTruthy();
|
||||
expect(screen.getByRole("textbox", { name: "Search pull requests" })).toBeTruthy();
|
||||
const body = JSON.parse(ghApi.mock.calls[0]![0].body!) as { variables: { query: string; pageSize: number } };
|
||||
// First run: "Assigned to you".
|
||||
expect(body.variables).toMatchObject({ query: "type:pr repo:org/app is:open assignee:me", pageSize: 50 });
|
||||
// First run: every open pull request.
|
||||
expect(body.variables).toMatchObject({ query: "type:pr repo:org/app is:open", pageSize: 50 });
|
||||
await act(async () => openPullRequestTab(4));
|
||||
expect(screen.getByRole("tab", { name: /#4/ })).toBeTruthy();
|
||||
});
|
||||
|
||||
Reference in new issue
Заблокувати користувача