Narrow down IssueOp type by flattening it

This commit is contained in:
Sebastian Martinez
2024-10-22 12:29:35 +02:00
committed by Rūdolfs Ošiņš
parent 5ed10a408c
commit caebd0a325
4 changed files with 79 additions and 40 deletions
+48
View File
@@ -0,0 +1,48 @@
// 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";
export type IssueOp = { entryId: string; timestamp: number; author: Author } & (
| { type: "assign"; assignees: Array<string> }
| { type: "edit"; title: string }
| {
type: "lifecycle";
state:
| { status: "closed"; reason: "other" | "solved" }
| { status: "open" };
}
| { type: "label"; labels: Array<string> }
| {
type: "comment";
/**
* Comment body.
*/
body: string;
/**
* Comment this is a reply to.
* Should be [`None` | `null`] if it's the top-level comment.
* Should be the root [`CommentId`] if it's a top-level comment.
*/
replyTo: string | null;
/**
* Embeded content.
*/
embeds: Array<string>;
}
| {
type: "comment.edit";
/**
* Comment being edited.
*/
id: string;
/**
* New value for the comment body.
*/
body: string;
/**
* New value for the embeds list.
*/
embeds: Array<string>;
}
| { type: "comment.redact"; id: string }
| { type: "comment.react"; id: string; reaction: string; active: boolean }
);
-10
View File
@@ -1,10 +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 { IssueAction } from "./IssueAction";
export type IssueOps = {
id: string;
action: IssueAction;
timestamp: number;
author: Author;
};
+18 -16
View File
@@ -5,6 +5,7 @@ use radicle::git;
use radicle::identity;
use radicle::storage::{ReadRepository, ReadStorage};
use crate::types::cobs::IssueAction;
use crate::{error, types, AppState};
pub mod draft;
@@ -12,14 +13,16 @@ pub mod issue;
pub mod patch;
#[derive(serde::Serialize, ts_rs::TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct IssueOps {
pub struct IssueOp {
#[ts(as = "String")]
id: git::Oid,
action: types::cobs::IssueAction,
pub entry_id: git::Oid,
#[serde(flatten)]
pub action: types::cobs::IssueAction,
#[ts(type = "number")]
timestamp: cob::Timestamp,
author: types::cobs::Author,
pub timestamp: cob::Timestamp,
pub author: types::cobs::Author,
}
#[tauri::command]
@@ -53,25 +56,24 @@ pub fn activity_by_id(
rid: identity::RepoId,
type_name: cob::TypeName,
id: git::Oid,
) -> Result<Vec<serde_json::Value>, error::Error> {
) -> Result<Vec<IssueOp>, error::Error> {
let aliases = ctx.profile.aliases();
let repo = ctx.profile.storage.repository(rid)?;
let ops = cob::store::ops(&id.into(), &type_name, &repo).unwrap();
let mut actions: Vec<serde_json::Value> = Vec::new();
let mut actions: Vec<IssueOp> = Vec::new();
for op in ops.into_iter() {
actions.extend(
op.actions
.iter()
.filter_map(|action: &Vec<u8>| -> Option<serde_json::Value> {
serde_json::from_slice(action).ok()
})
.map(|action| {
serde_json::json!({
"id": op.id,
"action": action,
"author": types::cobs::Author::new(op.author.into(), &aliases),
"timestamp": op.timestamp
.filter_map(|action: &Vec<u8>| -> Option<IssueOp> {
let action: IssueAction = serde_json::from_slice(action).ok()?;
Some(IssueOp {
entry_id: op.id,
action,
author: types::cobs::Author::new(op.author.into(), &aliases),
timestamp: op.timestamp,
})
}),
)
+13 -14
View File
@@ -2,7 +2,7 @@
import type { Config } from "@bindings/Config";
import type { Issue } from "@bindings/Issue";
import type { RepoInfo } from "@bindings/RepoInfo";
import type { IssueOps } from "@bindings/IssueOps";
import type { IssueOp } from "@bindings/IssueOp";
import capitalize from "lodash/capitalize";
@@ -221,32 +221,31 @@
{/if}
</div>
<div>
{#await invoke<IssueOps[]>( "activity_by_id", { rid: repo.rid, typeName: "xyz.radicle.issue", id: issue.id }, ) then activity}
{#each activity.slice(1) as { action, timestamp, author }}
{#if action.type === "lifecycle"}
{#await invoke<IssueOp[]>( "activity_by_id", { rid: repo.rid, typeName: "xyz.radicle.issue", id: issue.id }, ) then activity}
{#each activity.slice(1) as op}
{#if op.type === "lifecycle"}
<div class="txt-small body">
<div class="global-flex txt-small">
<NodeId {...authorForNodeId(author)} />
alias={author.alias} /> change of status to {action.state
.status}
<NodeId {...authorForNodeId(op.author)} />
alias={op.author.alias} /> change of status to {op.state.status}
<!-- <div class="global-oid"></div> -->
{formatTimestamp(timestamp)}
{formatTimestamp(op.timestamp)}
</div>
</div>
{:else if action.type === "comment"}
{:else if op.type === "comment"}
<div class="txt-small body">
<Markdown rid={repo.rid} breaks content={action.body} />
<Markdown rid={repo.rid} breaks content={op.body} />
<div class="global-flex txt-small" style:margin-top="1.5rem">
<NodeId {...authorForNodeId(author)} />
{#if action.replyTo}
<NodeId {...authorForNodeId(op.author)} />
{#if op.replyTo}
replied to <div class="global-oid">
{formatOid(action.replyTo)}
{formatOid(op.replyTo)}
</div>
{:else}
commented
{/if}
<!-- <div class="global-oid"></div> -->
{formatTimestamp(timestamp)}
{formatTimestamp(op.timestamp)}
</div>
</div>
{/if}