Skip to content

Commit

Permalink
Add repo issues and patches routes
Browse files Browse the repository at this point in the history
  • Loading branch information
rudolfs committed Sep 10, 2024
1 parent cb82dae commit f09253f
Show file tree
Hide file tree
Showing 9 changed files with 243 additions and 25 deletions.
6 changes: 6 additions & 0 deletions src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import AuthenticationError from "@app/views/AuthenticationError.svelte";
import Home from "@app/views/Home.svelte";
import Issues from "@app/views/repo/Issues.svelte";
import Patches from "@app/views/repo/Patches.svelte";
const activeRouteStore = router.activeRouteStore;
Expand Down Expand Up @@ -40,6 +42,10 @@
<!-- Don't show anything -->
{:else if $activeRouteStore.resource === "home"}
<Home {...$activeRouteStore.params} />
{:else if $activeRouteStore.resource === "repo.issues"}
<Issues {...$activeRouteStore.params} />
{:else if $activeRouteStore.resource === "repo.patches"}
<Patches {...$activeRouteStore.params} />
{:else if $activeRouteStore.resource === "authenticationError"}
<AuthenticationError {...$activeRouteStore.params} />
{:else}
Expand Down
7 changes: 6 additions & 1 deletion src/components/RepoCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@
}
</style>

<Border variant="ghost" styleWidth="100%" stylePadding="8px 12px" hoverable>
<Border
variant="ghost"
styleWidth="100%"
stylePadding="8px 12px"
hoverable
on:click>
<div class="container txt-small">
<div class="global-flex header">
<div class="global-flex">
Expand Down
17 changes: 12 additions & 5 deletions src/lib/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { get, writable } from "svelte/store";
import * as mutexExecutor from "@app/lib/mutexExecutor";
import * as utils from "@app/lib/utils";
import { loadRoute } from "@app/lib/router/definitions";
import { repoRouteToPath, repoUrlToRoute } from "@app/views/repo/router";

export { type Route };

Expand Down Expand Up @@ -45,10 +46,8 @@ async function navigateToUrl(
if (route) {
await navigate(action, route);
} else {
await navigate(action, {
// On 404 we redirect to the Home page, shouldn't happen.
resource: "home",
});
console.error("Could not resolve route for URL: ", url);
await navigate(action, { resource: "home" });
}
}

