mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-11-04 03:00:32 +08:00
Make Operation generic, and handle patch operations
So far we only supported issue operations on the `activity_by_id` command. With this commit we separate the commands into a `activity_by_issue` and `activity_by_patch` command that calls a generic `activity_by_id` trait implementation. `Operation` now takes as a generic either `cob/issue/Action.ts` or `cob/patch/Action.ts`. Also `Operation` now stores the array of all `Action` that happened on said operation. I'm not entirely sure if this will help us in the future, but it represents more closely the state of the relation between an `Operation` and the cob `Actions`.
This commit is contained in:
@@ -2,12 +2,10 @@ use std::path::PathBuf;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
use radicle::cob;
|
||||
use radicle::git;
|
||||
use radicle::identity;
|
||||
use radicle_types as types;
|
||||
use radicle_types::error::Error;
|
||||
use radicle_types::traits::cobs::Cobs;
|
||||
use radicle_types::traits::thread::Thread;
|
||||
use tauri_plugin_clipboard_manager::ClipboardExt;
|
||||
use tauri_plugin_dialog::DialogExt;
|
||||
@@ -84,13 +82,3 @@ pub async fn save_embed_to_disk(
|
||||
|
||||
ctx.save_embed_to_disk(rid, oid, path)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn activity_by_id(
|
||||
ctx: tauri::State<AppState>,
|
||||
rid: identity::RepoId,
|
||||
type_name: cob::TypeName,
|
||||
id: git::Oid,
|
||||
) -> Result<Vec<types::cobs::issue::Operation>, Error> {
|
||||
ctx.activity_by_id(rid, type_name, id)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use radicle::git;
|
||||
use radicle::identity;
|
||||
|
||||
use radicle::issue::{Action, TYPENAME};
|
||||
use radicle_types as types;
|
||||
use radicle_types::error::Error;
|
||||
use radicle_types::traits::cobs::Cobs;
|
||||
use radicle_types::traits::issue::Issues;
|
||||
use radicle_types::traits::issue::IssuesMut;
|
||||
|
||||
@@ -55,3 +57,12 @@ pub(crate) fn comment_threads_by_issue_id(
|
||||
) -> Result<Option<Vec<types::cobs::thread::Thread>>, Error> {
|
||||
ctx.comment_threads_by_issue_id(rid, id)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn activity_by_issue(
|
||||
ctx: tauri::State<AppState>,
|
||||
rid: identity::RepoId,
|
||||
id: git::Oid,
|
||||
) -> Result<Vec<types::cobs::Operation<Action>>, Error> {
|
||||
ctx.activity_by_id(rid, &TYPENAME, id)
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@ use radicle::git;
|
||||
use radicle::identity;
|
||||
use radicle::patch;
|
||||
|
||||
use radicle::patch::{Action, TYPENAME};
|
||||
use radicle_types as types;
|
||||
use radicle_types::error::Error;
|
||||
use radicle_types::traits::cobs::Cobs;
|
||||
use radicle_types::traits::patch::Patches;
|
||||
use radicle_types::traits::patch::PatchesMut;
|
||||
|
||||
@@ -109,3 +111,12 @@ pub fn edit_patch(
|
||||
) -> Result<types::cobs::patch::Patch, Error> {
|
||||
ctx.edit_patch(rid, cob_id, action, opts)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn activity_by_patch(
|
||||
ctx: tauri::State<AppState>,
|
||||
rid: identity::RepoId,
|
||||
id: git::Oid,
|
||||
) -> Result<Vec<types::cobs::Operation<Action>>, Error> {
|
||||
ctx.activity_by_id(rid, &TYPENAME, id)
|
||||
}
|
||||
|
||||
@@ -78,15 +78,16 @@ pub fn run() {
|
||||
diff::get_diff,
|
||||
cob::get_embed,
|
||||
cob::save_embed_to_disk,
|
||||
cob::activity_by_id,
|
||||
cob::save_embed_by_path,
|
||||
cob::save_embed_by_clipboard,
|
||||
cob::save_embed_by_bytes,
|
||||
cob::issue::activity_by_issue,
|
||||
cob::issue::list_issues,
|
||||
cob::issue::issue_by_id,
|
||||
cob::issue::comment_threads_by_issue_id,
|
||||
cob::issue::create_issue,
|
||||
cob::issue::edit_issue,
|
||||
cob::patch::activity_by_patch,
|
||||
cob::patch::list_patches,
|
||||
cob::patch::patch_by_id,
|
||||
cob::patch::edit_patch,
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { Author } from "./Author";
|
||||
|
||||
/**
|
||||
* Everything that can be done in the system is represented by an `Op`.
|
||||
* Operations are applied to an accumulator to yield a final state.
|
||||
*/
|
||||
export type Operation<A> = {
|
||||
id: string;
|
||||
actions: Array<A>;
|
||||
author: Author;
|
||||
timestamp: number;
|
||||
};
|
||||
@@ -1,27 +0,0 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { Author } from "../Author";
|
||||
import type { Embed } from "../thread/Embed";
|
||||
import type { State } from "./State";
|
||||
|
||||
export type Operation =
|
||||
& { entryId: string; timestamp: number; author: Author }
|
||||
& (
|
||||
| { "type": "assign"; assignees: Array<string> }
|
||||
| { "type": "edit"; title: string }
|
||||
| { "type": "lifecycle"; state: State }
|
||||
| { "type": "label"; labels: Array<string> }
|
||||
| {
|
||||
"type": "comment";
|
||||
body: string;
|
||||
replyTo?: string;
|
||||
embeds?: Array<Embed>;
|
||||
}
|
||||
| {
|
||||
"type": "comment.edit";
|
||||
id: string;
|
||||
body: string;
|
||||
embeds?: Array<Embed>;
|
||||
}
|
||||
| { "type": "comment.redact"; id: string }
|
||||
| { "type": "comment.react"; id: string; reaction: string; active: boolean }
|
||||
);
|
||||
@@ -1,6 +1,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ts_rs::TS;
|
||||
|
||||
use radicle::cob;
|
||||
use radicle::identity;
|
||||
use radicle::node::{Alias, AliasStore};
|
||||
|
||||
@@ -31,6 +32,21 @@ impl Author {
|
||||
}
|
||||
}
|
||||
|
||||
/// Everything that can be done in the system is represented by an `Op`.
|
||||
/// Operations are applied to an accumulator to yield a final state.
|
||||
#[derive(Debug, Serialize, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
#[ts(export_to = "cob/")]
|
||||
pub struct Operation<A> {
|
||||
#[ts(as = "String")]
|
||||
pub id: cob::EntryId,
|
||||
pub actions: Vec<A>,
|
||||
pub author: Author,
|
||||
#[ts(type = "number")]
|
||||
pub timestamp: cob::Timestamp,
|
||||
}
|
||||
|
||||
#[derive(Serialize, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use radicle::git;
|
||||
use radicle::node::AliasStore;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ts_rs::TS;
|
||||
@@ -55,20 +54,6 @@ impl Issue {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
#[ts(export_to = "cob/issue/")]
|
||||
pub struct Operation {
|
||||
#[ts(as = "String")]
|
||||
pub entry_id: git::Oid,
|
||||
#[serde(flatten)]
|
||||
pub action: Action,
|
||||
#[ts(type = "number")]
|
||||
pub timestamp: cob::Timestamp,
|
||||
pub author: cobs::Author,
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, TS)]
|
||||
#[serde(rename_all = "camelCase", tag = "status")]
|
||||
#[ts(export)]
|
||||
|
||||
@@ -9,6 +9,10 @@ pub enum Error {
|
||||
#[error(transparent)]
|
||||
Profile(#[from] radicle::profile::Error),
|
||||
|
||||
/// CobStore error.
|
||||
#[error(transparent)]
|
||||
CobStore(#[from] radicle::cob::store::Error),
|
||||
|
||||
/// Anyhow error.
|
||||
#[error(transparent)]
|
||||
Anyhow(#[from] anyhow::Error),
|
||||
|
||||
@@ -2,39 +2,42 @@ use radicle::cob::object::Storage;
|
||||
use radicle::storage::refs::draft;
|
||||
use radicle::storage::{self, ReadStorage};
|
||||
use radicle::{cob, git, identity};
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::traits::Profile;
|
||||
|
||||
pub trait Cobs: Profile {
|
||||
fn activity_by_id(
|
||||
#[allow(clippy::unnecessary_filter_map)]
|
||||
fn activity_by_id<A: DeserializeOwned>(
|
||||
&self,
|
||||
rid: identity::RepoId,
|
||||
type_name: cob::TypeName,
|
||||
type_name: &cob::TypeName,
|
||||
id: git::Oid,
|
||||
) -> Result<Vec<crate::cobs::issue::Operation>, Error> {
|
||||
) -> Result<Vec<crate::cobs::Operation<A>>, Error> {
|
||||
let profile = self.profile();
|
||||
let aliases = profile.aliases();
|
||||
let repo = profile.storage.repository(rid)?;
|
||||
let ops = cob::store::ops(&id.into(), &type_name, &repo).unwrap();
|
||||
let mut actions: Vec<crate::cobs::issue::Operation> = Vec::new();
|
||||
let iter = cob::store::ops(&id.into(), type_name, &repo)?;
|
||||
let ops = iter
|
||||
.into_iter()
|
||||
.filter_map(|op| {
|
||||
let actions = op
|
||||
.actions
|
||||
.iter()
|
||||
.filter_map(|a| serde_json::from_slice(a).ok())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for op in ops.into_iter() {
|
||||
actions.extend(op.actions.iter().filter_map(
|
||||
|action: &Vec<u8>| -> Option<crate::cobs::issue::Operation> {
|
||||
let action: crate::cobs::issue::Action = serde_json::from_slice(action).ok()?;
|
||||
Some(crate::cobs::Operation {
|
||||
id: op.id,
|
||||
actions,
|
||||
author: crate::cobs::Author::new(&op.author.into(), &aliases),
|
||||
timestamp: op.timestamp,
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Some(crate::cobs::issue::Operation {
|
||||
entry_id: op.id,
|
||||
action,
|
||||
author: crate::cobs::Author::new(&op.author.into(), &aliases),
|
||||
timestamp: op.timestamp,
|
||||
})
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
Ok::<_, Error>(actions)
|
||||
Ok::<_, Error>(ops)
|
||||
}
|
||||
|
||||
fn publish_draft(
|
||||
|
||||
@@ -8,13 +8,14 @@ use axum::routing::post;
|
||||
use axum::Router;
|
||||
use hyper::header::CONTENT_TYPE;
|
||||
use hyper::Method;
|
||||
use radicle::cob::TypeName;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tower_http::cors::{self, CorsLayer};
|
||||
|
||||
use radicle::{git, identity};
|
||||
use radicle_types as types;
|
||||
use radicle_types::cobs::issue::{Action, NewIssue};
|
||||
use radicle_types::cobs::issue;
|
||||
use radicle_types::cobs::issue::NewIssue;
|
||||
use radicle_types::cobs::patch;
|
||||
use radicle_types::cobs::CobOptions;
|
||||
use radicle_types::error::Error;
|
||||
use radicle_types::traits::auth::Auth;
|
||||
@@ -57,7 +58,14 @@ pub fn router(ctx: Context) -> Router {
|
||||
.route("/list_repos", post(repo_root_handler))
|
||||
.route("/repo_by_id", post(repo_handler))
|
||||
.route("/diff_stats", post(diff_stats_handler))
|
||||
.route("/activity_by_id", post(activity_handler))
|
||||
.route(
|
||||
"/activity_by_issue",
|
||||
post(activity_issue_handler::<issue::Action>),
|
||||
)
|
||||
.route(
|
||||
"/activity_by_patch",
|
||||
post(activity_patch_handler::<patch::Action>),
|
||||
)
|
||||
.route("/get_diff", post(diff_handler))
|
||||
.route("/list_issues", post(issues_handler))
|
||||
.route("/create_issue", post(create_issue_handler))
|
||||
@@ -206,7 +214,7 @@ async fn create_issue_comment_handler(
|
||||
struct EditIssuesBody {
|
||||
pub rid: identity::RepoId,
|
||||
pub cob_id: git::Oid,
|
||||
pub action: Action,
|
||||
pub action: issue::Action,
|
||||
pub opts: CobOptions,
|
||||
}
|
||||
|
||||
@@ -228,15 +236,23 @@ async fn edit_issue_handler(
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct ActivityBody {
|
||||
pub rid: identity::RepoId,
|
||||
pub type_name: TypeName,
|
||||
pub id: git::Oid,
|
||||
}
|
||||
|
||||
async fn activity_handler(
|
||||
async fn activity_issue_handler<A: serde::Serialize + serde::de::DeserializeOwned>(
|
||||
State(ctx): State<Context>,
|
||||
Json(ActivityBody { rid, type_name, id }): Json<ActivityBody>,
|
||||
Json(ActivityBody { rid, id }): Json<ActivityBody>,
|
||||
) -> impl IntoResponse {
|
||||
let activity = ctx.activity_by_id(rid, type_name, id)?;
|
||||
let activity = ctx.activity_by_id::<A>(rid, &radicle::cob::issue::TYPENAME, id)?;
|
||||
|
||||
Ok::<_, Error>(Json(activity))
|
||||
}
|
||||
|
||||
async fn activity_patch_handler<A: serde::Serialize + serde::de::DeserializeOwned>(
|
||||
State(ctx): State<Context>,
|
||||
Json(ActivityBody { rid, id }): Json<ActivityBody>,
|
||||
) -> impl IntoResponse {
|
||||
let activity = ctx.activity_by_id::<A>(rid, &radicle::cob::patch::TYPENAME, id)?;
|
||||
|
||||
Ok::<_, Error>(Json(activity))
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { Operation } from "@bindings/cob/issue/Operation";
|
||||
import type { Operation } from "@bindings/cob/Operation";
|
||||
import type { Action } from "@bindings/cob/issue/Action";
|
||||
|
||||
import { authorForNodeId, formatTimestamp } from "@app/lib/utils";
|
||||
|
||||
@@ -8,19 +9,20 @@
|
||||
import NodeId from "@app/components/NodeId.svelte";
|
||||
|
||||
interface Props {
|
||||
operation: Extract<Operation, { type: "lifecycle" }>;
|
||||
action: Extract<Action, { type: "lifecycle" }>;
|
||||
op: Operation<Action>;
|
||||
}
|
||||
|
||||
const { operation }: Props = $props();
|
||||
const { op, action }: Props = $props();
|
||||
</script>
|
||||
|
||||
<Border variant="float" stylePadding="1rem">
|
||||
<div class="txt-small">
|
||||
<div class="global-flex txt-small">
|
||||
<NodeId {...authorForNodeId(operation.author)} />
|
||||
<NodeId {...authorForNodeId(op.author)} />
|
||||
changed status to
|
||||
<IssueStateBadge state={operation.state} />
|
||||
{formatTimestamp(operation.timestamp)}
|
||||
<IssueStateBadge state={action.state} />
|
||||
{formatTimestamp(op.timestamp)}
|
||||
</div>
|
||||
</div>
|
||||
</Border>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<script lang="ts">
|
||||
import type { Operation } from "@bindings/cob/Operation";
|
||||
import type { Action } from "@bindings/cob/patch/Action";
|
||||
|
||||
import { authorForNodeId, formatTimestamp } from "@app/lib/utils";
|
||||
|
||||
import Border from "@app/components/Border.svelte";
|
||||
import NodeId from "@app/components/NodeId.svelte";
|
||||
import PatchStateBadge from "./PatchStateBadge.svelte";
|
||||
|
||||
interface Props {
|
||||
action: Extract<Action, { type: "lifecycle" }>;
|
||||
op: Operation<Action>;
|
||||
}
|
||||
|
||||
const { op, action }: Props = $props();
|
||||
</script>
|
||||
|
||||
<Border variant="float" stylePadding="1rem">
|
||||
<div class="txt-small">
|
||||
<div class="global-flex txt-small">
|
||||
<NodeId {...authorForNodeId(op.author)} />
|
||||
changed status to
|
||||
<PatchStateBadge state={action.state} />
|
||||
{formatTimestamp(op.timestamp)}
|
||||
</div>
|
||||
</div>
|
||||
</Border>
|
||||
+24
-22
@@ -1,9 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { Action } from "@bindings/cob/issue/Action";
|
||||
import type { Author } from "@bindings/cob/Author";
|
||||
import type { Config } from "@bindings/config/Config";
|
||||
import type { Embed } from "@bindings/cob/thread/Embed";
|
||||
import type { Issue } from "@bindings/cob/issue/Issue";
|
||||
import type { Operation } from "@bindings/cob/issue/Operation";
|
||||
import type { Operation } from "@bindings/cob/Operation";
|
||||
import type { RepoInfo } from "@bindings/repo/RepoInfo";
|
||||
import type { Thread } from "@bindings/cob/thread/Thread";
|
||||
import type { IssueStatus } from "./router";
|
||||
@@ -45,7 +46,7 @@
|
||||
repo: RepoInfo;
|
||||
issue: Issue;
|
||||
issues: Issue[];
|
||||
activity: Operation[];
|
||||
activity: Operation<Action>[];
|
||||
config: Config;
|
||||
threads: Thread[];
|
||||
status: IssueStatus;
|
||||
@@ -149,9 +150,8 @@
|
||||
rid: repo.rid,
|
||||
id: issue.id,
|
||||
}),
|
||||
invoke<Operation[]>("activity_by_id", {
|
||||
invoke<Operation<Action>[]>("activity_by_issue", {
|
||||
rid: repo.rid,
|
||||
typeName: "xyz.radicle.issue",
|
||||
id: issue.id,
|
||||
}),
|
||||
invoke<Thread[]>("comment_threads_by_issue_id", {
|
||||
@@ -524,26 +524,28 @@
|
||||
|
||||
<div>
|
||||
{#each activity as op}
|
||||
{#if op.type === "lifecycle"}
|
||||
<IssueTimelineLifecycleAction operation={op} />
|
||||
<div class="connector"></div>
|
||||
{:else if op.type === "comment"}
|
||||
{@const thread = threads.find(t => t.root.id === op.entryId)}
|
||||
{#if thread}
|
||||
<ThreadComponent
|
||||
{thread}
|
||||
rid={repo.rid}
|
||||
canEditComment={partial(
|
||||
roles.isDelegateOrAuthor,
|
||||
config.publicKey,
|
||||
repo.delegates.map(delegate => delegate.did),
|
||||
)}
|
||||
{editComment}
|
||||
createReply={partial(createReply)}
|
||||
reactOnComment={partial(reactOnComment, config.publicKey)} />
|
||||
{#each op.actions as action}
|
||||
{#if action.type === "lifecycle"}
|
||||
<IssueTimelineLifecycleAction {op} {action} />
|
||||
<div class="connector"></div>
|
||||
{:else if action.type === "comment"}
|
||||
{@const thread = threads.find(t => t.root.id === op.id)}
|
||||
{#if thread}
|
||||
<ThreadComponent
|
||||
{thread}
|
||||
rid={repo.rid}
|
||||
canEditComment={partial(
|
||||
roles.isDelegateOrAuthor,
|
||||
config.publicKey,
|
||||
repo.delegates.map(delegate => delegate.did),
|
||||
)}
|
||||
{editComment}
|
||||
createReply={partial(createReply)}
|
||||
reactOnComment={partial(reactOnComment, config.publicKey)} />
|
||||
<div class="connector"></div>
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
{/each}
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { Operation } from "@bindings/cob/Operation";
|
||||
import type { Action } from "@bindings/cob/patch/Action";
|
||||
import type { Author } from "@bindings/cob/Author";
|
||||
import type { Config } from "@bindings/config/Config";
|
||||
import type { Diff } from "@bindings/diff/Diff";
|
||||
@@ -45,6 +47,7 @@
|
||||
patches: PaginatedQuery<Patch[]>;
|
||||
revisions: Revision[];
|
||||
config: Config;
|
||||
activity: Operation<Action>[];
|
||||
status: PatchStatus | undefined;
|
||||
}
|
||||
|
||||
@@ -56,6 +59,7 @@
|
||||
revisions,
|
||||
config,
|
||||
status: initialStatus,
|
||||
activity,
|
||||
}: Props = $props();
|
||||
/* eslint-enable prefer-const */
|
||||
|
||||
@@ -535,6 +539,17 @@
|
||||
) && partial(editRevision, revisions[0].id)}>
|
||||
</CommentComponent>
|
||||
</div>
|
||||
<div class="connector"></div>
|
||||
<div>
|
||||
{#each activity as op}
|
||||
{#each op.actions as action}
|
||||
{#if action.type === "revision"}
|
||||
<div>New revision created {action.oid}</div>
|
||||
<div class="connector"></div>
|
||||
{/if}
|
||||
{/each}
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
{@const revision = revisions.slice(-1)[0]}
|
||||
{#await loadHighlightedDiff(repo.rid, revision.base, revision.head) then diff}
|
||||
|
||||
+39
-23
@@ -1,7 +1,9 @@
|
||||
import type { Action as IssueAction } from "@bindings/cob/issue/Action";
|
||||
import type { Action as PatchAction } from "@bindings/cob/patch/Action";
|
||||
import type { Config } from "@bindings/config/Config";
|
||||
import type { Thread } from "@bindings/cob/thread/Thread";
|
||||
import type { Issue } from "@bindings/cob/issue/Issue";
|
||||
import type { Operation } from "@bindings/cob/issue/Operation";
|
||||
import type { Operation } from "@bindings/cob/Operation";
|
||||
import type { PaginatedQuery } from "@bindings/cob/PaginatedQuery";
|
||||
import type { Patch } from "@bindings/cob/patch/Patch";
|
||||
import type { RepoInfo } from "@bindings/repo/RepoInfo";
|
||||
@@ -33,7 +35,7 @@ export interface LoadedRepoIssueRoute {
|
||||
issue: Issue;
|
||||
issues: Issue[];
|
||||
status: IssueStatus;
|
||||
activity: Operation[];
|
||||
activity: Operation<IssueAction>[];
|
||||
threads: Thread[];
|
||||
};
|
||||
}
|
||||
@@ -82,6 +84,7 @@ export interface LoadedRepoPatchRoute {
|
||||
patches: PaginatedQuery<Patch[]>;
|
||||
status: PatchStatus | undefined;
|
||||
revisions: Revision[];
|
||||
activity: Operation<PatchAction>[];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -117,28 +120,42 @@ export type LoadedRepoRoute =
|
||||
export async function loadPatch(
|
||||
route: RepoPatchRoute,
|
||||
): Promise<LoadedRepoPatchRoute> {
|
||||
const [config, repo, patches, patch, revisions] = await Promise.all([
|
||||
invoke<Config>("config"),
|
||||
invoke<RepoInfo>("repo_by_id", {
|
||||
rid: route.rid,
|
||||
}),
|
||||
invoke<PaginatedQuery<Patch[]>>("list_patches", {
|
||||
rid: route.rid,
|
||||
status: route.status,
|
||||
}),
|
||||
invoke<Patch>("patch_by_id", {
|
||||
rid: route.rid,
|
||||
id: route.patch,
|
||||
}),
|
||||
invoke<Revision[]>("revisions_by_patch", {
|
||||
rid: route.rid,
|
||||
id: route.patch,
|
||||
}),
|
||||
]);
|
||||
const [config, repo, patches, patch, revisions, activity] = await Promise.all(
|
||||
[
|
||||
invoke<Config>("config"),
|
||||
invoke<RepoInfo>("repo_by_id", {
|
||||
rid: route.rid,
|
||||
}),
|
||||
invoke<PaginatedQuery<Patch[]>>("list_patches", {
|
||||
rid: route.rid,
|
||||
status: route.status,
|
||||
}),
|
||||
invoke<Patch>("patch_by_id", {
|
||||
rid: route.rid,
|
||||
id: route.patch,
|
||||
}),
|
||||
invoke<Revision[]>("revisions_by_patch", {
|
||||
rid: route.rid,
|
||||
id: route.patch,
|
||||
}),
|
||||
invoke<Operation<PatchAction>[]>("activity_by_patch", {
|
||||
rid: route.rid,
|
||||
id: route.patch,
|
||||
}),
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
resource: "repo.patch",
|
||||
params: { repo, config, patch, patches, revisions, status: route.status },
|
||||
params: {
|
||||
repo,
|
||||
config,
|
||||
patch,
|
||||
patches,
|
||||
revisions,
|
||||
status: route.status,
|
||||
activity,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -194,9 +211,8 @@ export async function loadIssue(
|
||||
rid: route.rid,
|
||||
id: route.issue,
|
||||
}),
|
||||
invoke<Operation[]>("activity_by_id", {
|
||||
invoke<Operation<IssueAction>[]>("activity_by_issue", {
|
||||
rid: route.rid,
|
||||
typeName: "xyz.radicle.issue",
|
||||
id: route.issue,
|
||||
}),
|
||||
invoke<Issue[]>("list_issues", {
|
||||
|
||||
Reference in New Issue
Block a user