Some issue information, better look, issues count
This commit is contained in:
parent
8ae4cc22ba
commit
a1d7e14984
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)));
|
||||
}
|
||||
|
@ -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()
|
||||
],
|
||||
]
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user