use std::collections::hash_map::HashMap; use serde::{Deserialize, Serialize}; use uuid::Uuid; use jirs_data::*; use crate::shared::styled_editor::Mode; use crate::shared::styled_select::StyledSelectState; use crate::{AddIssueModalFieldId, EditIssueModalFieldId, FieldId, HOST_URL}; #[derive(Clone, Debug, PartialOrd, PartialEq, Hash)] pub enum ModalType { AddIssue(AddIssueModal), EditIssue(IssueId, EditIssueModal), DeleteIssueConfirm(IssueId), DeleteCommentConfirm(CommentId), } #[derive(Clone, Debug, PartialOrd, PartialEq, Hash)] pub struct CommentForm { pub id: Option, pub body: String, pub creating: bool, } #[derive(Clone, Debug, PartialOrd, PartialEq, Hash)] pub struct EditIssueModal { pub id: i32, pub link_copied: bool, pub payload: UpdateIssuePayload, pub top_type_state: StyledSelectState, pub status_state: StyledSelectState, pub reporter_state: StyledSelectState, pub assignees_state: StyledSelectState, pub priority_state: StyledSelectState, pub description_editor_mode: Mode, // comments pub comment_form: CommentForm, } impl EditIssueModal { pub fn new(issue: &Issue) -> Self { Self { id: issue.id, link_copied: false, payload: UpdateIssuePayload { title: issue.title.clone(), issue_type: issue.issue_type.clone(), status: issue.status.clone(), priority: issue.priority.clone(), list_position: issue.list_position.clone(), description: issue.description.clone(), description_text: issue.description_text.clone(), estimate: issue.estimate.clone(), time_spent: issue.time_spent.clone(), time_remaining: issue.time_remaining.clone(), project_id: issue.project_id.clone(), reporter_id: issue.reporter_id.clone(), user_ids: issue.user_ids.clone(), }, top_type_state: StyledSelectState::new(FieldId::EditIssueModal( EditIssueModalFieldId::IssueType, )), status_state: StyledSelectState::new(FieldId::EditIssueModal( EditIssueModalFieldId::Status, )), reporter_state: StyledSelectState::new(FieldId::EditIssueModal( EditIssueModalFieldId::Reporter, )), assignees_state: StyledSelectState::new(FieldId::EditIssueModal( EditIssueModalFieldId::Assignees, )), priority_state: StyledSelectState::new(FieldId::EditIssueModal( EditIssueModalFieldId::Priority, )), description_editor_mode: Mode::View, comment_form: CommentForm { id: None, body: String::new(), creating: false, }, } } } #[derive(Clone, Debug, PartialOrd, PartialEq, Hash)] pub struct AddIssueModal { pub title: String, pub issue_type: IssueType, pub status: IssueStatus, pub priority: IssuePriority, pub description: Option, pub description_text: Option, pub estimate: Option, pub time_spent: Option, pub time_remaining: Option, pub project_id: Option, pub user_ids: Vec, pub reporter_id: Option, // modal fields pub type_state: StyledSelectState, pub reporter_state: StyledSelectState, pub assignees_state: StyledSelectState, pub priority_state: StyledSelectState, } impl Default for AddIssueModal { fn default() -> Self { Self { title: Default::default(), issue_type: Default::default(), status: Default::default(), priority: Default::default(), description: Default::default(), description_text: Default::default(), estimate: Default::default(), time_spent: Default::default(), time_remaining: Default::default(), project_id: Default::default(), user_ids: Default::default(), reporter_id: Default::default(), type_state: StyledSelectState::new(FieldId::AddIssueModal( AddIssueModalFieldId::IssueType, )), reporter_state: StyledSelectState::new(FieldId::AddIssueModal( AddIssueModalFieldId::Reporter, )), assignees_state: StyledSelectState::new(FieldId::AddIssueModal( AddIssueModalFieldId::Assignees, )), priority_state: StyledSelectState::new(FieldId::AddIssueModal( AddIssueModalFieldId::Priority, )), } } } #[derive(Copy, Clone, Debug, PartialOrd, PartialEq)] pub enum Page { Project, EditIssue(IssueId), AddIssue, ProjectSettings, Login, Register, } impl Page { pub fn to_path(&self) -> String { match self { Page::Project => "/board".to_string(), Page::EditIssue(id) => format!("/issues/{id}", id = id), Page::AddIssue => format!("/add-issues"), Page::ProjectSettings => "/project-settings".to_string(), Page::Login => "/login".to_string(), Page::Register => "/register".to_string(), } } } #[derive(Serialize, Deserialize, Debug)] pub struct CreateCommentForm { pub fields: CreateCommentPayload, } #[derive(Serialize, Deserialize, Debug)] pub struct CreateIssueForm { pub fields: CreateIssuePayload, } #[derive(Serialize, Deserialize, Debug)] pub struct UpdateProjectForm { pub id: ProjectId, pub fields: UpdateProjectPayload, } #[derive(Debug, Default)] pub struct ProjectPage { pub text_filter: String, pub active_avatar_filters: Vec, pub only_my_filter: bool, pub recently_updated_filter: bool, pub dragged_issue_id: Option, pub last_drag_exchange_id: Option, pub dirty_issues: Vec, } #[derive(Debug)] pub struct ProjectSettingsPage { pub payload: UpdateProjectPayload, pub project_type_state: StyledSelectState, } #[derive(Debug)] pub enum PageContent { Project(ProjectPage), ProjectSettings(ProjectSettingsPage), } #[derive(Debug)] pub struct Model { pub host_url: String, pub access_token: Option, pub about_tooltip_visible: bool, // mapped pub comments_by_project_id: HashMap>, // forms pub project_form: Option, pub issue_form: Option, pub comment_form: Option, // modals pub modals: Vec, // pages pub page: Page, pub page_content: PageContent, pub project: Option, pub user: Option, pub issues: Vec, pub users: Vec, pub comments: Vec, } impl Default for Model { fn default() -> Self { let host_url = unsafe { HOST_URL.clone() }; Self { access_token: None, user: None, issue_form: None, project_form: None, comment_form: None, issues: vec![], users: vec![], comments_by_project_id: Default::default(), page: Page::Project, host_url, page_content: PageContent::Project(ProjectPage::default()), modals: vec![], project: None, comments: vec![], about_tooltip_visible: false, } } }