🐸 Frogue(Fed)

~ololduck/Frogue

Raw

use actix_web::HttpResponse;
use maud::{Markup, Render, html};

use super::{
    Page,
    components::{RefSelect, RepositoryChrome, RepositoryTab},
    repositories::CommitSummary,
};

pub(super) struct CommitsBody<'a> {
    owner: &'a str,
    slug: &'a str,
    visibility: &'a str,
    default_branch: &'a str,
    reference: &'a str,
    commits: &'a [CommitSummary],
    branches: &'a [super::repositories::RefSummary],
    tags: &'a [super::repositories::RefSummary],
    patches: &'a [super::compare::PatchSummary],
    viewer: Option<&'a str>,
}

impl Render for CommitsBody<'_> {
    fn render(&self) -> Markup {
        html! {
            (RepositoryChrome {
                owner: self.owner,
                slug: self.slug,
                visibility: self.visibility,
                default_branch: self.default_branch,
                current_tab: RepositoryTab::Commits,
                is_owner: self.viewer == Some(self.owner),
            })
            p class="commit-header" {
                "Commits on "
                code { (self.reference) }
            }
            @if !self.branches.is_empty() || !self.tags.is_empty() || !self.patches.is_empty() {
                form method="get" action=(format!("/~{}/{}/commits/", self.owner, self.slug)) class="ref-form" {
                    (RefSelect {
                        name: "ref",
                        label: "History of",
                        branches: self.branches,
                        tags: self.tags,
                        patches: self.patches,
                        selected: self.reference,
                    })
                    button type="submit" { "Go" }
                }
            }
            @if self.commits.is_empty() {
                p class="empty" { "Nothing here yet." }
            } @else {
                ul class="commits" {
                    @for commit in self.commits {
                        li {
                            (CommitLine {
                                owner: self.owner,
                                slug: self.slug,
                                commit
                            })
                        }
                    }
                }
            }
        }
    }
}

pub(super) struct CommitLine<'a> {
    pub(super) owner: &'a str,
    pub(super) slug: &'a str,
    pub(super) commit: &'a CommitSummary,
}
impl Render for CommitLine<'_> {
    fn render(&self) -> Markup {
        html! {
            code class="hash" {
                a href=(format!(
                    "/~{}/{}/commit/{}",
                    self.owner, self.slug, self.commit.full_hash
                )) {
                    (self.commit.hash)
                }
            }
            code class="date" { (self.commit.date) }
            span class="author" { (self.commit.author) }
            span class="subject" { (self.commit.subject) }
            span class="stats" {
                (super::commit::commit_stats_inline(self.commit))
            }
        }
    }
}

/// The page showing the commit history of `owner`'s repository `slug` at
/// `reference`.
pub fn commits(
    viewer: Option<&str>,
    owner: &str,
    slug: &str,
    visibility: &'static str,
    default_branch: &str,
    reference: &str,
    commits: &[CommitSummary],
    branches: &[super::repositories::RefSummary],
    tags: &[super::repositories::RefSummary],
    patches: &[super::compare::PatchSummary],
) -> HttpResponse {
    Page {
        title: format!("~{owner}/{slug}: Commits on {reference} - Frogue"),
        viewer: viewer.map(str::to_string),
        extra_head: None,
        body: CommitsBody {
            owner,
            slug,
            visibility,
            default_branch,
            reference,
            commits,
            branches,
            tags,
            patches,
            viewer,
        },
    }
    .into_response()
}