Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/frontend/packages/swarm-ui/src/pages/issue-report-repo.ts
iris f6acc1e976 swarm-ui: keep the issue report's table, errors and repo filter consistent
A failed report dropped its error under the previous repo's rows, the
repo list and the report shared one error slot, a remembered repo that
the list lacked left the select on all repos, and the report URL did not
encode the repo path. Each request now has its own error, a failed report
clears the rows, the remembered repo keeps an option, and the path parts
are encoded.
2026-10-21 22:58:51 +02:00

42 lines
1.5 KiB
TypeScript

// Pure helpers for the issue report's repo filter: the report URL and the
// select's options. Kept out of the page so the cases are unit tested.
/** Select value for "every repo". It cannot collide with a real
* `owner/name`, which always has a slash. */
export const ALL_REPOS = "";
export interface RepoOption {
value: string;
label: string;
}
/** The report URL for a repo filter. The path parts are encoded, so a name
* with `?`, `#` or `%` stays one path segment. A filter without a slash
* is not a repo, so it reads as all repos. */
export function reportUrl(repoFilter: string): string {
const i = repoFilter.indexOf("/");
if (i < 0) return "/api/issue-report";
const org = encodeURIComponent(repoFilter.slice(0, i));
const name = encodeURIComponent(repoFilter.slice(i + 1));
return `/api/repos/${org}/${name}/issue-report`;
}
/** The select's options. A remembered repo that the list lacks keeps its
* own option, so the select shows what the table is filtered to. Once the
* list has loaded, the label says why the repo is not in it. */
export function repoOptions(
repos: string[] | null,
selected: string,
): RepoOption[] {
const options: RepoOption[] = [
{ value: ALL_REPOS, label: "all repos" },
...(repos ?? []).map((r) => ({ value: r, label: r })),
];
if (selected !== ALL_REPOS && !(repos ?? []).includes(selected)) {
options.push({
value: selected,
label: repos === null ? selected : `${selected} (no open issues)`,
});
}
return options;
}