Expand Down Expand Up @@ -95,12 +94,15 @@ export async function replace(newRoute: Route): Promise<void> {

function urlToRoute(url: URL): Route | null {
const segments = url.pathname.substring(1).split("/");

const resource = segments.shift();

switch (resource) {
case "": {
return { resource: "home" };
}
case "repos": {
return repoUrlToRoute(segments, url.searchParams);
}
case "authenticationError": {
return { resource: "authenticationError", params: { error: "" } };
}
Expand All @@ -115,6 +117,11 @@ export function routeToPath(route: Route): string {
return "/";
} else if (route.resource === "authenticationError") {
return "/authenticationError";
} else if (
route.resource === "repo.issues" ||
route.resource === "repo.patches"
) {
return repoRouteToPath(route);
} else if (route.resource === "booting") {
return "";
} else {
Expand Down
18 changes: 15 additions & 3 deletions src/lib/router/definitions.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import type { RepoInfo } from "@bindings/RepoInfo";
import type { Config } from "@bindings/Config";
import type { RepoInfo } from "@bindings/RepoInfo";
import type { LoadedRepoRoute, RepoRoute } from "@app/views/repo/router";

import { invoke } from "@tauri-apps/api/core";

import { loadIssues, loadPatches } from "@app/views/repo/router";

interface BootingRoute {
resource: "booting";
}
Expand All @@ -24,12 +27,17 @@ interface LoadedHomeRoute {
params: { repos: RepoInfo[]; config: Config };
}

export type Route = BootingRoute | HomeRoute | AuthenticationErrorRoute;
export type Route =
| AuthenticationErrorRoute
| BootingRoute
| HomeRoute
| RepoRoute;

export type LoadedRoute =
| AuthenticationErrorRoute
| BootingRoute
| LoadedHomeRoute
| AuthenticationErrorRoute;
| LoadedRepoRoute;

export async function loadRoute(
route: Route,
Expand All @@ -39,6 +47,10 @@ export async function loadRoute(
const repos: RepoInfo[] = await invoke("list_repos");
const config: Config = await invoke("config");
return { resource: "home", params: { repos, config } };
} else if (route.resource === "repo.issues") {
return loadIssues(route);
} else if (route.resource === "repo.patches") {
return loadPatches(route);
}
return route;
}
28 changes: 12 additions & 16 deletions src/views/Home.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,13 @@
import type { Config } from "@bindings/Config";
import type { RepoInfo } from "@bindings/RepoInfo";
import * as router from "@app/lib/router";
import Header from "@app/components/Header.svelte";
import RepoCard from "@app/components/RepoCard.svelte";
import { onMount } from "svelte";
import { invoke } from "@tauri-apps/api/core";
export let repos: RepoInfo[];
export let config: Config;
onMount(async () => {
const patches = await invoke("list_patches", {
rid: "rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5",
status: "open",
});
const issues = await invoke("list_issues", {
rid: "rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5",
status: "open",
});
console.log(patches, issues);
});
</script>

<style>
Expand All @@ -40,7 +27,16 @@
<div class="repo-grid">
{#each repos as repo}
{#if repo.payloads["xyz.radicle.project"]}
<RepoCard {repo} selfDid={`did:key:${config.publicKey}`} />
<RepoCard
{repo}
selfDid={`did:key:${config.publicKey}`}
on:click={() => {
void router.push({
resource: "repo.issues",
rid: repo.rid,
status: "open",
});
}} />
{/if}
{/each}
</div>
Expand Down
20 changes: 20 additions & 0 deletions src/views/repo/Issues.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script lang="ts">
import type { Issue } from "@bindings/Issue";
import type { RepoInfo } from "@bindings/RepoInfo";
import Layout from "./Layout.svelte";
export let repo: RepoInfo;
export let issues: Issue[];
</script>

<Layout {repo}>
<pre>
<!-- prettier-ignore -->
{#each issues as issue}
- {issue.title}
{:else}
No issues.
{/each}
</pre>
</Layout>
38 changes: 38 additions & 0 deletions src/views/repo/Layout.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<script lang="ts">
import type { RepoInfo } from "@bindings/RepoInfo";
import Header from "@app/components/Header.svelte";
import Link from "@app/components/Link.svelte";
export let repo: RepoInfo;
$: project = repo.payloads["xyz.radicle.project"]!;
</script>

<Header currentPage="Repositories" />
<div>{project.data.name}</div>
<div>{repo.rid}</div>

Issues
<Link route={{ resource: "repo.issues", rid: repo.rid, status: "open" }}>
Open
</Link>
<Link route={{ resource: "repo.issues", rid: repo.rid, status: "closed" }}>
Closed
</Link>

<br />
Patches
<Link route={{ resource: "repo.patches", rid: repo.rid, status: "draft" }}>
Draft
</Link>
<Link route={{ resource: "repo.patches", rid: repo.rid, status: "open" }}>
Open
</Link>
<Link route={{ resource: "repo.patches", rid: repo.rid, status: "archived" }}>
Archived
</Link>
<Link route={{ resource: "repo.patches", rid: repo.rid, status: "merged" }}>
Merged
</Link>
<slot />
20 changes: 20 additions & 0 deletions src/views/repo/Patches.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script lang="ts">
import type { Patch } from "@bindings/Patch";
import type { RepoInfo } from "@bindings/RepoInfo";
import Layout from "./Layout.svelte";
export let repo: RepoInfo;
export let patches: Patch[];
</script>

<Layout {repo}>
<pre>
<!-- prettier-ignore -->
{#each patches as patch}
- {patch.title}
{:else}
No patches.
{/each}
</pre>
</Layout>
114 changes: 114 additions & 0 deletions src/views/repo/router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import type { RepoInfo } from "@bindings/RepoInfo";
import type { Patch } from "@bindings/Patch";
import type { Issue } from "@bindings/Issue";

import { invoke } from "@tauri-apps/api/core";
import { unreachable } from "@app/lib/utils";

export interface RepoIssuesRoute {
resource: "repo.issues";
rid: string;
status?: "open" | "closed";
}

export interface LoadedRepoIssuesRoute {
resource: "repo.issues";
params: { repo: RepoInfo; issues: Issue[] };
}

export interface RepoPatchesRoute {
resource: "repo.patches";
rid: string;
status?: "draft" | "open" | "archived" | "merged";
}

export interface LoadedRepoPatchesRoute {
resource: "repo.patches";
params: { repo: RepoInfo; patches: Patch[] };
}

export type RepoRoute = RepoIssuesRoute | RepoPatchesRoute;
export type LoadedRepoRoute = LoadedRepoIssuesRoute | LoadedRepoPatchesRoute;

export async function loadPatches(route: RepoRoute): Promise<LoadedRepoRoute> {
const repo: RepoInfo = await invoke("repo_by_id", {
rid: route.rid,
});
const patches: Patch[] = await invoke("list_patches", {
rid: route.rid,
status: route.status,
});

return { resource: "repo.patches", params: { repo, patches } };
}

export async function loadIssues(route: RepoRoute): Promise<LoadedRepoRoute> {
const repo: RepoInfo = await invoke("repo_by_id", {
rid: route.rid,
});
const issues: Issue[] = await invoke("list_issues", {
rid: route.rid,
status: route.status,
});

return { resource: "repo.issues", params: { repo, issues } };
}

export function repoRouteToPath(route: RepoRoute): string {
const pathSegments = ["/repos", route.rid];

if (route.resource === "repo.issues") {
let url = [...pathSegments, "issues"].join("/");
const searchParams = new URLSearchParams();
if (route.status) {
searchParams.set("status", route.status);
url += `?${searchParams}`;
}
return url;
} else if (route.resource === "repo.patches") {
let url = [...pathSegments, "patches"].join("/");
const searchParams = new URLSearchParams();
if (route.status) {
searchParams.set("status", route.status);
url += `?${searchParams}`;
}
return url;
} else {
return unreachable(route);
}
}

export function repoUrlToRoute(
segments: string[],
searchParams: URLSearchParams,
): RepoRoute | null {
const rid = segments.shift();
const resource = segments.shift();

if (rid) {
if (resource === "issues") {
const status = searchParams.get("status");
if (status === "open" || status === "closed") {
return { resource: "repo.issues", rid, status };
} else {
return { resource: "repo.issues", rid };
}
} else if (resource === "patches") {
const status = searchParams.get("status");
if (
status === "draft" ||
status === "open" ||
status === "archived" ||
status === "merged"
) {
return { resource: "repo.patches", rid, status };
} else {
return { resource: "repo.patches", rid };
}
} else {
return null;
}
} else {
return null;
}
}

0 comments on commit f09253f

Please sign in to comment.