johnandersen777.bsky.social/knotless
git that lives in your Atmosphere account
Forked from chadtmiller.com/knotless
0
0
//! The views answers share, as `dev.knotless.defs` defines them: of
//! repositories, commits, checks and diffs.
use super::*;
/// `dev.knotless.defs#repoViewDetailed`: a repository, with what its pages
/// show above themselves.
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RepoViewDetailed {
pub uri: String,
pub owner: ActorView,
pub name: String,
/// Its key, which a rename keeps, as its record holds it.
#[serde(skip_serializing_if = "Option::is_none")]
pub key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
/// The links its pages show, in order, each an http or https address.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub links: Vec<ProfileLink>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fork_of: Option<RepoViewBasic>,
/// The default branch: empty, for a repository never pushed.
pub default_branch: String,
pub open_pulls: usize,
pub open_issues: usize,
/// Whether its pages lead to its merge queue: a branch's rule takes
/// pulls through it, or a pull waits in it still.
#[serde(skip_serializing_if = "std::ops::Not::not")]
pub merge_queue: bool,
/// The path of the picture its pages unfurl into.
pub card: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub star_count: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fork_count: Option<u64>,
/// What it publishes, in brief: none, with no releases.
#[serde(skip_serializing_if = "Option::is_none")]
pub releases: Option<super::releases::ReleasesView>,
#[serde(skip_serializing_if = "Option::is_none")]
pub viewer: Option<RepoViewerState>,
/// Whether it is private: in a space, shown only to its members.
#[serde(skip_serializing_if = "std::ops::Not::not")]
pub private: bool,
/// When its owner archived it, making it read only.
#[serde(skip_serializing_if = "Option::is_none")]
pub archived_at: Option<String>,
/// What it is about, as its record names them.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub topics: Vec<knotless::records::Topic>,
/// The first of those who may push to it besides its owner.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub collaborators: Vec<ActorView>,
/// How many may push to it besides its owner: none, absent.
#[serde(skip_serializing_if = "Option::is_none")]
pub collaborator_count: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub site: Option<SiteView>,
}
/// `dev.knotless.defs#repoViewerState`.
/// A repository's website: where it is served, and what it was deployed
/// from.
#[derive(Serialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct SiteView {
pub url: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub commit: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub check: Option<String>,
pub deployed_at: String,
}
#[derive(Serialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct RepoViewerState {
#[serde(skip_serializing_if = "Option::is_none")]
pub star: Option<String>,
/// Where the owner offered to move it, when that is to the asker.
#[serde(skip_serializing_if = "Option::is_none")]
pub transfer: Option<RepoViewBasic>,
/// The labels it defines that the asker may put on its pulls and issues.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub labels: Vec<LabelView>,
/// What the asker chose to hear of it: `all`, `releases` or `ignore`.
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription: Option<String>,
/// Whether the asker may change its settings: its owner, or an admin
/// who joined the organization that owns it.
#[serde(skip_serializing_if = "std::ops::Not::not")]
pub admin: bool,
}
/// `dev.knotless.defs#commitView`.
#[derive(Serialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct CommitView {
pub sha: String,
pub parents: Vec<CommitRefView>,
pub author: CommitAuthorView,
/// Who its message's `Co-authored-by` trailers name.
pub coauthors: Vec<CommitAuthorView>,
/// Who committed it, when that is someone other than its author.
#[serde(skip_serializing_if = "Option::is_none")]
pub committer: Option<CommitAuthorView>,
/// When its author wrote it, which a rebase or a squash keeps.
pub date: String,
/// When it was committed: what history runs in, and the pages go by.
pub committed_at: String,
/// Its message, less the line naming the pull it merged, if it did.
pub message: String,
/// The pull its message's last line names, as a squash merge records
/// it, when that is a pull on this repository.
#[serde(skip_serializing_if = "Option::is_none")]
pub pull: Option<ItemViewBasic>,
}
/// `dev.knotless.defs#commitRefView`.
#[derive(Serialize, Clone, Debug, PartialEq)]
pub struct CommitRefView {
pub sha: String,
}
/// `dev.knotless.defs#commitAuthorView`: who wrote a commit or helped to,
/// by the name git gives, and by account when that is one of the
/// repository's own people whose address it is (`knotless::emails`).
#[derive(Serialize, Clone, Debug, PartialEq)]
pub struct CommitAuthorView {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub actor: Option<ActorView>,
/// The coding agent whose address it is, when the pages know its face.
#[serde(skip_serializing_if = "Option::is_none")]
pub agent: Option<&'static str>,
}
/// `dev.knotless.defs#itemViewBasic`: a pull or an issue, by its record
/// and its title.
#[derive(Serialize, Clone, Debug, PartialEq)]
pub struct ItemViewBasic {
pub uri: String,
pub title: String,
}
/// `dev.knotless.defs#checkView`: the newest run of one workflow, as a
/// runner the repository names in its record reported it.
#[derive(Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CheckView {
pub uri: String,
/// The repository it is of, whose pages show it.
pub repo: RepoViewBasic,
pub workflow: String,
pub status: String,
pub commit: String,
pub started_at: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub finished_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
/// For a `success` that ran nothing, as the change touched none of the
/// paths its workflow names: why.
#[serde(skip_serializing_if = "Option::is_none")]
pub skipped: Option<String>,
/// The pictures it made to be looked at, in order.
pub images: Vec<CheckImageView>,
}
/// `dev.knotless.defs#checkImageView`: a picture a check made, such as
/// screenshots of the pages a change moved.
#[derive(Clone, Serialize)]
pub struct CheckImageView {
/// What it shows.
pub alt: String,
/// Where this server serves it, as a path.
pub url: String,
}
/// `dev.knotless.defs#fileDiffView`: one file of a diff, or why its rows
/// are not shown.
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FileDiffView {
pub old: String,
pub new: String,
/// `added`, `deleted`, `renamed` or `modified`.
pub status: String,
pub added: usize,
pub removed: usize,
#[serde(skip_serializing_if = "Option::is_none")]
pub note: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ranges: Option<String>,
pub rows: Vec<DiffRowView>,
/// Where its rows are left out but would be shown, how many there are,
/// and of them how many are hunk headers: the room a page keeps for
/// them until they come.
#[serde(skip_serializing_if = "Option::is_none")]
pub row_count: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub hunk_count: Option<usize>,
}
/// `dev.knotless.defs#diffRowView`: one row of a file's diff, a hunk
/// header, a note, or a line with its old and new numbers.
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DiffRowView {
/// `h`, `x`, `a`, `d`, or empty for context.
pub kind: String,
pub line: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub old: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub new: Option<u32>,
pub text: String,
}
/// `dev.knotless.defs#languageView`: one language a repository is written
/// in, its share in tenths of a percent, as a lexicon has no fractions.
#[derive(Serialize)]
pub struct LanguageView {
pub name: String,
pub color: String,
pub bytes: u64,
pub permille: u32,
}
impl From<Language> for LanguageView {
fn from(l: Language) -> LanguageView {
LanguageView {
name: l.name,
color: l.color,
bytes: l.bytes,
permille: (l.percent * 10.0).round() as u32,
}
}
}
/// `dev.knotless.repo#label`: a label, as the repository defines it.
#[derive(Serialize, Clone, Debug, PartialEq)]
pub struct LabelView {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub color: Option<String>,
#[serde(skip_serializing_if = "std::ops::Not::not")]
pub exclusive: bool,
}
/// `label` as `dev.knotless.repo#label` shows it.
pub fn label_view(l: &knotless::records::Label) -> LabelView {
LabelView {
name: l.name.clone(),
description: l.description.clone(),
color: l.color.clone(),
exclusive: l.exclusive,
}
}
/// `dev.knotless.defs#itemView`: a pull or an issue in a list of them.
#[derive(Serialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ItemView {
pub uri: String,
/// `pull` or `issue`.
pub kind: String,
pub title: String,
/// `open`, `closed` or `merged`.
pub state: String,
pub author: ActorView,
pub created_at: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_at: Option<String>,
pub comments: usize,
/// A pull its author has not marked ready.
#[serde(skip_serializing_if = "std::ops::Not::not")]
pub draft: bool,
/// Those asked to review a pull: by its author, then by the owner or
/// a collaborator, then the required reviewers its base's rule names.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub reviewers: Vec<ActorView>,
/// Of `reviewers`, those its base's rule requires: asked of every
/// pull into it, and stopped only by changing the rule.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub required_reviewers: Vec<ActorView>,
/// Those the owner or a collaborator assigns it to.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub assignees: Vec<ActorView>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub labels: Vec<LabelView>,
}
/// `item`, by its author's account, carrying the labels `record` defines.
pub async fn item_view(app: &App, record: &RepoRecord, item: &Item) -> ItemView {
let labels = item.labels.iter().filter_map(|name| record.label(name));
let labels = labels.map(label_view);
let base = item.base.as_deref().unwrap_or_default();
let required = record
.required_reviewers(base)
.filter(|r| item.reviewers.iter().any(|d| d == r));
ItemView {
uri: item.uri.clone(),
kind: item.kind.clone(),
title: item.title.clone(),
state: item.state.clone(),
author: actor(app, &item.author).await,
created_at: item.created_at.clone(),
updated_at: item.updated_at.clone(),
comments: item.comments,
draft: item.draft,
reviewers: futures::future::join_all(item.reviewers.iter().map(|r| actor(app, r))).await,
required_reviewers: futures::future::join_all(required.map(|r| actor(app, r))).await,
assignees: futures::future::join_all(item.assignees.iter().map(|a| actor(app, a))).await,
labels: labels.collect(),
}
}
/// `items`, each by `item_view`.
pub async fn item_views<'a>(
app: &App,
record: &RepoRecord,
items: impl IntoIterator<Item = &'a Item>,
) -> Vec<ItemView> {
let views = items.into_iter().map(|i| item_view(app, record, i));
futures::future::join_all(views).await
}
/// `dev.knotless.defs#commentView`: something said on a pull or an issue.
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CommentView {
/// Its record, for its author to change or take back.
pub uri: String,
pub author: ActorView,
pub created_at: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_at: Option<String>,
/// What it says, as its author wrote it, to change it from.
#[serde(skip_serializing_if = "Option::is_none")]
pub body: Option<String>,
pub html: String,
/// `approve` or `changes`, for a review.
#[serde(skip_serializing_if = "Option::is_none")]
pub verdict: Option<String>,
/// The head a review looked at, or the commit a line comment's lines
/// are in.
#[serde(skip_serializing_if = "Option::is_none")]
pub commit: Option<String>,
/// For a comment on a pull's lines, which, as they stand now.
#[serde(skip_serializing_if = "Option::is_none")]
pub line: Option<LineView>,
/// The comment starting the thread it answers.
#[serde(skip_serializing_if = "Option::is_none")]
pub reply: Option<String>,
/// The review it was sent with.
#[serde(skip_serializing_if = "Option::is_none")]
pub review: Option<String>,
/// The review it dismissed, from the owner or a collaborator.
#[serde(skip_serializing_if = "Option::is_none")]
pub dismisses: Option<String>,
/// Whether the thread it starts is resolved.
#[serde(skip_serializing_if = "std::ops::Not::not")]
pub resolved: bool,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub reactions: Vec<super::reactions::ReactionCountView>,
}
/// `dev.knotless.defs#lineView`: the lines of a pull's diff a comment is
/// on.
#[derive(Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct LineView {
pub path: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub side: Option<String>,
pub line: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub start_line: Option<u32>,
/// Whether the file on that side has changed since.
pub outdated: bool,
/// The lines as they were, and a few before one alone.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub lines: Vec<LineTextView>,
}
/// `dev.knotless.defs#lineText`: one line of a file.
#[derive(Serialize, Clone)]
pub struct LineTextView {
pub number: u32,
pub text: String,
}
/// `dev.knotless.defs#reviewView`: where one reviewer stands on a pull.
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ReviewView {
pub reviewer: ActorView,
pub verdict: String,
/// The comment that reviewed it.
pub uri: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub commit: Option<String>,
/// Whether the pull has moved past the head it looked at.
pub outdated: bool,
/// Whether the reviewer is the repository's owner or a collaborator.
pub maintainer: bool,
/// Whether the owner or a collaborator dismissed it.
#[serde(skip_serializing_if = "std::ops::Not::not")]
pub dismissed: bool,
/// Whether the rule protecting the pull's base names the reviewer as
/// a gate.
#[serde(skip_serializing_if = "std::ops::Not::not")]
pub gate: bool,
}
/// `dev.knotless.defs#pullHeadView`: the branch a pull brings in.
#[derive(Serialize)]
pub struct PullHeadView {
#[serde(skip_serializing_if = "Option::is_none")]
pub repo: Option<RepoViewBasic>,
pub branch: String,
}
/// `dev.knotless.defs#changesView`: what a pull brings in, its commits
/// oldest first.
#[derive(Serialize)]
pub struct ChangesView {
/// The repository whose commit pages show them.
pub repo: RepoViewBasic,
pub commits: Vec<CommitView>,
pub files: Vec<FileDiffView>,
/// The head an unmerged pull is at, whose checks alone it shows.
#[serde(skip_serializing_if = "Option::is_none")]
pub head: Option<String>,
}