Skip to content

Commit

Permalink
Add tauri commands for single repo and cobs
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastinez authored and rudolfs committed Sep 6, 2024
1 parent 0a059da commit 560891d
Show file tree
Hide file tree
Showing 14 changed files with 282 additions and 25 deletions.
3 changes: 3 additions & 0 deletions src-tauri/bindings/Author.ts
Original file line number Diff line number Diff line change
@@ -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 };
2 changes: 1 addition & 1 deletion src-tauri/bindings/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/
export type Config = {
/**
* Node alias.
* Node Public Key in NID format.
*/
publicKey: string;
/**
Expand Down
11 changes: 11 additions & 0 deletions src-tauri/bindings/Issue.ts
Original file line number Diff line number Diff line change
@@ -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<Author>;
labels: Array<string>;
};
26 changes: 26 additions & 0 deletions src-tauri/bindings/Patch.ts
Original file line number Diff line number Diff line change
@@ -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<Author>;
labels: Array<string>;
};
1 change: 1 addition & 0 deletions src-tauri/src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod auth;
pub mod cobs;
pub mod profile;
pub mod repos;
108 changes: 108 additions & 0 deletions src-tauri/src/commands/cobs.rs
Original file line number Diff line number Diff line change
@@ -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<AppState>,
rid: RepoId,
status: query::IssueStatus,
) -> Result<Vec<cobs::Issue>, 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::<Vec<_>>();

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::<Vec<_>>();

Ok::<_, Error>(issues)
}

#[tauri::command]
pub fn list_patches(
ctx: tauri::State<AppState>,
rid: RepoId,
status: query::PatchStatus,
) -> Result<Vec<cobs::Patch>, 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::<Vec<_>>();

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::<Vec<_>>();

Ok::<_, Error>(patches)
}

mod query {
use serde::{Deserialize, Serialize};

use radicle::issue;
use radicle::patch;

#[derive(Default, Serialize, Deserialize)]
#[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)]
#[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,
}
}
}
}
12 changes: 12 additions & 0 deletions src-tauri/src/commands/repos.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use radicle::identity::RepoId;
use radicle::storage::ReadStorage;

use crate::error::Error;
Expand Down Expand Up @@ -28,3 +29,14 @@ pub fn list_repos(ctx: tauri::State<AppState>) -> Result<Vec<types::repo::RepoIn

Ok::<_, Error>(infos)
}

#[tauri::command]
pub fn repo_by_id(
ctx: tauri::State<AppState>,
rid: RepoId,
) -> Result<types::repo::RepoInfo, Error> {
let (repo, doc) = ctx.repo(rid)?;
let repo_info = ctx.repo_info(&repo, doc)?;

Ok::<_, Error>(repo_info)
}
19 changes: 0 additions & 19 deletions src-tauri/src/json.rs

This file was deleted.

8 changes: 5 additions & 3 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
mod commands;
mod error;
mod json;
mod types;

use serde_json::json;
Expand All @@ -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 {
Expand All @@ -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::<Vec<_>>();
let db = &self.profile.database()?;
let seeding = db.count(&rid).unwrap_or_default();
Expand Down Expand Up @@ -107,6 +106,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!())
Expand Down
95 changes: 95 additions & 0 deletions src-tauri/src/types/cobs.rs
Original file line number Diff line number Diff line change
@@ -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(Serialize, TS)]
pub(crate) struct Author {
#[ts(as = "String")]
did: identity::Did,
#[serde(skip_serializing_if = "Option::is_none")]
#[ts(as = "Option<String>")]
#[ts(optional)]
alias: Option<Alias>,
}

impl Author {
pub fn new(did: identity::Did, aliases: &impl AliasStore) -> Self {
Self {
did,
alias: aliases.alias(&did),
}
}
}

#[derive(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<Author>,
#[ts(as = "Vec<String>")]
labels: Vec<Label>,
}

impl Issue {
pub fn new(id: issue::IssueId, issue: issue::Issue, aliases: &impl AliasStore) -> Self {
Self {
id: id.to_string(),
author: Author::new(*issue.author().id(), aliases),
title: issue.title().to_string(),
state: *issue.state(),
assignees: issue
.assignees()
.map(|did| Author::new(*did, aliases))
.collect::<Vec<_>>(),
labels: issue.labels().cloned().collect::<Vec<_>>(),
}
}
}

#[derive(TS, Serialize)]
#[ts(export)]
pub struct Patch {
#[ts(as = "String")]
id: String,
author: Author,
title: String,
#[ts(type = r#"{
status: 'draft'
} | {
status: 'open',
conflicts: [string, string][]
} | {
status: 'archived'
} | {
status: 'merged', revision: string, commit: string
} "#)]
state: patch::State,
assignees: Vec<Author>,
#[ts(as = "Vec<String>")]
labels: Vec<Label>,
}

impl Patch {
pub fn new(id: patch::PatchId, patch: patch::Patch, aliases: &impl AliasStore) -> Self {
Self {
id: id.to_string(),
author: Author::new(*patch.author().id(), aliases),
title: patch.title().to_string(),
state: patch.state().clone(),
assignees: patch
.assignees()
.map(|did| Author::new(did, aliases))
.collect::<Vec<_>>(),
labels: patch.labels().cloned().collect::<Vec<_>>(),
}
}
}
2 changes: 1 addition & 1 deletion src-tauri/src/types/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use radicle::node::config::DefaultSeedingPolicy;
use radicle::node::Alias;

/// Service configuration.
#[derive(Debug, Clone, TS, Serialize)]
#[derive(TS, Serialize)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct Config {
Expand Down
1 change: 1 addition & 0 deletions src-tauri/src/types/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod cobs;
pub mod config;
pub mod repo;
4 changes: 3 additions & 1 deletion src-tauri/src/types/repo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ use ts_rs::TS;

use radicle::identity::RepoId;

use super::cobs::Author;

/// Repos info.
#[derive(Serialize, TS)]
#[ts(export)]
pub struct RepoInfo {
pub payloads: SupportedPayloads,
#[ts(type = "({ id: string } | { id: string, alias?: string })[]")]
pub delegates: Vec<Value>,
pub delegates: Vec<Author>,
pub threshold: usize,
#[ts(type = "{ type: 'public' } | { type: 'private', allow?: string[] }")]
pub visibility: radicle::identity::Visibility,
Expand Down
15 changes: 15 additions & 0 deletions src/views/Home.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,24 @@
import Header from "@app/components/Header.svelte";
import RepoCard from "@app/components/RepoCard.svelte";
import { onMount } from "svelte";
import { invoke } from "@tauri-apps/api/core";
export let repos: RepoInfo[];
export let config: Config;
onMount(async () => {
const patches = await invoke("list_patches", {
rid: "rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5",
status: "open",
});
const issues = await invoke("list_issues", {
rid: "rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5",
status: "open",
});
console.log(patches, issues);
});
</script>

<style>
Expand Down

0 comments on commit 560891d

Please sign in to comment.