2020-03-30 08:16:26 +02:00
|
|
|
use std::collections::hash_map::HashMap;
|
|
|
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use uuid::Uuid;
|
|
|
|
|
|
|
|
use jirs_data::*;
|
|
|
|
|
2020-04-10 08:09:40 +02:00
|
|
|
use crate::shared::styled_editor::Mode;
|
2020-04-08 16:14:59 +02:00
|
|
|
use crate::shared::styled_select::StyledSelectState;
|
2020-04-14 16:20:05 +02:00
|
|
|
use crate::{
|
|
|
|
AddIssueModalFieldId, EditIssueModalFieldId, FieldId, ProjectSettingsFieldId, HOST_URL,
|
|
|
|
};
|
2020-03-30 08:16:26 +02:00
|
|
|
|
2020-04-08 16:14:59 +02:00
|
|
|
#[derive(Clone, Debug, PartialOrd, PartialEq, Hash)]
|
2020-04-01 18:30:01 +02:00
|
|
|
pub enum ModalType {
|
2020-04-04 17:42:02 +02:00
|
|
|
AddIssue(AddIssueModal),
|
2020-04-02 08:45:43 +02:00
|
|
|
EditIssue(IssueId, EditIssueModal),
|
2020-04-02 23:51:29 +02:00
|
|
|
DeleteIssueConfirm(IssueId),
|
2020-04-13 10:56:42 +02:00
|
|
|
DeleteCommentConfirm(CommentId),
|
2020-04-14 08:11:35 +02:00
|
|
|
TimeTracking(IssueId),
|
2020-04-13 10:56:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialOrd, PartialEq, Hash)]
|
|
|
|
pub struct CommentForm {
|
|
|
|
pub id: Option<CommentId>,
|
|
|
|
pub body: String,
|
|
|
|
pub creating: bool,
|
2020-04-02 08:45:43 +02:00
|
|
|
}
|
|
|
|
|
2020-04-08 16:14:59 +02:00
|
|
|
#[derive(Clone, Debug, PartialOrd, PartialEq, Hash)]
|
2020-04-02 08:45:43 +02:00
|
|
|
pub struct EditIssueModal {
|
|
|
|
pub id: i32,
|
2020-04-02 16:14:07 +02:00
|
|
|
pub link_copied: bool,
|
2020-04-10 08:09:40 +02:00
|
|
|
pub payload: UpdateIssuePayload,
|
2020-04-09 16:03:11 +02:00
|
|
|
pub top_type_state: StyledSelectState,
|
|
|
|
pub status_state: StyledSelectState,
|
|
|
|
pub reporter_state: StyledSelectState,
|
|
|
|
pub assignees_state: StyledSelectState,
|
|
|
|
pub priority_state: StyledSelectState,
|
2020-04-10 08:09:40 +02:00
|
|
|
|
|
|
|
pub description_editor_mode: Mode,
|
2020-04-13 10:56:42 +02:00
|
|
|
|
|
|
|
// comments
|
|
|
|
pub comment_form: CommentForm,
|
2020-04-12 13:21:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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(),
|
2020-04-14 16:20:05 +02:00
|
|
|
list_position: issue.list_position,
|
2020-04-12 13:21:47 +02:00
|
|
|
description: issue.description.clone(),
|
|
|
|
description_text: issue.description_text.clone(),
|
2020-04-14 16:20:05 +02:00
|
|
|
estimate: issue.estimate,
|
|
|
|
time_spent: issue.time_spent,
|
|
|
|
time_remaining: issue.time_remaining,
|
|
|
|
project_id: issue.project_id,
|
|
|
|
reporter_id: issue.reporter_id,
|
2020-04-12 13:21:47 +02:00
|
|
|
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,
|
|
|
|
)),
|
2020-04-13 19:55:21 +02:00
|
|
|
description_editor_mode: Mode::View,
|
2020-04-13 10:56:42 +02:00
|
|
|
comment_form: CommentForm {
|
|
|
|
id: None,
|
|
|
|
body: String::new(),
|
|
|
|
creating: false,
|
|
|
|
},
|
2020-04-12 13:21:47 +02:00
|
|
|
}
|
|
|
|
}
|
2020-04-01 18:30:01 +02:00
|
|
|
}
|
|
|
|
|
2020-04-08 16:14:59 +02:00
|
|
|
#[derive(Clone, Debug, PartialOrd, PartialEq, Hash)]
|
2020-04-04 17:42:02 +02:00
|
|
|
pub struct AddIssueModal {
|
|
|
|
pub title: String,
|
|
|
|
pub issue_type: IssueType,
|
|
|
|
pub status: IssueStatus,
|
|
|
|
pub priority: IssuePriority,
|
|
|
|
pub description: Option<String>,
|
|
|
|
pub description_text: Option<String>,
|
|
|
|
pub estimate: Option<i32>,
|
|
|
|
pub time_spent: Option<i32>,
|
|
|
|
pub time_remaining: Option<i32>,
|
2020-04-08 20:26:28 +02:00
|
|
|
pub project_id: Option<i32>,
|
2020-04-04 17:42:02 +02:00
|
|
|
pub user_ids: Vec<i32>,
|
2020-04-08 08:58:02 +02:00
|
|
|
pub reporter_id: Option<i32>,
|
2020-04-04 17:42:02 +02:00
|
|
|
|
|
|
|
// modal fields
|
2020-04-08 16:14:59 +02:00
|
|
|
pub type_state: StyledSelectState,
|
|
|
|
pub reporter_state: StyledSelectState,
|
|
|
|
pub assignees_state: StyledSelectState,
|
|
|
|
pub priority_state: StyledSelectState,
|
|
|
|
}
|
2020-04-08 08:58:02 +02:00
|
|
|
|
2020-04-08 16:14:59 +02:00
|
|
|
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(),
|
2020-04-12 13:21:47 +02:00
|
|
|
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,
|
|
|
|
)),
|
2020-04-08 16:14:59 +02:00
|
|
|
}
|
|
|
|
}
|
2020-04-04 17:42:02 +02:00
|
|
|
}
|
|
|
|
|
2020-04-08 16:14:59 +02:00
|
|
|
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
|
2020-03-30 14:26:25 +02:00
|
|
|
pub enum Page {
|
|
|
|
Project,
|
2020-04-01 10:36:05 +02:00
|
|
|
EditIssue(IssueId),
|
2020-04-04 17:42:02 +02:00
|
|
|
AddIssue,
|
2020-03-30 14:26:25 +02:00
|
|
|
ProjectSettings,
|
|
|
|
Login,
|
|
|
|
Register,
|
|
|
|
}
|
|
|
|
|
2020-03-30 14:56:22 +02:00
|
|
|
impl Page {
|
2020-04-14 16:20:05 +02:00
|
|
|
pub fn to_path(self) -> String {
|
2020-03-30 14:56:22 +02:00
|
|
|
match self {
|
2020-04-01 10:36:05 +02:00
|
|
|
Page::Project => "/board".to_string(),
|
|
|
|
Page::EditIssue(id) => format!("/issues/{id}", id = id),
|
2020-04-14 16:20:05 +02:00
|
|
|
Page::AddIssue => "/add-issues".to_string(),
|
2020-04-01 10:36:05 +02:00
|
|
|
Page::ProjectSettings => "/project-settings".to_string(),
|
|
|
|
Page::Login => "/login".to_string(),
|
|
|
|
Page::Register => "/register".to_string(),
|
2020-03-30 14:56:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-30 14:26:25 +02:00
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
2020-03-30 08:16:26 +02:00
|
|
|
pub struct CreateCommentForm {
|
2020-03-30 14:26:25 +02:00
|
|
|
pub fields: CreateCommentPayload,
|
2020-03-30 08:16:26 +02:00
|
|
|
}
|
|
|
|
|
2020-03-30 14:26:25 +02:00
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
2020-03-30 08:16:26 +02:00
|
|
|
pub struct CreateIssueForm {
|
2020-03-30 14:26:25 +02:00
|
|
|
pub fields: CreateIssuePayload,
|
2020-03-30 08:16:26 +02:00
|
|
|
}
|
|
|
|
|
2020-03-30 14:26:25 +02:00
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
2020-03-30 08:16:26 +02:00
|
|
|
pub struct UpdateProjectForm {
|
2020-03-30 14:26:25 +02:00
|
|
|
pub id: ProjectId,
|
|
|
|
pub fields: UpdateProjectPayload,
|
2020-03-30 08:16:26 +02:00
|
|
|
}
|
|
|
|
|
2020-04-13 19:55:21 +02:00
|
|
|
#[derive(Debug, Default)]
|
2020-03-31 08:56:46 +02:00
|
|
|
pub struct ProjectPage {
|
|
|
|
pub text_filter: String,
|
2020-03-31 22:05:18 +02:00
|
|
|
pub active_avatar_filters: Vec<UserId>,
|
2020-03-31 11:11:06 +02:00
|
|
|
pub only_my_filter: bool,
|
2020-03-31 22:05:18 +02:00
|
|
|
pub recently_updated_filter: bool,
|
|
|
|
pub dragged_issue_id: Option<IssueId>,
|
2020-04-09 11:10:52 +02:00
|
|
|
pub last_drag_exchange_id: Option<IssueId>,
|
|
|
|
pub dirty_issues: Vec<IssueId>,
|
2020-03-31 08:56:46 +02:00
|
|
|
}
|
|
|
|
|
2020-04-13 19:55:21 +02:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct ProjectSettingsPage {
|
|
|
|
pub payload: UpdateProjectPayload,
|
2020-04-14 16:20:05 +02:00
|
|
|
pub project_category_state: StyledSelectState,
|
|
|
|
pub description_mode: crate::shared::styled_editor::Mode,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ProjectSettingsPage {
|
|
|
|
pub fn new(project: &Project) -> Self {
|
|
|
|
use crate::shared::styled_editor::Mode as EditorMode;
|
|
|
|
let jirs_data::Project {
|
|
|
|
id,
|
|
|
|
name,
|
|
|
|
url,
|
|
|
|
description,
|
|
|
|
category,
|
|
|
|
..
|
|
|
|
} = project;
|
|
|
|
Self {
|
|
|
|
payload: UpdateProjectPayload {
|
|
|
|
id: *id,
|
|
|
|
name: Some(name.clone()),
|
|
|
|
url: Some(url.clone()),
|
|
|
|
description: Some(description.clone()),
|
|
|
|
category: Some(category.clone()),
|
|
|
|
},
|
|
|
|
description_mode: EditorMode::View,
|
|
|
|
project_category_state: StyledSelectState::new(FieldId::ProjectSettings(
|
|
|
|
ProjectSettingsFieldId::Category,
|
|
|
|
)),
|
|
|
|
}
|
|
|
|
}
|
2020-04-13 19:55:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum PageContent {
|
|
|
|
Project(ProjectPage),
|
|
|
|
ProjectSettings(ProjectSettingsPage),
|
|
|
|
}
|
|
|
|
|
2020-04-05 15:15:09 +02:00
|
|
|
#[derive(Debug)]
|
2020-03-30 08:16:26 +02:00
|
|
|
pub struct Model {
|
2020-04-07 16:02:13 +02:00
|
|
|
pub host_url: String,
|
2020-03-30 14:26:25 +02:00
|
|
|
pub access_token: Option<Uuid>,
|
2020-04-13 19:55:21 +02:00
|
|
|
pub about_tooltip_visible: bool,
|
2020-04-07 16:02:13 +02:00
|
|
|
|
|
|
|
// mapped
|
|
|
|
pub comments_by_project_id: HashMap<ProjectId, Vec<Comment>>,
|
|
|
|
|
|
|
|
// forms
|
2020-03-30 14:26:25 +02:00
|
|
|
pub project_form: Option<UpdateProjectForm>,
|
|
|
|
pub issue_form: Option<CreateIssueForm>,
|
|
|
|
pub comment_form: Option<CreateCommentForm>,
|
2020-04-06 22:59:33 +02:00
|
|
|
|
2020-04-07 16:02:13 +02:00
|
|
|
// modals
|
|
|
|
pub modals: Vec<ModalType>,
|
|
|
|
|
|
|
|
// pages
|
2020-03-30 14:26:25 +02:00
|
|
|
pub page: Page,
|
2020-04-13 19:55:21 +02:00
|
|
|
pub page_content: PageContent,
|
2020-04-06 08:38:08 +02:00
|
|
|
|
2020-04-06 22:59:33 +02:00
|
|
|
pub project: Option<Project>,
|
|
|
|
pub user: Option<User>,
|
|
|
|
pub issues: Vec<Issue>,
|
|
|
|
pub users: Vec<User>,
|
2020-04-11 11:18:41 +02:00
|
|
|
pub comments: Vec<Comment>,
|
2020-03-30 08:16:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for Model {
|
|
|
|
fn default() -> Self {
|
2020-03-30 14:26:25 +02:00
|
|
|
let host_url = unsafe { HOST_URL.clone() };
|
2020-03-30 08:16:26 +02:00
|
|
|
Self {
|
|
|
|
access_token: None,
|
|
|
|
user: None,
|
|
|
|
issue_form: None,
|
|
|
|
project_form: None,
|
|
|
|
comment_form: None,
|
|
|
|
issues: vec![],
|
2020-04-06 22:59:33 +02:00
|
|
|
users: vec![],
|
2020-03-30 08:16:26 +02:00
|
|
|
comments_by_project_id: Default::default(),
|
2020-03-30 14:26:25 +02:00
|
|
|
page: Page::Project,
|
|
|
|
host_url,
|
2020-04-13 19:55:21 +02:00
|
|
|
page_content: PageContent::Project(ProjectPage::default()),
|
2020-04-02 19:32:40 +02:00
|
|
|
modals: vec![],
|
2020-04-06 22:59:33 +02:00
|
|
|
project: None,
|
2020-04-11 11:18:41 +02:00
|
|
|
comments: vec![],
|
2020-04-13 19:55:21 +02:00
|
|
|
about_tooltip_visible: false,
|
2020-03-30 08:16:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|