Some issue information, better look, issues count

This commit is contained in:
eraden 2021-04-29 23:21:48 +02:00
parent 8ae4cc22ba
commit a1d7e14984
4 changed files with 140 additions and 35 deletions

View File

@ -1,5 +1,8 @@
#epics {
> section {
max-width: 1024px;
margin: 0 auto;
> h1 {
font-family: var(--font-bold);
}
@ -7,7 +10,8 @@
> .description {
font-family: var(--font-regular);
margin: {
top: 5px;
top: 16px;
bottom: 16px;
}
}
@ -22,19 +26,52 @@
> li.epic {
padding: 0;
margin: {
top: 5px;
bottom: 5px;
};
display: flex;
justify-content: space-between;
margin: 5px 0 0;
> .epicName {
//
> .firstRow {
display: flex;
justify-content: space-between;
margin: {
top: 5px;
bottom: 5px;
};
> .epicName {
font-family: var(--font-black);
font-size: 16px;
}
> .date {
width: 400px;
display: flex;
justify-content: space-between;
}
> .counter {
//
}
}
> .date {
width: 250px;
> .secondRow {
margin: {
top: 5px;
bottom: 5px;
left: 20px;
right: 20px;
};
> .issues {
> .issue {
display: flex;
justify-content: space-between;
> .flags {
display: flex;
justify-content: space-between;
width: 40px;
}
}
}
}
}
}

View File

@ -1,8 +1,30 @@
#[derive(Debug)]
pub struct EpicsPage {}
use std::collections::HashMap;
use jirs_data::{EpicId, IssueId};
use crate::model::Model;
#[derive(Debug, Default)]
pub struct EpicsPage {
pub(crate) issues_per_epic: HashMap<EpicId, Vec<IssueId>>,
}
impl EpicsPage {
pub fn new() -> Self {
Self {}
pub fn new(model: &Model) -> Self {
let issues_per_epic = Self::build_issues_per_epic(model);
Self { issues_per_epic }
}
pub fn build_issues_per_epic(model: &Model) -> HashMap<EpicId, Vec<IssueId>> {
model.issues().iter().fold(HashMap::new(), |mut h, issue| {
if let Some(epic_id) = issue.epic_id.as_ref() {
h.entry(*epic_id).or_default().push(issue.id);
}
h
})
}
pub fn issues(&self, epic_id: EpicId) -> Option<&Vec<IssueId>> {
self.issues_per_epic.get(&epic_id)
}
}

View File

@ -1,6 +1,7 @@
use seed::app::Orders;
use crate::model::{Model, Page, PageContent};
use crate::pages::epics_page::EpicsPage;
use crate::ws::board_load;
use crate::{Msg, OperationKind, ResourceKind};
@ -21,10 +22,17 @@ pub fn update(msg: Msg, model: &mut crate::model::Model, orders: &mut impl Order
board_load(model, orders);
build_page_content(model);
}
Msg::ResourceChanged(ResourceKind::Issue, OperationKind::ListLoaded, ..) => {
let hash = EpicsPage::build_issues_per_epic(model);
crate::match_page_mut!(model, Epics).issues_per_epic = hash;
}
_ => (),
}
}
fn build_page_content(model: &mut Model) {
model.page_content = PageContent::Epics(Box::new(super::EpicsPage::new()));
if matches!(model.page_content, PageContent::Epics(..)) {
return;
}
model.page_content = PageContent::Epics(Box::new(super::EpicsPage::new(model)));
}

View File

@ -1,38 +1,49 @@
use chrono::NaiveDateTime;
use jirs_data::Issue;
use seed::prelude::*;
use seed::*;
use crate::components::styled_icon::{Icon, StyledIcon};
use crate::model::Model;
use crate::shared::inner_layout;
use crate::Msg;
pub fn view(model: &Model) -> Node<Msg> {
let page = crate::match_page!(model, Epics; Empty);
let epics: Vec<Node<Msg>> = model
.epics
.iter()
.map(|epic| {
let issues = page
.issues(epic.id)
.map(|v| {
v.iter()
.filter_map(|i| model.issues_by_id.get(i))
.collect::<Vec<&Issue>>()
})
.unwrap_or_default();
li![
C!["epic"],
div![C!["epicName"], &epic.name],
div![
C!["date"],
C!["firstRow"],
div![C!["epicName"], &epic.name],
div![
C!["startsAt"],
span!["Stats At:"],
span![epic
.starts_at
.as_ref()
.map(|d| format!("{}", d.format("%e %B %Y")))
.unwrap_or_default()]
C!["date"],
date_field("Starts at:", "startsAt", epic.starts_at.as_ref()),
date_field("Ends at:", "endsAt", epic.ends_at.as_ref()),
],
div![C!["counter"], "Number of issues:", issues.len()],
],
div![
C!["secondRow"],
div![
C!["endsAt"],
span!["Ends At: "],
span![epic
.ends_at
.as_ref()
.map(|d| format!("{}", d.format("%e %B %Y")))
.unwrap_or_default()]
C!["issues"],
issues
.into_iter()
.map(|issue| render_issue(issue))
.collect::<Vec<Node<Msg>>>()
]
]
]
@ -44,14 +55,41 @@ pub fn view(model: &Model) -> Node<Msg> {
"epics",
&[section![
h1!["Epics"],
p!["Epics and issues grouped in them"],
p![C!["description"], "Epics and issues grouped in them"],
ul![C!["epicsList"], epics]
]],
)
}
fn date_field(name: &str, date: Option<&NaiveDateTime>) -> Node<Msg> {
fn date_field(
name: &'static str,
class_name: &'static str,
date: Option<&NaiveDateTime>,
) -> Node<Msg> {
match date {
_ => Node::Empty,
None => Node::Empty,
Some(d) => div![
C![class_name],
span![name],
span![format!("{}", d.format("%e %B %Y"))]
],
}
}
fn render_issue(issue: &Issue) -> Node<Msg> {
div![
C!["issue"],
div![C!["name"], issue.title.as_str()],
div![
C!["flags"],
div![
C!["type"],
StyledIcon::from(Icon::from(issue.issue_type)).render()
],
div![
C!["priority"],
StyledIcon::from(Icon::from(issue.priority)).render()
],
]
]
}