From 72e1b992642934b369a98355b77734bce816c0fb Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Mon, 24 Jun 2024 15:05:21 +0200 Subject: [PATCH] Simplify sidebar context boxes Also starts removing features that relied on the web client handling local httpd instances --- http-client/index.ts | 7 +- http-client/lib/shared.ts | 12 + src/lib/utils.ts | 10 +- src/views/nodes/View.svelte | 6 +- src/views/projects/Sidebar.svelte | 228 ++++++------------ src/views/projects/Sidebar/ContextHelp.svelte | 91 ------- src/views/projects/Sidebar/ContextRepo.svelte | 153 +++++------- tests/unit/utils.test.ts | 14 -- 8 files changed, 157 insertions(+), 364 deletions(-) delete mode 100644 src/views/projects/Sidebar/ContextHelp.svelte diff --git a/http-client/index.ts b/http-client/index.ts index 23d8b5da06..87b33c240e 100644 --- a/http-client/index.ts +++ b/http-client/index.ts @@ -12,6 +12,7 @@ import type { SuccessResponse, CodeLocation, Range, + SeedingPolicy, DefaultSeedingPolicy, } from "./lib/shared.js"; import type { Comment, Embed, Reaction } from "./lib/project/comment.js"; @@ -50,6 +51,7 @@ import { Fetcher } from "./lib/fetcher.js"; import { nodeConfigSchema, scopeSchema, + seedingPolicySchema, successResponseSchema, } from "./lib/shared.js"; @@ -85,6 +87,7 @@ export type { Remote, Review, Revision, + SeedingPolicy, TreeStats, Tree, Verdict, @@ -211,14 +214,14 @@ export class HttpdClient { public async getPoliciesById( id: string, options?: RequestOptions, - ): Promise { + ): Promise { return this.#fetcher.fetchOk( { method: "GET", path: `node/policies/repos/${id}`, options, }, - array(nodePoliciesSchema.shape.policy), + seedingPolicySchema, ); } diff --git a/http-client/lib/shared.ts b/http-client/lib/shared.ts index b0425a2119..3ecd701e9a 100644 --- a/http-client/lib/shared.ts +++ b/http-client/lib/shared.ts @@ -12,6 +12,18 @@ export const successResponseSchema = object({ export const scopeSchema = union([literal("followed"), literal("all")]); +export const seedingPolicySchema = union([ + object({ + policy: literal("block"), + }), + object({ + policy: literal("allow"), + scope: scopeSchema, + }), +]); + +export type SeedingPolicy = z.infer; + const defaultSeedingPolicySchema = union([ object({ default: literal("block"), diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 76a0d04b69..5b6fdd25fc 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,4 +1,4 @@ -import type { BaseUrl, DefaultSeedingPolicy } from "@http-client"; +import type { BaseUrl } from "@http-client"; import md5 from "md5"; import bs58 from "bs58"; @@ -13,14 +13,6 @@ export function formatLocationHash(hash: string | null): number | null { return null; } -export function formatShortSeedingPolicy( - policy: DefaultSeedingPolicy | undefined, -) { - return policy?.default === "allow" && policy?.scope === "all" - ? "permissive" - : "restrictive"; -} - // Removes the first and last character which are always `/`. export function formatUserAgent(agent: string): string { return agent.slice(1, -1); diff --git a/src/views/nodes/View.svelte b/src/views/nodes/View.svelte index 97e34ef092..38b5438e92 100644 --- a/src/views/nodes/View.svelte +++ b/src/views/nodes/View.svelte @@ -7,7 +7,6 @@ import { api, httpdStore } from "@app/lib/httpd"; import { baseUrlToString, - formatShortSeedingPolicy, formatUserAgent, isLocal, truncateId, @@ -32,7 +31,10 @@ export let seedingPolicy: DefaultSeedingPolicy | undefined = undefined; export let agent: string; - $: shortScope = formatShortSeedingPolicy(seedingPolicy); + $: shortScope = + seedingPolicy?.default === "allow" && seedingPolicy?.scope === "all" + ? "permissive" + : "restrictive"; $: hostname = isLocal(baseUrl.hostname) ? "Local Node" : baseUrl.hostname; $: session = $httpdStore.state === "authenticated" && isLocal(api.baseUrl.hostname) diff --git a/src/views/projects/Sidebar.svelte b/src/views/projects/Sidebar.svelte index 8e56291ccf..55f8e710c7 100644 --- a/src/views/projects/Sidebar.svelte +++ b/src/views/projects/Sidebar.svelte @@ -2,22 +2,12 @@ import type { ActiveTab } from "./Header.svelte"; import type { BaseUrl, Node, Project } from "@http-client"; - import { onMount } from "svelte"; - - import { experimental } from "@app/lib/appearance"; - import { httpdStore, api } from "@app/lib/httpd"; - import { isLocal } from "@app/lib/utils"; - import { queryProject } from "@app/lib/projects"; - import Button from "@app/components/Button.svelte"; - import ContextHelp from "@app/views/projects/Sidebar/ContextHelp.svelte"; import ContextRepo from "@app/views/projects/Sidebar/ContextRepo.svelte"; + import Help from "@app/App/Help.svelte"; import IconSmall from "@app/components/IconSmall.svelte"; import Link from "@app/components/Link.svelte"; - import Loading from "@app/components/Loading.svelte"; import Popover from "@app/components/Popover.svelte"; - - import Help from "@app/App/Help.svelte"; import Settings from "@app/App/Settings.svelte"; const SIDEBAR_STATE_KEY = "sidebarState"; @@ -37,20 +27,6 @@ ); } - // To avoid concurrent request. - let queryingLocalProject: boolean = true; - let localProject: "notFound" | "found" | undefined = undefined; - $: hideContextHelp = - $experimental && - isLocal(baseUrl.hostname) && - $httpdStore.state === "authenticated"; - - httpdStore.subscribe(async () => { - if ($httpdStore.state !== "stopped" && !queryingLocalProject) { - await detectLocalProject(); - } - }); - function loadSidebarState(): boolean { const storedSidebarState = window.localStorage.getItem(SIDEBAR_STATE_KEY); @@ -66,19 +42,7 @@ storeSidebarState(expanded); } - async function detectLocalProject(): Promise { - queryingLocalProject = true; - localProject = await queryProject(api.baseUrl, project.id); - queryingLocalProject = false; - } - - onMount(async () => { - if ($httpdStore.state !== "stopped") { - await detectLocalProject(); - } else { - localProject = "notFound"; - } - }); + $: seedingPolicy = formatShortSeedingPolicy(node.config?.seedingPolicy); - -
- {#if $httpdStore.state === "stopped"} -
Local node not connected
-
- Click the Connect button in the top right -
- corner to get started. -
- {:else if localProject === "notFound"} -
Repository not available locally
-
- This repository hasn't been found on your local -
- node. To get a local copy start seeding it -
- using the following command. -
- - {:else if $httpdStore.state === "running" && localProject === "found"} -
Not authenticated
-
To make changes you need to authenticate.
-
- Click the Authenticate button in the top -
- right corner to get authenticated. -
- {:else if !isLocal(baseUrl.hostname) && localProject === "found"} -
Read Only
-
This is a read only preview hosted on
- - {/if} - - {#if !hideLocalButton} -
- - - -
- {/if} -
diff --git a/src/views/projects/Sidebar/ContextRepo.svelte b/src/views/projects/Sidebar/ContextRepo.svelte index b5630beb9f..3c3af883e2 100644 --- a/src/views/projects/Sidebar/ContextRepo.svelte +++ b/src/views/projects/Sidebar/ContextRepo.svelte @@ -1,119 +1,88 @@ -
-
-
- - Delegates - {project.delegates.length} -
-
- - - {project.threshold}/{project.delegates.length} - - {#if !disablePopovers} - - - - - -
- {project.threshold} out of {project.delegates.length} delegates have - to accept changes to be included in the canonical branch. -
-
- {/if} -
-
-
- {#each project.delegates as { id: nodeId, alias }} -
- -
- {/each} +
+ Delegates +
+ + {projectThreshold}/{projectDelegates.length} + + (delegateExpanded = !delegateExpanded)}> + +
-
-
- {#if isLocal(baseUrl.hostname)} - Local Node +{#if delegateExpanded} +
+ {#if projectDelegates.length === 1} + Any changes accepted by the sole delegate will be included in the + canonical branch. {:else} - {baseUrl.hostname} + {projectThreshold} out of {projectDelegates.length} delegates have to accept + changes to be included in the canonical branch. {/if}
- -
-
-
- (expandedNode = !expandedNode)}> - - - Seeding Policy -
-
- {capitalize(shortSeedingPolicy)} -
+ {#each projectDelegates as delegate} +
+
- {#if expandedNode && node.config?.seedingPolicy} -
- -
- {/if} + {/each} +{/if} +
+ Seeding Scope +
+ + {capitalize( + "scope" in seedingPolicy ? seedingPolicy.scope : "not defined", + )} + + (policyExpanded = !policyExpanded)}> + +
+{#if policyExpanded} +
+ {#if seedingPolicy.policy === "block"} + Seeding scope only has an effect when a repository is seeded. This repo + isn't seeded by the seed node. + {:else if seedingPolicy.scope === "all"} + This repository tracks changes by any peer. + {:else} + This repository tracks only peers followed by the seed node. + {/if} +
+{/if} diff --git a/tests/unit/utils.test.ts b/tests/unit/utils.test.ts index 23d4eb392b..5365c7aaf0 100644 --- a/tests/unit/utils.test.ts +++ b/tests/unit/utils.test.ts @@ -9,20 +9,6 @@ describe("Format functions", () => { expect(utils.formatLocationHash(hash)).toEqual(expected); }); - test.each([ - { - input: { default: "allow", scope: "all" }, - expected: "permissive", - } as const, - { - input: { default: "allow", scope: "followed" }, - expected: "restrictive", - } as const, - { input: { default: "block" }, expected: "restrictive" } as const, - ])("formatShortSeedingPolicy $input => $expected", ({ input, expected }) => { - expect(utils.formatShortSeedingPolicy(input)).toEqual(expected); - }); - test.each([ { id: "rad:zKtT7DmF9H34KkvcKj9PHW19WzjT",