mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-11-11 23:20:34 +08:00
Show job cobs on latest revision and default branch commits
This commit is contained in:
Generated
+160
-6
@@ -191,6 +191,56 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.98"
|
||||
@@ -801,6 +851,47 @@ dependencies = [
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
"terminal_size",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
|
||||
|
||||
[[package]]
|
||||
name = "clipboard-win"
|
||||
version = "5.4.0"
|
||||
@@ -810,6 +901,12 @@ dependencies = [
|
||||
"error-code",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
|
||||
[[package]]
|
||||
name = "combine"
|
||||
version = "4.6.7"
|
||||
@@ -2561,6 +2658,12 @@ dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.8"
|
||||
@@ -3037,6 +3140,12 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nonempty"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "549e471b99ccaf2f89101bec68f4d244457d5a95a9c3d0672e9564124397741d"
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.6"
|
||||
@@ -3360,6 +3469,12 @@ version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.3.1"
|
||||
@@ -3952,7 +4067,7 @@ dependencies = [
|
||||
"localtime",
|
||||
"log",
|
||||
"multibase",
|
||||
"nonempty",
|
||||
"nonempty 0.9.0",
|
||||
"qcheck",
|
||||
"radicle-cob",
|
||||
"radicle-crypto",
|
||||
@@ -3977,7 +4092,7 @@ dependencies = [
|
||||
"fastrand",
|
||||
"git2",
|
||||
"log",
|
||||
"nonempty",
|
||||
"nonempty 0.9.0",
|
||||
"once_cell",
|
||||
"radicle-crypto",
|
||||
"radicle-dag",
|
||||
@@ -4033,6 +4148,25 @@ dependencies = [
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "radicle-job"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70b2de1bb748a1b587f759137058c4ae917753652b5fb4ae3baee991a7b31a68"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"indexmap 2.9.0",
|
||||
"nonempty 0.11.0",
|
||||
"once_cell",
|
||||
"qcheck",
|
||||
"radicle",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 2.0.12",
|
||||
"url",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "radicle-ssh"
|
||||
version = "0.9.0"
|
||||
@@ -4062,7 +4196,7 @@ dependencies = [
|
||||
"flate2",
|
||||
"git2",
|
||||
"log",
|
||||
"nonempty",
|
||||
"nonempty 0.9.0",
|
||||
"radicle-git-ext",
|
||||
"radicle-std-ext",
|
||||
"serde",
|
||||
@@ -4081,6 +4215,7 @@ dependencies = [
|
||||
"infer",
|
||||
"log",
|
||||
"radicle",
|
||||
"radicle-job",
|
||||
"radicle-surf",
|
||||
"radicle-types",
|
||||
"serde",
|
||||
@@ -4111,6 +4246,7 @@ dependencies = [
|
||||
"log",
|
||||
"mime-infer",
|
||||
"radicle",
|
||||
"radicle-job",
|
||||
"radicle-surf",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -5774,6 +5910,16 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "terminal_size"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed"
|
||||
dependencies = [
|
||||
"rustix 1.0.7",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-http-api"
|
||||
version = "0.1.0"
|
||||
@@ -6533,13 +6679,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.16.0"
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d"
|
||||
dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"js-sys",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -21,6 +21,7 @@ either = { version = "1.15" }
|
||||
infer = { version = "0.19.0" }
|
||||
log = { version = "0.4.22" }
|
||||
radicle = { version = "0.16.1" }
|
||||
radicle-job = { version = "0.2.0" }
|
||||
radicle-types = { version = "0.1.0", path = "../radicle-types" }
|
||||
radicle-surf = { version = "0.22.1", features = ["serde"] }
|
||||
serde = { version = "1.0.0", features = ["derive"] }
|
||||
|
||||
@@ -11,6 +11,7 @@ use tauri_plugin_dialog::DialogExt;
|
||||
use crate::AppState;
|
||||
|
||||
pub mod issue;
|
||||
pub mod job;
|
||||
pub mod patch;
|
||||
|
||||
#[tauri::command]
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
use radicle::git;
|
||||
use radicle::identity::RepoId;
|
||||
use radicle_types::cobs::job;
|
||||
use radicle_types::error::Error;
|
||||
use radicle_types::traits::job::Jobs;
|
||||
|
||||
use crate::AppState;
|
||||
|
||||
#[tauri::command]
|
||||
pub fn list_jobs(
|
||||
ctx: tauri::State<AppState>,
|
||||
rid: RepoId,
|
||||
sha: git::Oid,
|
||||
) -> Result<Vec<job::Job>, Error> {
|
||||
ctx.list_jobs(rid, sha)
|
||||
}
|
||||
@@ -32,6 +32,7 @@ pub fn run() {
|
||||
cob::issue::issue_by_id,
|
||||
cob::issue::list_issues,
|
||||
cob::issue::rebuild_issue_cache,
|
||||
cob::job::list_jobs,
|
||||
cob::patch::activity_by_patch,
|
||||
cob::patch::edit_patch,
|
||||
cob::patch::list_patches,
|
||||
|
||||
@@ -12,6 +12,7 @@ log = { version = "0.4.22" }
|
||||
infer = { version = "0.19.0" }
|
||||
mime-infer = { version = "3.0.0" }
|
||||
radicle = { version = "0.16.1" }
|
||||
radicle-job = { version = "0.2.0" }
|
||||
radicle-surf = { version = "0.22.1", features = ["serde"] }
|
||||
serde = { version = "1.0.0", features = ["derive"] }
|
||||
serde_json = { version = "1.0.0" }
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { Run } from "./Run";
|
||||
|
||||
export type Job = { jobId: string; commit: string; runs: Array<Run> };
|
||||
@@ -0,0 +1,5 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { Author } from "../cob/Author";
|
||||
import type { Status } from "./Status";
|
||||
|
||||
export type Run = { runId: string; node: Author; status: Status; log: string };
|
||||
@@ -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 Status = "started" | "failed" | "succeeded";
|
||||
@@ -10,6 +10,7 @@ use radicle::node::{Alias, AliasStore};
|
||||
|
||||
pub mod diff;
|
||||
pub mod issue;
|
||||
pub mod job;
|
||||
pub mod repo;
|
||||
pub mod stream;
|
||||
pub mod thread;
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
use radicle::git;
|
||||
use radicle::node::AliasStore;
|
||||
use serde::Serialize;
|
||||
use ts_rs::TS;
|
||||
use url::Url;
|
||||
|
||||
use crate::cobs;
|
||||
|
||||
#[derive(Clone, Serialize, TS, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
#[ts(export_to = "repo/")]
|
||||
pub struct Job {
|
||||
#[ts(as = "String")]
|
||||
pub job_id: radicle_job::JobId,
|
||||
#[ts(as = "String")]
|
||||
pub commit: git::Oid,
|
||||
pub runs: Vec<Run>,
|
||||
}
|
||||
|
||||
impl PartialEq for Job {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.job_id == other.job_id && self.commit == other.commit && self.runs == other.runs
|
||||
}
|
||||
}
|
||||
|
||||
impl Job {
|
||||
pub fn new(id: radicle_job::JobId, job: &radicle_job::Job, aliases: &impl AliasStore) -> Self {
|
||||
Self {
|
||||
job_id: id,
|
||||
commit: *job.oid(),
|
||||
runs: job
|
||||
.runs()
|
||||
.iter()
|
||||
.flat_map(|(node_id, runs)| {
|
||||
runs.iter().map(move |(run_id, run)| Run {
|
||||
run_id: run_id.to_string(),
|
||||
node: cobs::Author::new(&(*node_id).into(), aliases),
|
||||
status: (*run.status()).into(),
|
||||
log: run.log().clone(),
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, TS, Debug, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
#[ts(export_to = "repo/")]
|
||||
pub struct Run {
|
||||
pub run_id: String,
|
||||
pub node: cobs::Author,
|
||||
pub status: Status,
|
||||
#[ts(as = "String")]
|
||||
pub log: Url,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, TS, Debug, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
#[ts(export_to = "repo/")]
|
||||
pub enum Status {
|
||||
Started,
|
||||
Failed,
|
||||
Succeeded,
|
||||
}
|
||||
|
||||
impl From<radicle_job::Status> for Status {
|
||||
fn from(value: radicle_job::Status) -> Self {
|
||||
match value {
|
||||
radicle_job::Status::Started => Self::Started,
|
||||
radicle_job::Status::Finished(reason) => match reason {
|
||||
radicle_job::Reason::Failed => Self::Failed,
|
||||
radicle_job::Reason::Succeeded => Self::Succeeded,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
use traits::cobs::Cobs;
|
||||
use traits::issue::{Issues, IssuesMut};
|
||||
use traits::job::Jobs;
|
||||
use traits::patch::{Patches, PatchesMut};
|
||||
use traits::repo::Repo;
|
||||
use traits::thread::Thread;
|
||||
@@ -27,6 +28,7 @@ impl Thread for AppState {}
|
||||
impl Cobs for AppState {}
|
||||
impl Issues for AppState {}
|
||||
impl IssuesMut for AppState {}
|
||||
impl Jobs for AppState {}
|
||||
impl Patches for AppState {}
|
||||
impl PatchesMut for AppState {}
|
||||
impl Profile for AppState {
|
||||
|
||||
@@ -4,6 +4,7 @@ use crate::config::Config;
|
||||
|
||||
pub mod cobs;
|
||||
pub mod issue;
|
||||
pub mod job;
|
||||
pub mod patch;
|
||||
pub mod repo;
|
||||
pub mod thread;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
use radicle::storage::ReadStorage;
|
||||
use radicle::{git, identity};
|
||||
use radicle_job::{Job, JobId, Jobs as JobsStore};
|
||||
|
||||
use crate::cobs::job;
|
||||
use crate::error::Error;
|
||||
use crate::traits::Profile;
|
||||
|
||||
pub trait Jobs: Profile {
|
||||
fn list_jobs(&self, rid: identity::RepoId, sha: git::Oid) -> Result<Vec<job::Job>, Error> {
|
||||
let profile = self.profile();
|
||||
let repo = profile.storage.repository(rid)?;
|
||||
let aliases = &profile.aliases();
|
||||
|
||||
let jobs = JobsStore::open(&repo).unwrap();
|
||||
let found_jobs: Result<Vec<(JobId, Job)>, _> = jobs.find_by_commit(sha)?.collect();
|
||||
|
||||
Ok(found_jobs?
|
||||
.into_iter()
|
||||
.map(|(id, job)| job::Job::new(id, &job, aliases))
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ use radicle_types::error::Error;
|
||||
use radicle_types::outbound::sqlite::Sqlite;
|
||||
use radicle_types::traits::cobs::Cobs;
|
||||
use radicle_types::traits::issue::{Issues, IssuesMut};
|
||||
use radicle_types::traits::job::Jobs;
|
||||
use radicle_types::traits::patch::{Patches, PatchesMut};
|
||||
use radicle_types::traits::repo::{Repo, Show};
|
||||
use radicle_types::traits::thread::Thread;
|
||||
@@ -41,6 +42,7 @@ impl Cobs for Context {}
|
||||
impl Thread for Context {}
|
||||
impl Issues for Context {}
|
||||
impl IssuesMut for Context {}
|
||||
impl Jobs for Context {}
|
||||
impl Patches for Context {}
|
||||
impl PatchesMut for Context {}
|
||||
impl Profile for Context {
|
||||
@@ -90,6 +92,7 @@ pub fn router(ctx: Context) -> Router {
|
||||
.route("/save_embed_by_clipboard", post(save_embed_handler))
|
||||
.route("/save_embed_by_bytes", post(save_embed_handler))
|
||||
.route("/save_embed_to_disk", post(save_embed_handler))
|
||||
.route("/list_jobs", post(jobs_handler))
|
||||
.layer(
|
||||
CorsLayer::new()
|
||||
.allow_origin(cors::Any)
|
||||
@@ -470,3 +473,18 @@ async fn revision_handler(
|
||||
|
||||
Ok::<_, Error>(Json(revisions))
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct JobsBody {
|
||||
pub rid: identity::RepoId,
|
||||
pub sha: git::Oid,
|
||||
}
|
||||
|
||||
async fn jobs_handler(
|
||||
State(ctx): State<Context>,
|
||||
Json(JobsBody { rid, sha }): Json<JobsBody>,
|
||||
) -> impl IntoResponse {
|
||||
let jobs = ctx.list_jobs(rid, sha)?;
|
||||
|
||||
Ok::<_, Error>(Json(jobs))
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
import CommitsContainer from "@app/components/CommitsContainer.svelte";
|
||||
import Icon from "@app/components/Icon.svelte";
|
||||
import Id from "@app/components/Id.svelte";
|
||||
import JobCob from "@app/components/JobCob.svelte";
|
||||
import NakedButton from "@app/components/NakedButton.svelte";
|
||||
|
||||
interface Props {
|
||||
@@ -175,7 +176,7 @@
|
||||
<div class="global-counter">Base</div>
|
||||
</div>
|
||||
<div class="commits">
|
||||
{#each [...commits].reverse() as commit}
|
||||
{#each [...commits].reverse() as commit, idx}
|
||||
<div
|
||||
class="commit"
|
||||
class:single-commit={commits.length === 1}
|
||||
@@ -196,7 +197,11 @@
|
||||
commitId: commit.id,
|
||||
});
|
||||
}}
|
||||
{commit} />
|
||||
{commit}>
|
||||
{#if idx === commits.length - 1}
|
||||
<JobCob {rid} commit={commit.id} />
|
||||
{/if}
|
||||
</CobCommitTeaser>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { Commit } from "@bindings/repo/Commit";
|
||||
import type { Snippet } from "svelte";
|
||||
|
||||
import { twemoji } from "@app/lib/utils";
|
||||
|
||||
@@ -10,13 +11,20 @@
|
||||
import NakedButton from "@app/components/NakedButton.svelte";
|
||||
|
||||
interface Props {
|
||||
disabled: boolean;
|
||||
children?: Snippet;
|
||||
commit: Commit;
|
||||
onclick: () => void;
|
||||
disabled: boolean;
|
||||
hoverable?: boolean;
|
||||
onclick: () => void;
|
||||
}
|
||||
|
||||
const { disabled, hoverable = false, commit, onclick }: Props = $props();
|
||||
const {
|
||||
children,
|
||||
commit,
|
||||
disabled,
|
||||
hoverable = false,
|
||||
onclick,
|
||||
}: Props = $props();
|
||||
|
||||
let commitMessageVisible = $state(false);
|
||||
</script>
|
||||
@@ -99,6 +107,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
<div class="right">
|
||||
{@render children?.()}
|
||||
<CompactCommitAuthorship {commit}>
|
||||
<Id
|
||||
id={commit.id}
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
|
||||
interface Props {
|
||||
popover: Snippet;
|
||||
stylePopoverPositionBottom: string | undefined;
|
||||
stylePopoverPositionLeft: string | undefined;
|
||||
stylePopoverPositionBottom?: string | undefined;
|
||||
stylePopoverPositionLeft?: string | undefined;
|
||||
stylePopoverPositionRight?: string | undefined;
|
||||
stylePadding?: string | undefined;
|
||||
toggle: Snippet;
|
||||
}
|
||||
|
||||
@@ -14,6 +16,8 @@
|
||||
popover,
|
||||
stylePopoverPositionBottom,
|
||||
stylePopoverPositionLeft,
|
||||
stylePopoverPositionRight,
|
||||
stylePadding = "0.5rem 1rem",
|
||||
toggle,
|
||||
}: Props = $props();
|
||||
|
||||
@@ -31,8 +35,6 @@
|
||||
}
|
||||
.popover {
|
||||
background: var(--color-fill-ghost);
|
||||
border-radius: var(--border-radius-regular);
|
||||
padding: 0.5rem 1rem;
|
||||
box-shadow: var(--elevation-low);
|
||||
position: absolute;
|
||||
clip-path: var(--2px-corner-fill);
|
||||
@@ -41,9 +43,13 @@
|
||||
</style>
|
||||
|
||||
<div class="container">
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<div
|
||||
role="button"
|
||||
tabindex="0"
|
||||
onclick={e => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
onmouseenter={() => setVisible(true)}
|
||||
onmouseleave={() => setVisible(false)}>
|
||||
{@render toggle()}
|
||||
@@ -52,7 +58,9 @@
|
||||
<div style:position="absolute">
|
||||
<div
|
||||
class="popover"
|
||||
style:padding={stylePadding}
|
||||
style:left={stylePopoverPositionLeft}
|
||||
style:right={stylePopoverPositionRight}
|
||||
style:bottom={stylePopoverPositionBottom}>
|
||||
{@render popover()}
|
||||
</div>
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
| "checkbox-checked"
|
||||
| "checkbox-unchecked"
|
||||
| "checkmark"
|
||||
| "checkmark-double"
|
||||
| "checkout"
|
||||
| "chevron-down"
|
||||
| "chevron-right"
|
||||
@@ -34,6 +35,7 @@
|
||||
| "comment-cross"
|
||||
| "copy"
|
||||
| "cross"
|
||||
| "cross-double"
|
||||
| "dashboard"
|
||||
| "delegate"
|
||||
| "diff"
|
||||
@@ -47,6 +49,7 @@
|
||||
| "filter"
|
||||
| "folder-closed"
|
||||
| "folder-open"
|
||||
| "help"
|
||||
| "home"
|
||||
| "hourglass"
|
||||
| "inbox"
|
||||
@@ -296,6 +299,23 @@
|
||||
<path d="M4 8V9H3L3 8H4Z" />
|
||||
<path d="M5 9L5 10L4 10L4 9H5Z" />
|
||||
<path d="M6 10L6 11H5L5 10L6 10Z" />
|
||||
{:else if name === "checkmark-double"}
|
||||
<path d="M6 10L6 11H5L5 10H6Z" />
|
||||
<path d="M8 10V11H7L7 10H8Z" />
|
||||
<path d="M7 9L7 10L6 10V9H7Z" />
|
||||
<path d="M9 9V10H8V9L9 9Z" />
|
||||
<path d="M8 8L8 9L7 9L7 8H8Z" />
|
||||
<path d="M10 8V9L9 9V8H10Z" />
|
||||
<path d="M9 7L9 8L8 8L8 7H9Z" />
|
||||
<path d="M11 7V8L10 8L10 7H11Z" />
|
||||
<path d="M10 6V7L9 7V6L10 6Z" />
|
||||
<path d="M12 6V7H11V6H12Z" />
|
||||
<path d="M11 5V6L10 6V5L11 5Z" />
|
||||
<path d="M13 5V6L12 6V5L13 5Z" />
|
||||
<path d="M4 8V9H3L3 8H4Z" />
|
||||
<path d="M6 8L6 9L5 9V8H6Z" />
|
||||
<path d="M5 9L5 10H4L4 9H5Z" />
|
||||
<path d="M7 9L7 10L6 10V9H7Z" />
|
||||
{:else if name === "checkout"}
|
||||
<path d="M5 5H11V6H5V5Z" />
|
||||
<path d="M4 6L5 6L5 11H4L4 6Z" />
|
||||
@@ -522,6 +542,33 @@
|
||||
<path d="M6.00003 6L6.00003 7H7.00003L7.00003 6H6.00003Z" />
|
||||
<path d="M5.00003 5V6L6.00003 6V5L5.00003 5Z" />
|
||||
<path d="M4.00003 4L4.00003 5L5.00003 5L5.00003 4L4.00003 4Z" />
|
||||
{:else if name === "cross-double"}
|
||||
<path d="M4 11V12H3L3 11H4Z" />
|
||||
<path d="M5 10L5 11H4L4 10H5Z" />
|
||||
<path d="M6 9V10H5L5 9L6 9Z" />
|
||||
<path d="M7 7V8H6V7H7Z" />
|
||||
<path d="M10 5V6L9 6V5H10Z" />
|
||||
<path d="M11 4V5L10 5V4L11 4Z" />
|
||||
<path d="M9 10V11H10V10H9Z" />
|
||||
<path d="M10 11V12H11V11H10Z" />
|
||||
<path d="M8 9V10H9V9H8Z" />
|
||||
<path d="M7 8L7 9H8V8L7 8Z" />
|
||||
<path d="M5 6L5 7H6L6 6H5Z" />
|
||||
<path d="M4 5V6L5 6V5L4 5Z" />
|
||||
<path d="M3 4L3 5L4 5L4 4L3 4Z" />
|
||||
<path d="M6 11V12H5L5 11H6Z" />
|
||||
<path d="M7 10L7 11H6L6 10H7Z" />
|
||||
<path d="M9 7V8H8V7H9Z" />
|
||||
<path d="M11 6V7H10V6H11Z" />
|
||||
<path d="M12 5V6L11 6V5H12Z" />
|
||||
<path d="M13 4V5L12 5V4L13 4Z" />
|
||||
<path d="M11 10V11H12V10H11Z" />
|
||||
<path d="M12 11V12H13V11H12Z" />
|
||||
<path d="M10 9V10H11V9H10Z" />
|
||||
<path d="M9 8L9 9H10V8L9 8Z" />
|
||||
<path d="M7 6L7 7H8L8 6H7Z" />
|
||||
<path d="M6 5V6L7 6V5L6 5Z" />
|
||||
<path d="M5 4L5 5L6 5L6 4L5 4Z" />
|
||||
{:else if name === "dashboard"}
|
||||
<path d="M2 11H14V12H2V11Z" />
|
||||
<path d="M2 9H3V11H2L2 9Z" />
|
||||
@@ -721,6 +768,32 @@
|
||||
<path d="M4.5 8V10H3.5L3.5 8H4.5Z" />
|
||||
<path d="M14.5 8L14.5 10H13.5L13.5 8H14.5Z" />
|
||||
<path d="M11.5 12H12.5V13H11.5V12Z" />
|
||||
{:else if name === "help"}
|
||||
<path d="M9 12H8L8 14H9L9 12Z" />
|
||||
<path d="M8 12H7V14H8L8 12Z" />
|
||||
<path d="M11 5L11 7H12V5H11Z" />
|
||||
<path d="M11 5L11 7H12V5H11Z" />
|
||||
<path d="M10 5L10 7L11 7L11 5L10 5Z" />
|
||||
<path d="M5 4L5 6H4L4 4H5Z" />
|
||||
<path d="M6 4V6H5L5 4H6Z" />
|
||||
<path d="M11 4V5H12V4H11Z" />
|
||||
<path d="M10 4V5L11 5V4L10 4Z" />
|
||||
<path d="M9 8V9H10V8H9Z" />
|
||||
<path d="M8 9V10H9V9L8 9Z" />
|
||||
<path d="M8 10V11H9V10H8Z" />
|
||||
<path d="M6 4H5L5 3L6 3L6 4Z" />
|
||||
<path d="M9 4L11 4V3L9 3V4Z" />
|
||||
<path d="M11 6V7H12V6H11Z" />
|
||||
<path d="M10 6V7L11 7V6L10 6Z" />
|
||||
<path d="M9 7L9 8H10L10 7H9Z" />
|
||||
<path d="M8 8V9L9 9V8H8Z" />
|
||||
<path d="M7 9V10L8 10V9L7 9Z" />
|
||||
<path d="M7 10L7 11L8 11V10L7 10Z" />
|
||||
<path d="M10 7L10 8H11V7L10 7Z" />
|
||||
<path d="M7 3L6 3L6 2L7 2V3Z" />
|
||||
<path d="M7 4H6L6 3L7 3V4Z" />
|
||||
<path d="M7 3L9 3V2L7 2V3Z" />
|
||||
<path d="M7 4L9 4V3L7 3V4Z" />
|
||||
{:else if name === "home"}
|
||||
<path d="M7 1.50003H9V2.50003H7V1.50003Z" />
|
||||
<path d="M6 2.50003L7 2.50003V3.50003H6V2.50003Z" />
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
<script lang="ts">
|
||||
import type { Job } from "@bindings/repo/Job";
|
||||
|
||||
import { invoke } from "@app/lib/invoke";
|
||||
import { authorForNodeId } from "@app/lib/utils";
|
||||
|
||||
import HoverPopover from "@app/components/HoverPopover.svelte";
|
||||
import Icon from "@app/components/Icon.svelte";
|
||||
|
||||
import DropdownListItem from "./DropdownListItem.svelte";
|
||||
import NodeId from "./NodeId.svelte";
|
||||
|
||||
interface Props {
|
||||
commit: string;
|
||||
rid: string;
|
||||
}
|
||||
|
||||
const { commit, rid }: Props = $props();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.status {
|
||||
gap: 0.5rem;
|
||||
width: fit-content;
|
||||
}
|
||||
</style>
|
||||
|
||||
{#await invoke<Job[]>("list_jobs", { rid, sha: commit }) then jobs}
|
||||
{#if jobs.length > 0}
|
||||
<HoverPopover
|
||||
stylePadding="0.25rem"
|
||||
stylePopoverPositionBottom="2rem"
|
||||
stylePopoverPositionRight="-1.5rem">
|
||||
{#snippet toggle()}
|
||||
{#if jobs.every(j => {
|
||||
return j.runs.every(r => {
|
||||
return r.status === "succeeded";
|
||||
});
|
||||
})}
|
||||
<div
|
||||
class="global-counter"
|
||||
style:padding="0"
|
||||
style:color="var(--color-fill-success)"
|
||||
style:background-color="var(--color-fill-diff-green)">
|
||||
<Icon name="checkmark-double" />
|
||||
</div>
|
||||
{:else if jobs.every(j => {
|
||||
return j.runs.every(r => {
|
||||
return r.status === "failed";
|
||||
});
|
||||
})}
|
||||
<div
|
||||
class="global-counter"
|
||||
style:color="var(--color-foreground-red)"
|
||||
style:padding="0"
|
||||
style:background-color="var(--color-fill-diff-red)">
|
||||
<Icon name="cross-double" />
|
||||
</div>
|
||||
{:else}
|
||||
<div
|
||||
class="global-counter"
|
||||
style:padding="0"
|
||||
style:color="var(--color-fill-gray)"
|
||||
style:background-color="var(--color-fill-ghost)">
|
||||
<Icon name="help" />
|
||||
</div>
|
||||
{/if}
|
||||
{/snippet}
|
||||
|
||||
{#snippet popover()}
|
||||
{#each jobs as job}
|
||||
{#each job.runs as run}
|
||||
<a
|
||||
style:text-decoration="none"
|
||||
style:cursor="pointer"
|
||||
style:width="100%"
|
||||
href={run.log}
|
||||
target="_blank">
|
||||
<DropdownListItem styleGap="0.5rem" selected={true}>
|
||||
{#if run.status === "started"}
|
||||
<div
|
||||
class="global-counter status"
|
||||
style:background-color="var(--color-fill-float)"
|
||||
style:color="var(--color-fill-gray)">
|
||||
<Icon name="hourglass" /> Started
|
||||
</div>
|
||||
{:else if run.status === "failed"}
|
||||
<div
|
||||
class="global-counter status"
|
||||
style:color="var(--color-foreground-red)"
|
||||
style:background-color="var(--color-fill-diff-red)">
|
||||
<Icon name="cross" /> Failed
|
||||
</div>
|
||||
{:else if run.status === "succeeded"}
|
||||
<div
|
||||
class="global-counter status"
|
||||
style:color="var(--color-fill-success)"
|
||||
style:background-color="var(--color-fill-diff-green)">
|
||||
<Icon name="checkmark" /> Passed
|
||||
</div>
|
||||
{/if}
|
||||
<NodeId {...authorForNodeId(run.node)} />
|
||||
<div
|
||||
style:margin-left="auto"
|
||||
style:color="var(--color-fill-gray)">
|
||||
<Icon name="open-external" />
|
||||
</div>
|
||||
</DropdownListItem>
|
||||
</a>
|
||||
{/each}
|
||||
{/each}
|
||||
{/snippet}
|
||||
</HoverPopover>
|
||||
{/if}
|
||||
{/await}
|
||||
@@ -11,6 +11,8 @@
|
||||
import NodeId from "@app/components/NodeId.svelte";
|
||||
import VisibilityBadge from "@app/components/VisibilityBadge.svelte";
|
||||
|
||||
import JobCob from "./JobCob.svelte";
|
||||
|
||||
interface Props {
|
||||
horizontal?: boolean;
|
||||
repo: RepoInfo;
|
||||
@@ -111,13 +113,14 @@
|
||||
style:width="100%">
|
||||
<div class="metadata-section">
|
||||
<div class="metadata-section-title">Default branch</div>
|
||||
<span>
|
||||
<span class="global-flex">
|
||||
<span class="txt-selectable">{project.data.defaultBranch}</span>
|
||||
->
|
||||
<Id
|
||||
id={project.meta.head}
|
||||
clipboard={project.meta.head}
|
||||
variant="commit" />
|
||||
<JobCob rid={repo.rid} commit={project.meta.head} />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user