From 7f91111cc81b11f5ba942b48eb1d2983f770350f Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Fri, 6 Sep 2024 12:19:07 +0200 Subject: [PATCH] Add tauri commands for single repo and cobs --- src-tauri/bindings/Author.ts | 3 + src-tauri/bindings/Config.ts | 2 +- src-tauri/bindings/Issue.ts | 11 ++++ src-tauri/bindings/Patch.ts | 26 ++++++++ src-tauri/src/commands.rs | 1 + src-tauri/src/commands/cobs.rs | 108 ++++++++++++++++++++++++++++++++ src-tauri/src/commands/repos.rs | 12 ++++ src-tauri/src/json.rs | 19 ------ src-tauri/src/lib.rs | 8 ++- src-tauri/src/types/cobs.rs | 95 ++++++++++++++++++++++++++++ src-tauri/src/types/mod.rs | 1 + src-tauri/src/types/repo.rs | 8 ++- src/views/Home.svelte | 15 +++++ 13 files changed, 283 insertions(+), 26 deletions(-) create mode 100644 src-tauri/bindings/Author.ts create mode 100644 src-tauri/bindings/Issue.ts create mode 100644 src-tauri/bindings/Patch.ts create mode 100644 src-tauri/src/commands/cobs.rs delete mode 100644 src-tauri/src/json.rs create mode 100644 src-tauri/src/types/cobs.rs diff --git a/src-tauri/bindings/Author.ts b/src-tauri/bindings/Author.ts new file mode 100644 index 0000000..3784bce --- /dev/null +++ b/src-tauri/bindings/Author.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type Author = { did: string; alias?: string }; diff --git a/src-tauri/bindings/Config.ts b/src-tauri/bindings/Config.ts index 789e732..dbce075 100644 --- a/src-tauri/bindings/Config.ts +++ b/src-tauri/bindings/Config.ts @@ -5,7 +5,7 @@ */ export type Config = { /** - * Node alias. + * Node Public Key in NID format. */ publicKey: string; /** diff --git a/src-tauri/bindings/Issue.ts b/src-tauri/bindings/Issue.ts new file mode 100644 index 0000000..995cc23 --- /dev/null +++ b/src-tauri/bindings/Issue.ts @@ -0,0 +1,11 @@ +// 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 Issue = { + id: string; + author: Author; + title: string; + state: { status: "closed"; reason: "other" | "solved" } | { status: "open" }; + assignees: Array; + labels: Array; +}; diff --git a/src-tauri/bindings/Patch.ts b/src-tauri/bindings/Patch.ts new file mode 100644 index 0000000..446b347 --- /dev/null +++ b/src-tauri/bindings/Patch.ts @@ -0,0 +1,26 @@ +// 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 Patch = { + id: string; + author: Author; + title: string; + state: + | { + status: "draft"; + } + | { + status: "open"; + conflicts: [string, string][]; + } + | { + status: "archived"; + } + | { + status: "merged"; + revision: string; + commit: string; + }; + assignees: Array; + labels: Array; +}; diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 14f9d2f..0198bbe 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -1,3 +1,4 @@ pub mod auth; +pub mod cobs; pub mod profile; pub mod repos; diff --git a/src-tauri/src/commands/cobs.rs b/src-tauri/src/commands/cobs.rs new file mode 100644 index 0000000..3ef3801 --- /dev/null +++ b/src-tauri/src/commands/cobs.rs @@ -0,0 +1,108 @@ +use radicle::identity::RepoId; +use radicle::issue::cache::Issues; +use radicle::patch::cache::Patches; + +use crate::error::Error; +use crate::types::cobs; +use crate::AppState; + +#[tauri::command] +pub fn list_issues( + ctx: tauri::State, + rid: RepoId, + status: query::IssueStatus, +) -> Result, Error> { + let (repo, _) = ctx.repo(rid)?; + let issues = ctx.profile.issues(&repo)?; + let mut issues: Vec<_> = issues + .list()? + .filter_map(|r| { + let (id, issue) = r.ok()?; + (status.matches(issue.state())).then_some((id, issue)) + }) + .collect::>(); + + issues.sort_by(|(_, a), (_, b)| b.timestamp().cmp(&a.timestamp())); + let aliases = &ctx.profile.aliases(); + let issues = issues + .into_iter() + .map(|(id, issue)| cobs::Issue::new(id, issue, aliases)) + .collect::>(); + + Ok::<_, Error>(issues) +} + +#[tauri::command] +pub fn list_patches( + ctx: tauri::State, + rid: RepoId, + status: query::PatchStatus, +) -> Result, Error> { + let (repo, _) = ctx.repo(rid)?; + let patches = ctx.profile.patches(&repo)?; + let mut patches: Vec<_> = patches + .list()? + .filter_map(|r| { + let (id, patch) = r.ok()?; + (status.matches(patch.state())).then_some((id, patch)) + }) + .collect::>(); + + patches.sort_by(|(_, a), (_, b)| b.timestamp().cmp(&a.timestamp())); + let aliases = &ctx.profile.aliases(); + let patches = patches + .into_iter() + .map(|(id, patch)| cobs::Patch::new(id, patch, aliases)) + .collect::>(); + + Ok::<_, Error>(patches) +} + +mod query { + use serde::{Deserialize, Serialize}; + + use radicle::issue; + use radicle::patch; + + #[derive(Default, Serialize, Deserialize, Clone)] + #[serde(rename_all = "camelCase")] + pub enum IssueStatus { + Closed, + #[default] + Open, + All, + } + + impl IssueStatus { + pub fn matches(&self, issue: &issue::State) -> bool { + match self { + Self::Open => matches!(issue, issue::State::Open), + Self::Closed => matches!(issue, issue::State::Closed { .. }), + Self::All => true, + } + } + } + + #[derive(Default, Serialize, Deserialize, Clone)] + #[serde(rename_all = "camelCase")] + pub enum PatchStatus { + #[default] + Open, + Draft, + Archived, + Merged, + All, + } + + impl PatchStatus { + pub fn matches(&self, patch: &patch::State) -> bool { + match self { + Self::Open => matches!(patch, patch::State::Open { .. }), + Self::Draft => matches!(patch, patch::State::Draft), + Self::Archived => matches!(patch, patch::State::Archived), + Self::Merged => matches!(patch, patch::State::Merged { .. }), + Self::All => true, + } + } + } +} diff --git a/src-tauri/src/commands/repos.rs b/src-tauri/src/commands/repos.rs index 62ddbe2..a5e4ae2 100644 --- a/src-tauri/src/commands/repos.rs +++ b/src-tauri/src/commands/repos.rs @@ -1,3 +1,4 @@ +use radicle::identity::RepoId; use radicle::storage::ReadStorage; use crate::error::Error; @@ -28,3 +29,14 @@ pub fn list_repos(ctx: tauri::State) -> Result(infos) } + +#[tauri::command] +pub fn repo_by_id( + ctx: tauri::State, + rid: RepoId, +) -> Result { + let (repo, doc) = ctx.repo(rid)?; + let repo_info = ctx.repo_info(&repo, doc)?; + + Ok::<_, Error>(repo_info.clone()) +} diff --git a/src-tauri/src/json.rs b/src-tauri/src/json.rs deleted file mode 100644 index dbca949..0000000 --- a/src-tauri/src/json.rs +++ /dev/null @@ -1,19 +0,0 @@ -use serde_json::{json, Value}; - -use radicle::identity; -use radicle::node::AliasStore; - -pub(crate) struct Author<'a>(&'a identity::Did); - -impl<'a> Author<'a> { - pub fn new(did: &'a identity::Did) -> Self { - Self(did) - } - - pub fn as_json(&self, aliases: &impl AliasStore) -> Value { - aliases.alias(self.0).map_or( - json!({ "id": self.0 }), - |alias| json!({ "id": self.0, "alias": alias, }), - ) - } -} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 0f47e14..af46151 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,6 +1,5 @@ mod commands; mod error; -mod json; mod types; use serde_json::json; @@ -15,7 +14,7 @@ use radicle::patch::cache::Patches; use radicle::storage::git::Repository; use radicle::storage::{ReadRepository, ReadStorage}; -use commands::{auth, profile, repos}; +use commands::{auth, cobs, profile, repos}; use types::repo::SupportedPayloads; struct AppState { @@ -35,7 +34,7 @@ impl AppState { let delegates = doc .delegates .into_iter() - .map(|did| json::Author::new(&did).as_json(&aliases)) + .map(|did| types::cobs::Author::new(did, &aliases)) .collect::>(); let db = &self.profile.database()?; let seeding = db.count(&rid).unwrap_or_default(); @@ -102,6 +101,9 @@ pub fn run() { .invoke_handler(tauri::generate_handler![ auth::authenticate, repos::list_repos, + repos::repo_by_id, + cobs::list_issues, + cobs::list_patches, profile::config, ]) .run(tauri::generate_context!()) diff --git a/src-tauri/src/types/cobs.rs b/src-tauri/src/types/cobs.rs new file mode 100644 index 0000000..257c3cc --- /dev/null +++ b/src-tauri/src/types/cobs.rs @@ -0,0 +1,95 @@ +use radicle::cob::Label; +use radicle::identity; +use radicle::issue; +use radicle::node::{Alias, AliasStore}; +use radicle::patch; +use serde::Serialize; +use ts_rs::TS; + +#[derive(Clone, Serialize, TS)] +pub(crate) struct Author { + #[ts(as = "String")] + did: identity::Did, + #[serde(skip_serializing_if = "Option::is_none")] + #[ts(as = "Option")] + #[ts(optional)] + alias: Option, +} + +impl Author { + pub fn new(did: identity::Did, aliases: &impl AliasStore) -> Self { + Self { + did, + alias: aliases.alias(&did), + } + } +} + +#[derive(Clone, TS, Serialize)] +#[ts(export)] +pub struct Issue { + #[ts(as = "String")] + id: String, + author: Author, + title: String, + #[ts(type = "{ status: 'closed', reason: 'other' | 'solved' } | { status: 'open' } ")] + state: issue::State, + assignees: Vec, + #[ts(as = "Vec")] + labels: Vec