mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-10-30 00:31:03 +08:00
Simplify project view component
We refactor the project view by moving all sub-view related variables into the respective sub-views. Signed-off-by: Rūdolfs Ošiņš <rudolfs@osins.org>
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
<script lang="ts" strictEvents>
|
||||
<script lang="ts">
|
||||
import type { BaseUrl } from "@httpd-client";
|
||||
import type { Session } from "@app/lib/httpd";
|
||||
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
import * as httpd from "@app/lib/httpd";
|
||||
import * as modal from "@app/lib/modal";
|
||||
import * as router from "@app/lib/router";
|
||||
import * as utils from "@app/lib/utils";
|
||||
import { HttpdClient } from "@httpd-client";
|
||||
import { httpdStore } from "@app/lib/httpd";
|
||||
@@ -18,13 +17,12 @@
|
||||
import Markdown from "@app/components/Markdown.svelte";
|
||||
import TagInput from "@app/views/projects/Cob/TagInput.svelte";
|
||||
import Textarea from "@app/components/Textarea.svelte";
|
||||
import ErrorMessage from "@app/components/ErrorMessage.svelte";
|
||||
|
||||
export let session: Session;
|
||||
export let projectId: string;
|
||||
export let projectHead: string;
|
||||
export let baseUrl: BaseUrl;
|
||||
|
||||
const dispatch = createEventDispatcher<{ create: string }>();
|
||||
let preview: boolean = false;
|
||||
let action: "create" | "view";
|
||||
$: action =
|
||||
@@ -41,7 +39,7 @@
|
||||
|
||||
const api = new HttpdClient(baseUrl);
|
||||
|
||||
async function createIssue() {
|
||||
async function createIssue(sessionId: string) {
|
||||
try {
|
||||
const result = await api.project.createIssue(
|
||||
projectId,
|
||||
@@ -51,9 +49,20 @@
|
||||
assignees: utils.stripDidPrefix(assignees),
|
||||
tags: tags,
|
||||
},
|
||||
session.id,
|
||||
sessionId,
|
||||
);
|
||||
dispatch("create", result.id);
|
||||
|
||||
void router.push({
|
||||
resource: "projects",
|
||||
params: {
|
||||
id: projectId,
|
||||
hostAndPort: httpd.api.hostAndPort,
|
||||
view: {
|
||||
resource: "issue",
|
||||
params: { issue: result.id },
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch {
|
||||
modal.show({
|
||||
component: AuthenticationErrorModal,
|
||||
@@ -123,63 +132,75 @@
|
||||
</style>
|
||||
|
||||
<main>
|
||||
<div class="form">
|
||||
<div class="editor">
|
||||
<CobHeader {action} bind:title={issueTitle}>
|
||||
<svelte:fragment slot="state">
|
||||
{#if action === "view"}
|
||||
<Badge variant="positive">open</Badge>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="description">
|
||||
{#if action === "create"}
|
||||
<Textarea
|
||||
resizable
|
||||
bind:value={issueText}
|
||||
on:submit={createIssue}
|
||||
placeholder="Write a description" />
|
||||
{:else if !issueText}
|
||||
<p class="txt-missing">No description</p>
|
||||
{:else}
|
||||
<Markdown
|
||||
content={issueText}
|
||||
rawPath={utils.getRawBasePath(projectId, baseUrl, projectHead)} />
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
<div class="author" slot="author">
|
||||
{#if action === "view"}
|
||||
opened by <Authorship authorId={session.publicKey} /> now
|
||||
{/if}
|
||||
{#if $httpdStore.state === "authenticated"}
|
||||
{@const session = $httpdStore.session}
|
||||
<div class="form">
|
||||
<div class="editor">
|
||||
<CobHeader {action} bind:title={issueTitle}>
|
||||
<svelte:fragment slot="state">
|
||||
{#if action === "view"}
|
||||
<Badge variant="positive">open</Badge>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="description">
|
||||
{#if action === "create"}
|
||||
<Textarea
|
||||
resizable
|
||||
bind:value={issueText}
|
||||
on:submit={() => {
|
||||
void createIssue(session.id);
|
||||
}}
|
||||
placeholder="Write a description" />
|
||||
{:else if !issueText}
|
||||
<p class="txt-missing">No description</p>
|
||||
{:else}
|
||||
<Markdown
|
||||
content={issueText}
|
||||
rawPath={utils.getRawBasePath(
|
||||
projectId,
|
||||
baseUrl,
|
||||
projectHead,
|
||||
)} />
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
<div class="author" slot="author">
|
||||
{#if action === "view"}
|
||||
opened by <Authorship authorId={$httpdStore.session.publicKey} /> now
|
||||
{/if}
|
||||
</div>
|
||||
</CobHeader>
|
||||
<div class="actions">
|
||||
<Button
|
||||
size="small"
|
||||
variant="text"
|
||||
on:click={() => (preview = !preview)}>
|
||||
{#if preview}
|
||||
Resume editing
|
||||
{:else}
|
||||
Preview
|
||||
{/if}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={!issueTitle}
|
||||
size="small"
|
||||
variant="secondary"
|
||||
on:click={() => void createIssue(session.id)}>
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</CobHeader>
|
||||
<div class="actions">
|
||||
<Button
|
||||
size="small"
|
||||
variant="text"
|
||||
on:click={() => (preview = !preview)}>
|
||||
{#if preview}
|
||||
Resume editing
|
||||
{:else}
|
||||
Preview
|
||||
{/if}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={!issueTitle}
|
||||
size="small"
|
||||
variant="secondary"
|
||||
on:click={createIssue}>
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
<div class="metadata">
|
||||
<AssigneeInput
|
||||
{action}
|
||||
on:save={({ detail: updatedAssignees }) =>
|
||||
(assignees = updatedAssignees)} />
|
||||
<TagInput
|
||||
{action}
|
||||
on:save={({ detail: updatedTags }) => (tags = updatedTags)} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="metadata">
|
||||
<AssigneeInput
|
||||
{action}
|
||||
on:save={({ detail: updatedAssignees }) =>
|
||||
(assignees = updatedAssignees)} />
|
||||
<TagInput
|
||||
{action}
|
||||
on:save={({ detail: updatedTags }) => (tags = updatedTags)} />
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<ErrorMessage
|
||||
message="Couldn't access issue creation. Make sure you're still logged in." />
|
||||
{/if}
|
||||
</main>
|
||||
|
||||
@@ -21,11 +21,14 @@
|
||||
import ProjectLink from "@app/components/ProjectLink.svelte";
|
||||
import SquareButton from "@app/components/SquareButton.svelte";
|
||||
|
||||
export let search: string | undefined = undefined;
|
||||
export let projectId: string;
|
||||
export let state: IssueStatus;
|
||||
export let baseUrl: BaseUrl;
|
||||
export let issueCounters: { open: number; closed: number };
|
||||
|
||||
$: searchParams = new URLSearchParams(search || "");
|
||||
$: state = (searchParams.get("state") as IssueStatus) || "open";
|
||||
|
||||
const perPage = 10;
|
||||
|
||||
let loading = false;
|
||||
|
||||
@@ -63,14 +63,18 @@
|
||||
import SquareButton from "@app/components/SquareButton.svelte";
|
||||
import TagInput from "@app/views/projects/Cob/TagInput.svelte";
|
||||
|
||||
export let search: string | undefined = undefined;
|
||||
export let projectId: string;
|
||||
export let baseUrl: BaseUrl;
|
||||
export let patch: Patch;
|
||||
export let projectHead: string;
|
||||
export let projectDefaultBranch: string;
|
||||
export let revision: string;
|
||||
export let currentTab: "activity" | "commits" | "files";
|
||||
export let diff: string | undefined = undefined;
|
||||
export let revision: string | undefined = undefined;
|
||||
|
||||
$: searchParams = new URLSearchParams(search || "");
|
||||
$: currentTab =
|
||||
(searchParams.get("tab") as "activity" | "commits" | "files") || "activity";
|
||||
$: diff = searchParams.get("diff") || undefined;
|
||||
|
||||
const api = new HttpdClient(baseUrl);
|
||||
|
||||
@@ -136,7 +140,8 @@
|
||||
}));
|
||||
|
||||
$: currentRevision =
|
||||
patch.revisions.find(r => r.id === revision) || patch.revisions[0];
|
||||
(revision && patch.revisions.find(r => r.id === revision)) ||
|
||||
patch.revisions[patch.revisions.length - 1];
|
||||
$: timelineTuple = patch.revisions.map<
|
||||
[
|
||||
{
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
import ProjectLink from "@app/components/ProjectLink.svelte";
|
||||
import SquareButton from "@app/components/SquareButton.svelte";
|
||||
|
||||
export let search: string | undefined = undefined;
|
||||
export let projectId: string;
|
||||
export let state: PatchStatus;
|
||||
export let baseUrl: BaseUrl;
|
||||
export let patchCounters: {
|
||||
draft: number;
|
||||
@@ -28,6 +28,9 @@
|
||||
merged: number;
|
||||
};
|
||||
|
||||
$: searchParams = new URLSearchParams(search || "");
|
||||
$: state = (searchParams.get("state") as PatchStatus) || "open";
|
||||
|
||||
const perPage = 10;
|
||||
|
||||
let loading = false;
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { IssueStatus } from "./Issues.svelte";
|
||||
import type { PatchStatus } from "./Patches.svelte";
|
||||
import type { Project } from "@httpd-client";
|
||||
import type { ProjectLoadedView } from "@app/views/projects/router";
|
||||
|
||||
import * as httpd from "@app/lib/httpd";
|
||||
import * as router from "@app/lib/router";
|
||||
import * as utils from "@app/lib/utils";
|
||||
import { HttpdClient } from "@httpd-client";
|
||||
import { unreachable } from "@app/lib/utils";
|
||||
import { httpdStore } from "@app/lib/httpd";
|
||||
|
||||
import Loading from "@app/components/Loading.svelte";
|
||||
import ErrorMessage from "@app/components/ErrorMessage.svelte";
|
||||
import SourceBrowsingHeader from "./SourceBrowsingHeader.svelte";
|
||||
|
||||
import Browser from "./Browser.svelte";
|
||||
@@ -37,28 +29,7 @@
|
||||
export let revision: string | undefined = undefined;
|
||||
export let search: string | undefined = undefined;
|
||||
|
||||
$: searchParams = new URLSearchParams(search || "");
|
||||
$: issueFilter = (searchParams.get("state") as IssueStatus) || "open";
|
||||
$: patchTabFilter =
|
||||
(searchParams.get("tab") as "activity" | "commits" | "files") || "activity";
|
||||
$: patchFilter = (searchParams.get("state") as PatchStatus) || "open";
|
||||
$: patchDiffFilter = searchParams.get("diff") || undefined;
|
||||
$: baseUrl = utils.extractBaseUrl(hostAndPort);
|
||||
$: api = new HttpdClient(baseUrl);
|
||||
|
||||
function handleIssueCreation({ detail: issueId }: CustomEvent<string>) {
|
||||
void router.push({
|
||||
resource: "projects",
|
||||
params: {
|
||||
id,
|
||||
hostAndPort: httpd.api.hostAndPort,
|
||||
view: {
|
||||
resource: "issue",
|
||||
params: { issue: issueId },
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -74,14 +45,7 @@
|
||||
min-width: var(--content-min-width);
|
||||
padding-bottom: 4rem;
|
||||
}
|
||||
main > .message {
|
||||
padding: 0 2rem 0 8rem;
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
main > .message {
|
||||
padding-left: 2rem;
|
||||
}
|
||||
main {
|
||||
padding-top: 2rem;
|
||||
min-width: 0;
|
||||
@@ -133,36 +97,12 @@
|
||||
totalCommitCount={view.totalCommitCount}
|
||||
commitHeaders={view.commitHeaders} />
|
||||
{:else if view.resource === "commits"}
|
||||
{#await api.project.getCommitBySha(id, view.params.selectedCommit)}
|
||||
<Loading center />
|
||||
{:then fetchedCommit}
|
||||
<Commit commit={fetchedCommit} />
|
||||
{:catch e}
|
||||
<div class="message">
|
||||
<ErrorMessage message="Couln't load commit." stackTrace={e} />
|
||||
</div>
|
||||
{/await}
|
||||
<Commit commit={view.commit} />
|
||||
{/if}
|
||||
{:else if view.resource === "issues" && view.params?.view.resource === "new"}
|
||||
{#if $httpdStore.state === "authenticated"}
|
||||
<NewIssue
|
||||
on:create={handleIssueCreation}
|
||||
session={$httpdStore.session}
|
||||
projectId={id}
|
||||
projectHead={project.head}
|
||||
{baseUrl} />
|
||||
{:else}
|
||||
<div class="message">
|
||||
<ErrorMessage
|
||||
message="Couldn't access issue creation. Make sure you're still logged in." />
|
||||
</div>
|
||||
{/if}
|
||||
<NewIssue projectId={id} projectHead={project.head} {baseUrl} />
|
||||
{:else if view.resource === "issues"}
|
||||
<Issues
|
||||
{baseUrl}
|
||||
projectId={id}
|
||||
issueCounters={project.issues}
|
||||
state={issueFilter} />
|
||||
<Issues {baseUrl} projectId={id} issueCounters={project.issues} {search} />
|
||||
{:else if view.resource === "issue"}
|
||||
<Issue
|
||||
projectId={id}
|
||||
@@ -173,20 +113,17 @@
|
||||
<Patches
|
||||
{baseUrl}
|
||||
projectId={id}
|
||||
state={patchFilter}
|
||||
patchCounters={project.patches} />
|
||||
patchCounters={project.patches}
|
||||
{search} />
|
||||
{:else if view.resource === "patch"}
|
||||
{@const patch = view.params.loadedPatch}
|
||||
{@const latestRevision = patch.revisions[patch.revisions.length - 1]}
|
||||
<Patch
|
||||
{patch}
|
||||
patch={view.params.loadedPatch}
|
||||
{baseUrl}
|
||||
projectId={id}
|
||||
projectDefaultBranch={project.defaultBranch}
|
||||
projectHead={project.head}
|
||||
revision={view.params.revision ?? latestRevision.id}
|
||||
currentTab={patchTabFilter}
|
||||
diff={patchDiffFilter} />
|
||||
revision={view.params.revision}
|
||||
{search} />
|
||||
{:else}
|
||||
{unreachable(view)}
|
||||
{/if}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { LoadError } from "@app/lib/router/definitions";
|
||||
import type {
|
||||
Commit,
|
||||
CommitHeader,
|
||||
Issue,
|
||||
Patch,
|
||||
@@ -83,6 +84,7 @@ export type ProjectLoadedView =
|
||||
| {
|
||||
resource: "commits";
|
||||
params: LoadedSourceBrowsingParams;
|
||||
commit: Commit;
|
||||
}
|
||||
| {
|
||||
resource: "history";
|
||||
@@ -224,6 +226,25 @@ export async function loadProjectRoute(
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
if (params.view.resource === "commits") {
|
||||
const loadedCommit = await api.project.getCommitBySha(
|
||||
params.id,
|
||||
commit,
|
||||
);
|
||||
|
||||
return {
|
||||
resource: "projects",
|
||||
params: {
|
||||
...params,
|
||||
project,
|
||||
view: {
|
||||
resource: params.view.resource,
|
||||
params: viewParams,
|
||||
commit: loadedCommit,
|
||||
},
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
resource: "projects",
|
||||
|
||||
Reference in New Issue
Block a user