Add delete epic modal
This commit is contained in:
parent
915ff46281
commit
87d2ea48a3
@ -28,21 +28,21 @@ pub struct LoadProjectIssues {
|
||||
#[derive(Default, Execute)]
|
||||
#[db_exec(result = "Issue", schema = "issues")]
|
||||
pub struct UpdateIssue {
|
||||
pub issue_id: i32,
|
||||
pub issue_id: jirs_data::IssueId,
|
||||
pub title: Option<String>,
|
||||
pub issue_type: Option<IssueType>,
|
||||
pub priority: Option<IssuePriority>,
|
||||
pub list_position: Option<i32>,
|
||||
pub list_position: Option<jirs_data::ListPosition>,
|
||||
pub description: Option<String>,
|
||||
pub description_text: Option<String>,
|
||||
pub estimate: Option<i32>,
|
||||
pub time_spent: Option<i32>,
|
||||
pub time_remaining: Option<i32>,
|
||||
pub project_id: Option<i32>,
|
||||
pub user_ids: Option<Vec<i32>>,
|
||||
pub reporter_id: Option<i32>,
|
||||
pub issue_status_id: Option<i32>,
|
||||
pub epic_id: Option<Option<i32>>,
|
||||
pub project_id: Option<jirs_data::ProjectId>,
|
||||
pub user_ids: Option<Vec<jirs_data::UserId>>,
|
||||
pub reporter_id: Option<jirs_data::UserId>,
|
||||
pub issue_status_id: Option<jirs_data::IssueStatusId>,
|
||||
pub epic_id: Option<Option<jirs_data::EpicId>>,
|
||||
}
|
||||
|
||||
impl UpdateIssue {
|
||||
|
@ -1,4 +1,3 @@
|
||||
use jirs_data::{EpicId, IssueStatusId, ListPosition};
|
||||
use {
|
||||
crate::{WebSocketActor, WsHandler, WsResult},
|
||||
database_actor::{
|
||||
@ -6,7 +5,10 @@ use {
|
||||
issues::{LoadProjectIssues, UpdateIssue},
|
||||
},
|
||||
futures::executor::block_on,
|
||||
jirs_data::{CreateIssuePayload, IssueAssignee, IssueFieldId, IssueId, PayloadVariant, WsMsg},
|
||||
jirs_data::{
|
||||
CreateIssuePayload, IssueAssignee, IssueFieldId, IssueId, IssueStatusId, ListPosition,
|
||||
PayloadVariant, WsMsg,
|
||||
},
|
||||
std::collections::HashMap,
|
||||
};
|
||||
|
||||
@ -257,7 +259,7 @@ impl WsHandler<LoadIssues> for WebSocketActor {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SyncIssueListPosition(pub Vec<(IssueId, ListPosition, IssueStatusId, Option<EpicId>)>);
|
||||
pub struct SyncIssueListPosition(pub Vec<(IssueId, ListPosition, IssueStatusId, Option<IssueId>)>);
|
||||
|
||||
impl WsHandler<SyncIssueListPosition> for WebSocketActor {
|
||||
fn handle_msg(&mut self, msg: SyncIssueListPosition, ctx: &mut Self::Context) -> WsResult {
|
||||
|
@ -108,6 +108,62 @@
|
||||
&.debugModal {
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
&.deleteEpic {
|
||||
> section {
|
||||
> .header {
|
||||
background: var(--danger);
|
||||
color: var(--secondary);
|
||||
|
||||
padding: {
|
||||
top: 15px;
|
||||
right: 40px;
|
||||
left: 40px;
|
||||
bottom: 15px;
|
||||
};
|
||||
}
|
||||
|
||||
> .warning {
|
||||
margin: {
|
||||
bottom: 10px;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
padding: {
|
||||
right: 40px;
|
||||
left: 40px;
|
||||
};
|
||||
}
|
||||
|
||||
> .relatedList {
|
||||
list-style: none;
|
||||
padding: {
|
||||
right: 40px;
|
||||
left: 40px;
|
||||
bottom: 20px;
|
||||
};
|
||||
|
||||
> li {
|
||||
> .relatedIssue {
|
||||
list-style: none;
|
||||
line-height: 22px;
|
||||
font-size: 14px;
|
||||
|
||||
> a {
|
||||
color: var(--textLink);
|
||||
|
||||
.styledIcon.link {
|
||||
font-size: 14px;
|
||||
margin: {
|
||||
right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use seed::prelude::WebSocketMessage;
|
||||
|
||||
use jirs_data::{IssueId, IssueStatusId, WsMsg};
|
||||
use jirs_data::{EpicId, IssueStatusId, WsMsg};
|
||||
|
||||
use crate::shared::styled_editor::Mode as TabMode;
|
||||
use crate::FieldId;
|
||||
@ -16,10 +16,10 @@ pub enum FieldChange {
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum BoardPageChange {
|
||||
// dragging
|
||||
IssueDragStarted(IssueId),
|
||||
IssueDragStopped(IssueId),
|
||||
DragLeave(IssueId),
|
||||
ExchangePosition(IssueId),
|
||||
IssueDragStarted(EpicId),
|
||||
IssueDragStopped(EpicId),
|
||||
DragLeave(EpicId),
|
||||
ExchangePosition(EpicId),
|
||||
IssueDragOverStatus(IssueStatusId),
|
||||
IssueDropZone(IssueStatusId),
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ pub enum Msg {
|
||||
|
||||
// issues
|
||||
AddIssue,
|
||||
DeleteIssue(IssueId),
|
||||
DeleteIssue(EpicId),
|
||||
|
||||
// epics
|
||||
AddEpic,
|
||||
@ -237,7 +237,7 @@ fn update(msg: Msg, model: &mut model::Model, orders: &mut impl Orders<Msg>) {
|
||||
crate::modals::update(&msg, model, orders);
|
||||
|
||||
match model.page {
|
||||
Page::Project | Page::AddIssue | Page::EditIssue(..) => {
|
||||
Page::Project | Page::AddIssue | Page::EditIssue(..) | Page::DeleteEpic(..) => {
|
||||
pages::project_page::update(msg, model, orders)
|
||||
}
|
||||
Page::ProjectSettings => pages::project_settings_page::update(msg, model, orders),
|
||||
@ -255,8 +255,9 @@ fn update(msg: Msg, model: &mut model::Model, orders: &mut impl Orders<Msg>) {
|
||||
|
||||
fn view(model: &model::Model) -> Node<Msg> {
|
||||
match model.page {
|
||||
Page::Project | Page::AddIssue => pages::project_page::view(model),
|
||||
Page::EditIssue(_id) => pages::project_page::view(model),
|
||||
Page::Project | Page::AddIssue | Page::DeleteEpic(..) | Page::EditIssue(..) => {
|
||||
pages::project_page::view(model)
|
||||
}
|
||||
Page::ProjectSettings => pages::project_settings_page::view(model),
|
||||
Page::SignIn => pages::sign_in_page::view(model),
|
||||
Page::SignUp => pages::sign_up_page::view(model),
|
||||
@ -278,6 +279,10 @@ fn resolve_page(url: Url) -> Option<Page> {
|
||||
Some(Ok(id)) => Page::EditIssue(id),
|
||||
_ => return None,
|
||||
},
|
||||
"delete-epic" => match url.path().get(1).as_ref().map(|s| s.parse::<i32>()) {
|
||||
Some(Ok(id)) => Page::DeleteEpic(id),
|
||||
_ => return None,
|
||||
},
|
||||
"profile" => Page::Profile,
|
||||
"add-issue" => Page::AddIssue,
|
||||
"project-settings" => Page::ProjectSettings,
|
||||
|
@ -14,7 +14,7 @@ pub fn view(model: &Model) -> Node<Msg> {
|
||||
.width(1200)
|
||||
.add_class("debugModal")
|
||||
.center()
|
||||
.children(vec![code])
|
||||
.children(vec![code].into_iter())
|
||||
.build()
|
||||
.into_node()
|
||||
}
|
||||
|
5
jirs-client/src/modals/epic_delete/mod.rs
Normal file
5
jirs-client/src/modals/epic_delete/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
pub use {model::*, update::*, view::*};
|
||||
|
||||
mod model;
|
||||
mod update;
|
||||
mod view;
|
30
jirs-client/src/modals/epic_delete/model.rs
Normal file
30
jirs-client/src/modals/epic_delete/model.rs
Normal file
@ -0,0 +1,30 @@
|
||||
use {
|
||||
crate::model,
|
||||
jirs_data::{EpicId, IssueId},
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, PartialOrd, PartialEq)]
|
||||
pub struct Model {
|
||||
pub epic_id: EpicId,
|
||||
pub related_issues: Vec<IssueId>,
|
||||
}
|
||||
|
||||
impl Model {
|
||||
pub fn new(issue_id: i32, model: &mut model::Model) -> Self {
|
||||
let related_issues = model
|
||||
.issues
|
||||
.iter()
|
||||
.filter_map(|issue| {
|
||||
if issue.epic_id == Some(issue_id) {
|
||||
Some(issue.id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
Self {
|
||||
epic_id: issue_id,
|
||||
related_issues,
|
||||
}
|
||||
}
|
||||
}
|
10
jirs-client/src/modals/epic_delete/update.rs
Normal file
10
jirs-client/src/modals/epic_delete/update.rs
Normal file
@ -0,0 +1,10 @@
|
||||
use {
|
||||
crate::{shared::go_to_board, Msg},
|
||||
seed::prelude::*,
|
||||
};
|
||||
|
||||
pub fn update(msg: &Msg, _model: &mut crate::model::Model, orders: &mut impl Orders<Msg>) {
|
||||
if let Msg::ModalDropped = msg {
|
||||
go_to_board(orders);
|
||||
};
|
||||
}
|
55
jirs-client/src/modals/epic_delete/view.rs
Normal file
55
jirs-client/src/modals/epic_delete/view.rs
Normal file
@ -0,0 +1,55 @@
|
||||
use {
|
||||
crate::{
|
||||
modals::epic_delete::Model,
|
||||
model,
|
||||
shared::{styled_confirm_modal::*, styled_icon::*, styled_modal::*, ToNode},
|
||||
Msg,
|
||||
},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
|
||||
pub fn view(model: &model::Model, modal: &Model) -> Node<Msg> {
|
||||
if modal.related_issues.is_empty() {
|
||||
StyledConfirmModal::build()
|
||||
.title("Delete empty epic")
|
||||
.cancel_text("Cancel")
|
||||
.confirm_text("Delete epic")
|
||||
.build()
|
||||
.into_node()
|
||||
} else {
|
||||
StyledModal::build()
|
||||
.add_class("deleteEpic")
|
||||
.center()
|
||||
.width(600)
|
||||
.child(warning(model, modal))
|
||||
.build()
|
||||
.into_node()
|
||||
}
|
||||
}
|
||||
|
||||
fn warning(model: &model::Model, modal: &Model) -> Node<Msg> {
|
||||
let issues: Vec<Node<Msg>> = modal
|
||||
.related_issues
|
||||
.iter()
|
||||
.flat_map(|id| model.issues_by_id.get(id))
|
||||
.map(|issue| {
|
||||
let link = StyledIcon::build(Icon::Link).build().into_node();
|
||||
li![div![
|
||||
C!["relatedIssue"],
|
||||
a![
|
||||
attrs! {"href" => format!("/issues/{}", issue.id)},
|
||||
link,
|
||||
issue.title.as_str()
|
||||
]
|
||||
]]
|
||||
})
|
||||
.collect();
|
||||
section![
|
||||
h3![C!["header"], "Cannot delete epic"],
|
||||
div![
|
||||
C!["warning"],
|
||||
"This epic have related issues. Please move or delete them first."
|
||||
],
|
||||
ol![C!["relatedList"], issues]
|
||||
]
|
||||
}
|
@ -114,7 +114,7 @@ pub fn view(model: &Model, modal: &AddIssueModal) -> Node<Msg> {
|
||||
.add_class("addIssue")
|
||||
.width(0)
|
||||
.variant(crate::shared::styled_modal::Variant::Center)
|
||||
.children(vec![form])
|
||||
.child(form)
|
||||
.build()
|
||||
.into_node()
|
||||
}
|
||||
|
@ -9,13 +9,13 @@ use {
|
||||
},
|
||||
EditIssueModalSection, FieldId, Msg,
|
||||
},
|
||||
jirs_data::{Issue, IssueFieldId, IssueId, TimeTracking, UpdateIssuePayload},
|
||||
jirs_data::{EpicId, Issue, IssueFieldId, TimeTracking, UpdateIssuePayload},
|
||||
seed::prelude::*,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, PartialOrd, PartialEq)]
|
||||
pub struct Model {
|
||||
pub id: IssueId,
|
||||
pub id: EpicId,
|
||||
pub link_copied: bool,
|
||||
pub payload: UpdateIssuePayload,
|
||||
pub top_type_state: StyledSelectState,
|
||||
|
@ -2,6 +2,7 @@ pub use {epic_field::*, update::*, view::*};
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
pub mod debug;
|
||||
pub mod epic_delete;
|
||||
pub mod issue_statuses_delete;
|
||||
pub mod issues_create;
|
||||
pub mod issues_delete;
|
||||
|
@ -12,7 +12,7 @@ use {
|
||||
},
|
||||
EditIssueModalSection, FieldId, Msg,
|
||||
},
|
||||
jirs_data::{IssueFieldId, IssueId, TimeTracking},
|
||||
jirs_data::{EpicId, IssueFieldId, TimeTracking},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
|
||||
@ -25,7 +25,7 @@ pub fn value_for_time_tracking(v: &Option<i32>, time_tracking_type: &TimeTrackin
|
||||
}
|
||||
}
|
||||
|
||||
pub fn view(model: &Model, issue_id: IssueId) -> Node<Msg> {
|
||||
pub fn view(model: &Model, issue_id: EpicId) -> Node<Msg> {
|
||||
if model.issues_by_id.get(&issue_id).is_none() {
|
||||
return Node::Empty;
|
||||
}
|
||||
@ -73,12 +73,7 @@ pub fn view(model: &Model, issue_id: IssueId) -> Node<Msg> {
|
||||
|
||||
StyledModal::build()
|
||||
.add_class("timeTrackingModal")
|
||||
.children(vec![
|
||||
modal_title,
|
||||
tracking,
|
||||
inputs,
|
||||
div![C!["actions"], close],
|
||||
])
|
||||
.children(vec![modal_title, tracking, inputs, div![C!["actions"], close]].into_iter())
|
||||
.width(400)
|
||||
.build()
|
||||
.into_node()
|
||||
|
@ -43,6 +43,9 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||
Msg::ChangePage(Page::EditIssue(issue_id)) => push_edit_modal(*issue_id, model, orders),
|
||||
|
||||
Msg::ChangePage(Page::AddIssue) => push_add_modal(model, orders),
|
||||
Msg::ChangePage(Page::DeleteEpic(issue_id)) => {
|
||||
push_delete_epic_modal(*issue_id, model, orders)
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
Msg::GlobalKeyDown { key, .. } if key.eq("#") => {
|
||||
@ -61,10 +64,13 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||
_ => (),
|
||||
}
|
||||
|
||||
use crate::modals::{issue_statuses_delete, issues_create, issues_edit};
|
||||
issues_create::update(msg, model, orders);
|
||||
issues_edit::update(msg, model, orders);
|
||||
issue_statuses_delete::update(msg, model, orders);
|
||||
{
|
||||
use crate::modals::*;
|
||||
issues_create::update(msg, model, orders);
|
||||
issues_edit::update(msg, model, orders);
|
||||
issue_statuses_delete::update(msg, model, orders);
|
||||
epic_delete::update(msg, model, orders);
|
||||
}
|
||||
}
|
||||
|
||||
fn push_add_modal(model: &mut Model, _orders: &mut impl Orders<Msg>) {
|
||||
@ -75,12 +81,18 @@ fn push_add_modal(model: &mut Model, _orders: &mut impl Orders<Msg>) {
|
||||
})));
|
||||
}
|
||||
|
||||
fn push_delete_epic_modal(issue_id: i32, model: &mut Model, _orders: &mut impl Orders<Msg>) {
|
||||
use crate::modals::epic_delete::Model;
|
||||
let modal = Model::new(issue_id, model);
|
||||
model.modals.push(ModalType::DeleteEpic(Box::new(modal)));
|
||||
}
|
||||
|
||||
fn push_edit_modal(issue_id: i32, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||
let time_tracking_type = model
|
||||
.project
|
||||
.as_ref()
|
||||
.map(|p| p.time_tracking)
|
||||
.unwrap_or_else(|| TimeTracking::Untracked);
|
||||
.unwrap_or(TimeTracking::Untracked);
|
||||
let modal = {
|
||||
let issue = match model.issues_by_id.get(&issue_id) {
|
||||
Some(issue) => issue,
|
||||
|
@ -18,7 +18,7 @@ pub fn view(model: &Model) -> Node<Msg> {
|
||||
StyledModal::build()
|
||||
.variant(crate::shared::styled_modal::Variant::Center)
|
||||
.width(1040)
|
||||
.children(vec![details])
|
||||
.child(details)
|
||||
.build()
|
||||
.into_node()
|
||||
} else {
|
||||
@ -45,6 +45,7 @@ pub fn view(model: &Model) -> Node<Msg> {
|
||||
}
|
||||
#[cfg(debug_assertions)]
|
||||
ModalType::DebugModal => crate::modals::debug::view(model),
|
||||
ModalType::DeleteEpic(modal) => crate::modals::epic_delete::view(model, modal),
|
||||
})
|
||||
.collect();
|
||||
section![id!["modals"], modals]
|
||||
|
@ -27,10 +27,11 @@ pub trait IssueModal {
|
||||
#[derive(Clone, Debug, PartialOrd, PartialEq)]
|
||||
pub enum ModalType {
|
||||
AddIssue(Box<crate::modals::issues_create::Model>),
|
||||
EditIssue(IssueId, Box<crate::modals::issues_edit::Model>),
|
||||
DeleteIssueConfirm(IssueId),
|
||||
EditIssue(EpicId, Box<crate::modals::issues_edit::Model>),
|
||||
DeleteEpic(Box<crate::modals::epic_delete::Model>),
|
||||
DeleteIssueConfirm(EpicId),
|
||||
DeleteCommentConfirm(CommentId),
|
||||
TimeTracking(IssueId),
|
||||
TimeTracking(EpicId),
|
||||
DeleteIssueStatusModal(Box<crate::modals::issue_statuses_delete::Model>),
|
||||
#[cfg(debug_assertions)]
|
||||
DebugModal,
|
||||
@ -46,7 +47,8 @@ pub struct CommentForm {
|
||||
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
|
||||
pub enum Page {
|
||||
Project,
|
||||
EditIssue(IssueId),
|
||||
EditIssue(EpicId),
|
||||
DeleteEpic(EpicId),
|
||||
AddIssue,
|
||||
ProjectSettings,
|
||||
SignIn,
|
||||
@ -62,6 +64,7 @@ impl Page {
|
||||
match self {
|
||||
Page::Project => "/board".to_string(),
|
||||
Page::EditIssue(id) => format!("/issues/{id}", id = id),
|
||||
Page::DeleteEpic(id) => format!("/delete-epic/{id}", id = id),
|
||||
Page::AddIssue => "/add-issue".to_string(),
|
||||
Page::ProjectSettings => "/project-settings".to_string(),
|
||||
Page::SignIn => "/login".to_string(),
|
||||
@ -147,7 +150,7 @@ pub struct Model {
|
||||
pub current_user_project: Option<UserProject>,
|
||||
|
||||
pub issues: Vec<Issue>,
|
||||
pub issues_by_id: HashMap<IssueId, Issue>,
|
||||
pub issues_by_id: HashMap<EpicId, Issue>,
|
||||
|
||||
pub user: Option<User>,
|
||||
pub users: Vec<User>,
|
||||
|
@ -4,12 +4,12 @@ use {crate::shared::drag::DragState, jirs_data::*, std::collections::HashMap};
|
||||
pub struct StatusIssueIds {
|
||||
pub status_id: IssueStatusId,
|
||||
pub status_name: IssueStatusName,
|
||||
pub issue_ids: Vec<IssueId>,
|
||||
pub issue_ids: Vec<EpicId>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct EpicIssuePerStatus {
|
||||
pub epic_name: Option<EpicName>,
|
||||
pub epic_ref: Option<(EpicId, EpicName)>,
|
||||
pub per_status_issues: Vec<StatusIssueIds>,
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ impl ProjectPage {
|
||||
|
||||
for epic in epics {
|
||||
let mut per_epic_map = EpicIssuePerStatus {
|
||||
epic_name: epic.map(|(_, name)| name.to_string()),
|
||||
epic_ref: epic.map(|(id, name)| (id, name.to_string())),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
use crate::shared::styled_button::StyledButton;
|
||||
use {
|
||||
crate::{
|
||||
model::PageContent,
|
||||
@ -9,6 +8,8 @@ use {
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
|
||||
use crate::shared::styled_button::StyledButton;
|
||||
|
||||
pub fn project_board_lists(model: &Model) -> Node<Msg> {
|
||||
let project_page = match &model.page_content {
|
||||
PageContent::Project(project_page) => project_page,
|
||||
@ -32,8 +33,9 @@ pub fn project_board_lists(model: &Model) -> Node<Msg> {
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let epic_name = match per_epic.epic_name.as_deref() {
|
||||
Some(name) => {
|
||||
let epic_name = match per_epic.epic_ref.as_ref() {
|
||||
Some((id, name)) => {
|
||||
let id = *id;
|
||||
let edit_button = StyledButton::build()
|
||||
.empty()
|
||||
.icon(Icon::EditAlt)
|
||||
@ -42,6 +44,15 @@ pub fn project_board_lists(model: &Model) -> Node<Msg> {
|
||||
let delete_button = StyledButton::build()
|
||||
.empty()
|
||||
.icon(Icon::DeleteAlt)
|
||||
.on_click(mouse_ev("click", move |ev| {
|
||||
ev.stop_propagation();
|
||||
ev.prevent_default();
|
||||
seed::Url::new()
|
||||
.add_path_part("delete-epic")
|
||||
.add_path_part(id.to_string())
|
||||
.go_and_push();
|
||||
Msg::ChangePage(Page::DeleteEpic(id))
|
||||
}))
|
||||
.build()
|
||||
.into_node();
|
||||
|
||||
|
@ -109,15 +109,9 @@ pub fn render(values: StyledConfirmModal) -> Node<Msg> {
|
||||
|
||||
StyledModal::build()
|
||||
.width(600)
|
||||
.children(vec![
|
||||
div![attrs![At::Class => "title"], title],
|
||||
message_node,
|
||||
div![
|
||||
attrs![At::Class => "actions"],
|
||||
confirm_button,
|
||||
cancel_button
|
||||
],
|
||||
])
|
||||
.child(div![C!["title"], title])
|
||||
.child(message_node)
|
||||
.child(div![C!["actions"], confirm_button, cancel_button])
|
||||
.add_class("confirmModal")
|
||||
.build()
|
||||
.into_node()
|
||||
|
@ -58,38 +58,48 @@ pub struct StyledModalBuilder<'l> {
|
||||
}
|
||||
|
||||
impl<'l> StyledModalBuilder<'l> {
|
||||
#[inline]
|
||||
pub fn variant(mut self, variant: Variant) -> Self {
|
||||
self.variant = Some(variant);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn center(self) -> Self {
|
||||
self.variant(Variant::Center)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn width(mut self, width: usize) -> Self {
|
||||
self.width = Some(width);
|
||||
self
|
||||
}
|
||||
|
||||
// pub fn with_icon(mut self, with_icon: bool) -> Self {
|
||||
// self.with_icon = Some(with_icon);
|
||||
// self
|
||||
// }
|
||||
|
||||
pub fn children(mut self, children: Vec<Node<Msg>>) -> Self {
|
||||
self.children = Some(children);
|
||||
#[inline]
|
||||
pub fn child(mut self, child: Node<Msg>) -> Self {
|
||||
self.children.get_or_insert(vec![]).push(child);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn children<ChildIter>(mut self, children: ChildIter) -> Self
|
||||
where
|
||||
ChildIter: Iterator<Item = Node<Msg>>,
|
||||
{
|
||||
self.children.get_or_insert(vec![]).extend(children);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn add_class(mut self, name: &'l str) -> Self {
|
||||
self.class_list.push(name);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn build(self) -> StyledModal<'l> {
|
||||
StyledModal {
|
||||
variant: self.variant.unwrap_or_else(|| Variant::Center),
|
||||
variant: self.variant.unwrap_or(Variant::Center),
|
||||
width: self.width,
|
||||
with_icon: self.with_icon.unwrap_or_default(),
|
||||
children: self.children.unwrap_or_default(),
|
||||
@ -98,6 +108,7 @@ impl<'l> StyledModalBuilder<'l> {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn render(values: StyledModal) -> Node<Msg> {
|
||||
let StyledModal {
|
||||
variant,
|
||||
|
@ -8,7 +8,7 @@ use {
|
||||
seed::{prelude::Orders, *},
|
||||
};
|
||||
|
||||
pub fn drag_started(issue_id: IssueId, model: &mut Model) {
|
||||
pub fn drag_started(issue_id: EpicId, model: &mut Model) {
|
||||
let project_page = match &mut model.page_content {
|
||||
PageContent::Project(project_page) => project_page,
|
||||
_ => return,
|
||||
@ -16,7 +16,7 @@ pub fn drag_started(issue_id: IssueId, model: &mut Model) {
|
||||
project_page.issue_drag.drag(issue_id);
|
||||
}
|
||||
|
||||
pub fn exchange_position(below_id: IssueId, model: &mut Model) {
|
||||
pub fn exchange_position(below_id: EpicId, model: &mut Model) {
|
||||
let project_page = match &mut model.page_content {
|
||||
PageContent::Project(project_page) => project_page,
|
||||
_ => return,
|
||||
@ -88,7 +88,7 @@ pub fn sync(model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let changes: Vec<(IssueId, ListPosition, IssueStatusId, Option<EpicId>)> = dirty
|
||||
let changes: Vec<(EpicId, ListPosition, IssueStatusId, Option<EpicId>)> = dirty
|
||||
.into_iter()
|
||||
.filter_map(|id| {
|
||||
model.issues_by_id.get(&id).map(|issue| {
|
||||
|
@ -1,6 +1,8 @@
|
||||
#[cfg(feature = "backend")]
|
||||
use diesel::*;
|
||||
|
||||
#[cfg(feature = "backend")]
|
||||
use derive_enum_sql::EnumSql;
|
||||
use {
|
||||
chrono::NaiveDateTime,
|
||||
derive_enum_iter::EnumIter,
|
||||
@ -16,9 +18,6 @@ pub mod fields;
|
||||
pub mod msg;
|
||||
mod payloads;
|
||||
|
||||
#[cfg(feature = "backend")]
|
||||
use derive_enum_sql::EnumSql;
|
||||
|
||||
pub type NumberOfDeleted = usize;
|
||||
pub type IssueId = i32;
|
||||
pub type ListPosition = i32;
|
||||
@ -223,7 +222,7 @@ pub struct Project {
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
|
||||
pub struct Issue {
|
||||
pub id: IssueId,
|
||||
pub id: EpicId,
|
||||
pub title: String,
|
||||
pub issue_type: IssueType,
|
||||
pub priority: IssuePriority,
|
||||
@ -275,7 +274,7 @@ pub struct Comment {
|
||||
pub id: CommentId,
|
||||
pub body: String,
|
||||
pub user_id: UserId,
|
||||
pub issue_id: IssueId,
|
||||
pub issue_id: EpicId,
|
||||
pub created_at: NaiveDateTime,
|
||||
pub updated_at: NaiveDateTime,
|
||||
}
|
||||
@ -320,7 +319,7 @@ pub struct Token {
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub struct IssueAssignee {
|
||||
pub id: i32,
|
||||
pub issue_id: IssueId,
|
||||
pub issue_id: EpicId,
|
||||
pub user_id: UserId,
|
||||
pub created_at: NaiveDateTime,
|
||||
pub updated_at: NaiveDateTime,
|
||||
|
@ -1,10 +1,9 @@
|
||||
use crate::ListPosition;
|
||||
use {
|
||||
crate::{
|
||||
AvatarUrl, BindToken, Code, Comment, CommentId, CreateCommentPayload, CreateIssuePayload,
|
||||
EmailString, Epic, EpicId, HighlightedCode, Invitation, InvitationId, InvitationToken,
|
||||
Issue, IssueFieldId, IssueId, IssueStatus, IssueStatusId, Lang, Message, MessageId,
|
||||
NameString, NumberOfDeleted, PayloadVariant, Position, Project, TitleString,
|
||||
Issue, IssueFieldId, IssueId, IssueStatus, IssueStatusId, Lang, ListPosition, Message,
|
||||
MessageId, NameString, NumberOfDeleted, PayloadVariant, Position, Project, TitleString,
|
||||
UpdateCommentPayload, UpdateProjectPayload, User, UserId, UserProject, UserProjectId,
|
||||
UserRole, UsernameString,
|
||||
},
|
||||
@ -187,7 +186,7 @@ pub enum WsMsg {
|
||||
IssueDeleted(IssueId, NumberOfDeleted),
|
||||
IssueCreate(CreateIssuePayload),
|
||||
IssueCreated(Issue),
|
||||
IssueSyncListPosition(Vec<(IssueId, ListPosition, IssueStatusId, Option<EpicId>)>),
|
||||
IssueSyncListPosition(Vec<(IssueId, ListPosition, IssueStatusId, Option<IssueId>)>),
|
||||
|
||||
// issue status
|
||||
IssueStatusesLoad,
|
||||
|
Loading…
Reference in New Issue
Block a user