From f778f5a5c5275e0ad68ed1baf7c7b40bfbeee426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Wo=C5=BAniak?= Date: Thu, 2 Apr 2020 16:14:07 +0200 Subject: [PATCH] Add copy link command --- jirs-client/Cargo.toml | 5 +- jirs-client/src/api.rs | 2 +- jirs-client/src/api_handlers.rs | 23 +-- jirs-client/src/model.rs | 1 + jirs-client/src/project.rs | 133 ++++++++++++++---- jirs-client/src/shared/styled_select.rs | 8 -- jirs-data/src/lib.rs | 62 ++++---- jirs-data/src/sql.rs | 44 +++++- .../2020-03-25-150001_create_uuid/down.sql | 2 + .../2020-03-25-150001_create_uuid/up.sql | 1 + .../down.sql | 1 + .../up.sql | 6 + .../down.sql | 1 + .../up.sql | 8 ++ .../down.sql | 1 + .../up.sql | 6 + .../down.sql | 1 + .../up.sql | 7 + .../down.sql | 1 + .../2020-03-25-150006_create_projects/up.sql | 10 ++ .../2020-03-25-150007_create_users/down.sql | 1 + .../2020-03-25-150007_create_users/up.sql | 9 ++ .../2020-03-25-150008_create_issues/down.sql | 1 + .../2020-03-25-150008_create_issues/up.sql | 17 +++ .../down.sql | 1 + .../2020-03-25-150009_create_comments/up.sql | 8 ++ .../2020-03-25-150010_create_tokens/down.sql | 1 + .../2020-03-25-150010_create_tokens/up.sql | 8 ++ .../2020-03-25-161803_initial/down.sql | 16 --- .../2020-03-25-161803_initial/up.sql | 77 ---------- jirs-server/src/db/issues.rs | 22 +-- jirs-server/src/errors.rs | 7 + jirs-server/src/models.rs | 10 +- jirs-server/src/routes/issues.rs | 11 +- jirs-server/src/routes/projects.rs | 4 +- jirs-server/src/schema.rs | 4 +- react-client/src/App/BaseStyles.js | 29 +++- react-client/src/App/Routes.jsx | 28 ++-- react-client/src/App/Toast/Styles.js | 6 +- react-client/src/Auth/Authenticate.jsx | 10 +- react-client/src/Auth/Styles.js | 6 +- .../src/Project/Board/Filters/Styles.js | 4 +- .../src/Project/Board/Filters/index.jsx | 28 ++-- .../src/Project/Board/Header/Styles.js | 2 +- .../src/Project/Board/Header/index.jsx | 2 +- .../IssueDetails/AssigneesReporter/Styles.js | 2 +- .../IssueDetails/AssigneesReporter/index.jsx | 18 ++- .../IssueDetails/Comments/BodyForm/Styles.js | 2 +- .../IssueDetails/Comments/BodyForm/index.jsx | 20 ++- .../IssueDetails/Comments/Comment/Styles.js | 24 ++-- .../IssueDetails/Comments/Comment/index.jsx | 33 ++--- .../Comments/Create/ProTip/Styles.js | 2 +- .../Comments/Create/ProTip/index.jsx | 14 +- .../IssueDetails/Comments/Create/Styles.js | 4 +- .../IssueDetails/Comments/Create/index.jsx | 14 +- .../Board/IssueDetails/Comments/Styles.js | 2 +- .../Board/IssueDetails/Comments/index.jsx | 30 ++-- .../Board/IssueDetails/Dates/Styles.js | 2 +- .../Board/IssueDetails/Dates/index.jsx | 12 +- .../src/Project/Board/IssueDetails/Delete.jsx | 20 ++- .../Board/IssueDetails/Description/Styles.js | 2 +- .../Board/IssueDetails/Description/index.jsx | 18 ++- .../IssueDetails/EstimateTracking/Styles.js | 2 +- .../EstimateTracking/TrackingWidget/Styles.js | 4 +- .../EstimateTracking/TrackingWidget/index.jsx | 12 +- .../IssueDetails/EstimateTracking/index.jsx | 44 +++--- .../Board/IssueDetails/Priority/Styles.js | 2 +- .../Board/IssueDetails/Priority/index.jsx | 36 +++-- .../Board/IssueDetails/Status/Styles.js | 21 ++- .../Board/IssueDetails/Status/index.jsx | 28 ++-- .../src/Project/Board/IssueDetails/Styles.js | 2 +- .../Board/IssueDetails/Title/Styles.js | 4 +- .../Board/IssueDetails/Title/index.jsx | 18 ++- .../Project/Board/IssueDetails/Type/Styles.js | 4 +- .../src/Project/Board/IssueDetails/index.jsx | 60 ++++---- .../Project/Board/Lists/List/Issue/Styles.js | 4 +- .../Project/Board/Lists/List/Issue/index.jsx | 18 ++- .../src/Project/Board/Lists/List/Styles.js | 2 +- .../src/Project/Board/Lists/List/index.jsx | 12 +- .../src/Project/Board/Lists/index.jsx | 14 +- react-client/src/Project/Board/index.jsx | 22 +-- .../src/Project/IssueCreate/Styles.js | 6 +- .../src/Project/IssueCreate/index.jsx | 22 +-- .../src/Project/IssueSearch/Styles.js | 4 +- .../src/Project/IssueSearch/index.jsx | 36 +++-- react-client/src/Project/NavbarLeft/Styles.js | 6 +- react-client/src/Project/NavbarLeft/index.jsx | 14 +- .../src/Project/ProjectSettings/Styles.js | 6 +- .../src/Project/ProjectSettings/index.jsx | 27 ++-- react-client/src/Project/Sidebar/Styles.js | 14 +- react-client/src/Project/Sidebar/index.jsx | 26 ++-- react-client/src/Project/index.jsx | 28 ++-- .../src/shared/components/CopyLinkButton.jsx | 16 +-- .../src/shared/components/Tooltip/Styles.js | 4 +- 94 files changed, 741 insertions(+), 631 deletions(-) create mode 100644 jirs-server/migrations/2020-03-25-150001_create_uuid/down.sql create mode 100644 jirs-server/migrations/2020-03-25-150001_create_uuid/up.sql create mode 100644 jirs-server/migrations/2020-03-25-150002_create__project_category_type/down.sql create mode 100644 jirs-server/migrations/2020-03-25-150002_create__project_category_type/up.sql create mode 100644 jirs-server/migrations/2020-03-25-150003_crate__issue_priority_type/down.sql create mode 100644 jirs-server/migrations/2020-03-25-150003_crate__issue_priority_type/up.sql create mode 100644 jirs-server/migrations/2020-03-25-150004_create__issue_type_type/down.sql create mode 100644 jirs-server/migrations/2020-03-25-150004_create__issue_type_type/up.sql create mode 100644 jirs-server/migrations/2020-03-25-150005_create__issue_status/down.sql create mode 100644 jirs-server/migrations/2020-03-25-150005_create__issue_status/up.sql create mode 100644 jirs-server/migrations/2020-03-25-150006_create_projects/down.sql create mode 100644 jirs-server/migrations/2020-03-25-150006_create_projects/up.sql create mode 100644 jirs-server/migrations/2020-03-25-150007_create_users/down.sql create mode 100644 jirs-server/migrations/2020-03-25-150007_create_users/up.sql create mode 100644 jirs-server/migrations/2020-03-25-150008_create_issues/down.sql create mode 100644 jirs-server/migrations/2020-03-25-150008_create_issues/up.sql create mode 100644 jirs-server/migrations/2020-03-25-150009_create_comments/down.sql create mode 100644 jirs-server/migrations/2020-03-25-150009_create_comments/up.sql create mode 100644 jirs-server/migrations/2020-03-25-150010_create_tokens/down.sql create mode 100644 jirs-server/migrations/2020-03-25-150010_create_tokens/up.sql delete mode 100644 jirs-server/migrations/2020-03-25-161803_initial/down.sql delete mode 100644 jirs-server/migrations/2020-03-25-161803_initial/up.sql diff --git a/jirs-client/Cargo.toml b/jirs-client/Cargo.toml index f75a8365..913c8661 100644 --- a/jirs-client/Cargo.toml +++ b/jirs-client/Cargo.toml @@ -31,5 +31,8 @@ features = [ "DataTransfer", "DragEvent", "HtmlDivElement", - "DomRect" + "DomRect", + "HtmlDocument", + "Document", + "Selection" ] diff --git a/jirs-client/src/api.rs b/jirs-client/src/api.rs index ff71601b..f5746f9e 100644 --- a/jirs-client/src/api.rs +++ b/jirs-client/src/api.rs @@ -30,7 +30,7 @@ pub async fn update_issue( .method(Method::Put) .header("Content-Type", "application/json") .body_json(&payload) - .fetch_json(Msg::IssueUpdateResult) + .fetch_string(Msg::IssueUpdateResult) .await } Err(e) => return Ok(Msg::InternalFailure(e)), diff --git a/jirs-client/src/api_handlers.rs b/jirs-client/src/api_handlers.rs index 2d664e4c..474a5768 100644 --- a/jirs-client/src/api_handlers.rs +++ b/jirs-client/src/api_handlers.rs @@ -1,7 +1,7 @@ use seed::fetch::{FetchObject, ResponseWithDataResult}; use seed::*; -use jirs_data::{FullProjectResponse, Issue}; +use jirs_data::{FullIssue, FullProject, Issue}; use crate::model::Model; @@ -42,9 +42,9 @@ pub fn current_project_response(fetched: &FetchObject, model: &mut Model if status.is_error() { return; } - match serde_json::from_str::<'_, FullProjectResponse>(body.as_str()) { - Ok(project_response) => { - model.project = Some(project_response.project); + match serde_json::from_str::<'_, FullProject>(body.as_str()) { + Ok(project) => { + model.project = Some(project); } _ => (), } @@ -52,8 +52,6 @@ pub fn current_project_response(fetched: &FetchObject, model: &mut Model } pub fn update_issue_response(fetched: &FetchObject, model: &mut Model) { - log!("update_issue_response"); - log!(fetched); if let FetchObject { result: Ok(ResponseWithDataResult { @@ -68,18 +66,21 @@ pub fn update_issue_response(fetched: &FetchObject, model: &mut Model) { return; } match ( - serde_json::from_str::<'_, Issue>(body.as_str()), + serde_json::from_str::<'_, FullIssue>(body.as_str()), model.project.as_mut(), ) { (Ok(issue), Some(project)) => { let mut issues: Vec = vec![]; - for i in project.issues.iter() { + std::mem::swap(&mut project.issues, &mut issues); + for i in issues.into_iter() { if i.id != issue.id { - issues.push(i.clone()); + project.issues.push(i); } } - issues.push(issue); - project.issues = issues; + project.issues.push(issue.into()); + } + (Err(error), _) => { + error!(error); } _ => (), } diff --git a/jirs-client/src/model.rs b/jirs-client/src/model.rs index 6253f572..5f411aa6 100644 --- a/jirs-client/src/model.rs +++ b/jirs-client/src/model.rs @@ -20,6 +20,7 @@ pub struct EditIssueModal { pub top_select_opened: bool, pub top_select_filter: String, pub value: IssueType, + pub link_copied: bool, } #[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialOrd, PartialEq)] diff --git a/jirs-client/src/project.rs b/jirs-client/src/project.rs index f1aca05a..2cd82101 100644 --- a/jirs-client/src/project.rs +++ b/jirs-client/src/project.rs @@ -2,6 +2,7 @@ use seed::{prelude::*, *}; use jirs_data::*; +use crate::api::update_issue; use crate::model::{EditIssueModal, Icon, ModalType, Model, Page}; use crate::shared::modal::{Modal, Variant as ModalVariant}; use crate::shared::styled_avatar::StyledAvatar; @@ -38,6 +39,7 @@ pub fn update(msg: Msg, model: &mut crate::model::Model, orders: &mut impl Order top_select_opened: false, top_select_filter: "".to_string(), value, + link_copied: false, }, )); } @@ -97,31 +99,34 @@ pub fn update(msg: Msg, model: &mut crate::model::Model, orders: &mut impl Order break; } } - if let Some(issue) = found { - issue.status = status.clone(); - issue.list_position = position + 1f64; + let issue = match found { + Some(i) => i, + _ => return, + }; - let payload = UpdateIssuePayload { - title: Some(issue.title.clone()), - issue_type: Some(issue.issue_type.clone()), - status: Some(status.to_payload().to_string()), - priority: Some(issue.priority.clone()), - list_position: Some(issue.list_position), - description: Some(issue.description.clone()), - description_text: Some(issue.description_text.clone()), - estimate: Some(issue.estimate), - time_spent: Some(issue.time_spent), - time_remaining: Some(issue.time_remaining), - project_id: Some(issue.project_id), - users: Some(vec![]), - user_ids: Some(issue.user_ids.clone()), - }; - orders.skip().perform_cmd(crate::api::update_issue( - model.host_url.clone(), - issue.id, - payload, - )); - } + issue.status = status.clone(); + issue.list_position = position + 1f64; + + let payload = UpdateIssuePayload { + title: Some(issue.title.clone()), + issue_type: Some(issue.issue_type.clone()), + status: Some(status), + priority: Some(issue.priority.clone()), + list_position: Some(issue.list_position), + description: Some(issue.description.clone()), + description_text: Some(issue.description_text.clone()), + estimate: Some(issue.estimate), + time_spent: Some(issue.time_spent), + time_remaining: Some(issue.time_remaining), + project_id: Some(issue.project_id), + user_ids: Some(issue.user_ids.clone()), + }; + model.project_page.dragged_issue_id = None; + orders.skip().perform_cmd(crate::api::update_issue( + model.host_url.clone(), + issue.id, + payload, + )); } _ => error!("Drag stopped before drop :("), } @@ -137,8 +142,46 @@ pub fn update(msg: Msg, model: &mut crate::model::Model, orders: &mut impl Order ) => { modal.top_select_opened = flag; } - (StyledSelectChange::Changed(value), Some(ModalType::EditIssue(_, modal))) => { + ( + StyledSelectChange::Changed(value), + Some(ModalType::EditIssue(issue_id, modal)), + ) => { modal.value = value.into(); + let project = match model.project.as_mut() { + Some(p) => p, + _ => return, + }; + let mut found: Option<&mut Issue> = None; + for issue in project.issues.iter_mut() { + if issue.id == *issue_id { + found = Some(issue); + break; + } + } + let issue = match found { + Some(i) => i, + _ => return, + }; + + let form = UpdateIssuePayload { + title: Some(issue.title.clone()), + issue_type: Some(modal.value.clone()), + status: Some(issue.status.clone()), + priority: Some(issue.priority.clone()), + list_position: Some(issue.list_position), + description: Some(issue.description.clone()), + description_text: Some(issue.description_text.clone()), + estimate: Some(issue.estimate.clone()), + time_spent: Some(issue.time_spent.clone()), + time_remaining: Some(issue.time_remaining.clone()), + project_id: Some(issue.project_id.clone()), + user_ids: Some(issue.user_ids.clone()), + }; + orders.skip().perform_cmd(update_issue( + model.host_url.clone(), + *issue_id, + form, + )); } _ => {} } @@ -405,10 +448,10 @@ fn project_issue(model: &Model, project: &FullProject, issue: &Issue) -> Node "issueLink"; At::Href => href], div![ attrs![At::Class => class_list.join(" "), At::Draggable => true], - drag_started, drag_stopped, p![attrs![At::Class => "title"], issue.title,], div![ @@ -492,12 +535,48 @@ fn issue_details(_model: &Model, issue: &Issue, modal: &EditIssueModal) -> Node< } .into_node(); + let click_handler = mouse_ev(Ev::Click, move |_| { + use wasm_bindgen::JsCast; + + let link = format!("http://localhost:7000/issues/{id}", id = issue_id); + let el = match seed::html_document().create_element("textarea") { + Ok(el) => el + .dyn_ref::() + .unwrap() + .clone(), + _ => return Msg::NoOp, + }; + seed::body().append_child(&el).unwrap(); + el.set_text_content(Some(link.as_str())); + el.select(); + el.set_selection_range(0, 9999).unwrap(); + seed::html_document().exec_command("copy").unwrap(); + seed::body().remove_child(&el).unwrap(); + Msg::NoOp + }); + + let copy_button = StyledButton { + variant: ButtonVariant::Empty, + icon_only: false, + disabled: false, + active: false, + text: None, + icon: Some(Icon::Link), + on_click: Some(click_handler), + children: vec![span![if modal.link_copied { + "Link Copied" + } else { + "Copy link" + }]], + } + .into_node(); + div![ attrs![At::Class => "issueDetails"], div![ attrs![At::Class => "topActions"], issue_type_select, - div![attrs![At::Class => "topActionsRight"]], + div![attrs![At::Class => "topActionsRight"], copy_button], ], div![ attrs![At::Class => "content"], diff --git a/jirs-client/src/shared/styled_select.rs b/jirs-client/src/shared/styled_select.rs index c9267d25..175c8f1c 100644 --- a/jirs-client/src/shared/styled_select.rs +++ b/jirs-client/src/shared/styled_select.rs @@ -162,14 +162,6 @@ where ] } -fn render_option( - content: Node, - on_change: EventHandler, - on_click: EventHandler, -) -> Node { - div![attrs![At::Class => "option"], on_change, on_click, content] -} - fn render_value(mut content: Node) -> Node { content.add_class("value"); content diff --git a/jirs-data/src/lib.rs b/jirs-data/src/lib.rs index d52e0be3..6560274e 100644 --- a/jirs-data/src/lib.rs +++ b/jirs-data/src/lib.rs @@ -12,12 +12,6 @@ pub use sql::*; #[cfg(feature = "backend")] pub mod sql; -pub trait ResponseData { - type Response: Serialize; - - fn into_response(self) -> Self::Response; -} - #[cfg_attr(feature = "backend", derive(FromSqlRow, AsExpression))] #[cfg_attr(feature = "backend", sql_type = "IssueTypeType")] #[derive(Clone, Deserialize, Serialize, Debug, PartialOrd, PartialEq)] @@ -69,7 +63,10 @@ impl std::fmt::Display for IssueType { } } +#[cfg_attr(feature = "backend", derive(FromSqlRow, AsExpression))] +#[cfg_attr(feature = "backend", sql_type = "IssueStatusType")] #[derive(Clone, Deserialize, Serialize, Debug, PartialOrd, PartialEq)] +#[serde(rename_all = "lowercase")] pub enum IssueStatus { Backlog, Selected, @@ -196,20 +193,6 @@ pub struct FullProject { pub users: Vec, } -#[derive(Clone, Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct FullProjectResponse { - pub project: FullProject, -} - -impl ResponseData for FullProject { - type Response = FullProjectResponse; - - fn into_response(self) -> Self::Response { - FullProjectResponse { project: self } - } -} - #[derive(Clone, Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct FullIssue { @@ -217,7 +200,7 @@ pub struct FullIssue { pub title: String, #[serde(rename = "type")] pub issue_type: IssueType, - pub status: String, + pub status: IssueStatus, pub priority: IssuePriority, pub list_position: f64, pub description: Option, @@ -234,17 +217,26 @@ pub struct FullIssue { pub comments: Vec, } -#[derive(Clone, Serialize, Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct FullIssueResponse { - pub issue: FullIssue, -} - -impl ResponseData for FullIssue { - type Response = FullIssueResponse; - - fn into_response(self) -> Self::Response { - FullIssueResponse { issue: self } +impl Into for FullIssue { + fn into(self) -> Issue { + Issue { + id: self.id, + title: self.title, + issue_type: self.issue_type, + status: self.status, + priority: self.priority, + list_position: self.list_position, + description: self.description, + description_text: self.description_text, + estimate: self.estimate, + time_spent: self.time_spent, + time_remaining: self.time_remaining, + reporter_id: self.reporter_id, + project_id: self.project_id, + created_at: self.created_at, + updated_at: self.updated_at, + user_ids: self.user_ids, + } } } @@ -325,7 +317,7 @@ pub struct UpdateIssuePayload { pub title: Option, #[serde(rename = "type")] pub issue_type: Option, - pub status: Option, + pub status: Option, pub priority: Option, pub list_position: Option, pub description: Option>, @@ -334,8 +326,6 @@ pub struct UpdateIssuePayload { pub time_spent: Option>, pub time_remaining: Option>, pub project_id: Option, - - pub users: Option>, pub user_ids: Option>, } @@ -359,7 +349,7 @@ pub struct CreateIssuePayload { pub title: String, #[serde(rename = "type")] pub issue_type: IssueType, - pub status: String, + pub status: IssueStatus, pub priority: IssuePriority, pub description: Option, pub description_text: Option, diff --git a/jirs-data/src/sql.rs b/jirs-data/src/sql.rs index 62fad0e4..0bffbd78 100644 --- a/jirs-data/src/sql.rs +++ b/jirs-data/src/sql.rs @@ -2,7 +2,7 @@ use std::io::Write; use diesel::{deserialize::*, pg::*, serialize::*, *}; -use crate::{IssuePriority, IssueType}; +use crate::{IssuePriority, IssueStatus, IssueType}; #[derive(SqlType)] #[postgres(type_name = "IssuePriorityType")] @@ -79,3 +79,45 @@ impl ToSql for IssueType { Ok(IsNull::No) } } + +#[derive(SqlType)] +#[postgres(type_name = "IssueStatusType")] +pub struct IssueStatusType; + +impl diesel::query_builder::QueryId for IssueStatusType { + type QueryId = IssueStatus; +} + +fn issue_status_from_sql(bytes: Option<&[u8]>) -> deserialize::Result { + match not_none!(bytes) { + b"backlog" => Ok(IssueStatus::Backlog), + b"selected" => Ok(IssueStatus::Selected), + b"in_progress" | b"inprogress" => Ok(IssueStatus::InProgress), + b"done" => Ok(IssueStatus::Done), + _ => Ok(IssueStatus::Backlog), + } +} + +impl FromSql for IssueStatus { + fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result { + issue_status_from_sql(bytes) + } +} + +impl FromSql for IssueStatus { + fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result { + issue_status_from_sql(bytes) + } +} + +impl ToSql for IssueStatus { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + match *self { + IssueStatus::Backlog => out.write_all(b"backlog")?, + IssueStatus::Selected => out.write_all(b"selected")?, + IssueStatus::InProgress => out.write_all(b"in_progress")?, + IssueStatus::Done => out.write_all(b"done")?, + } + Ok(IsNull::No) + } +} diff --git a/jirs-server/migrations/2020-03-25-150001_create_uuid/down.sql b/jirs-server/migrations/2020-03-25-150001_create_uuid/down.sql new file mode 100644 index 00000000..1cc1ad26 --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150001_create_uuid/down.sql @@ -0,0 +1,2 @@ +DROP EXTENSION IF EXISTS "uuid-ossp"; + diff --git a/jirs-server/migrations/2020-03-25-150001_create_uuid/up.sql b/jirs-server/migrations/2020-03-25-150001_create_uuid/up.sql new file mode 100644 index 00000000..c941cb36 --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150001_create_uuid/up.sql @@ -0,0 +1 @@ +CREATE EXTENSION "uuid-ossp"; diff --git a/jirs-server/migrations/2020-03-25-150002_create__project_category_type/down.sql b/jirs-server/migrations/2020-03-25-150002_create__project_category_type/down.sql new file mode 100644 index 00000000..d64d4a4d --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150002_create__project_category_type/down.sql @@ -0,0 +1 @@ +DROP TYPE IF EXISTS "ProjectCategoryType" CASCADE; diff --git a/jirs-server/migrations/2020-03-25-150002_create__project_category_type/up.sql b/jirs-server/migrations/2020-03-25-150002_create__project_category_type/up.sql new file mode 100644 index 00000000..de934d70 --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150002_create__project_category_type/up.sql @@ -0,0 +1,6 @@ +DROP TYPE IF EXISTS "ProjectCategoryType" CASCADE; +CREATE TYPE "ProjectCategoryType" as ENUM ( + 'software', + 'marketing', + 'business' +); diff --git a/jirs-server/migrations/2020-03-25-150003_crate__issue_priority_type/down.sql b/jirs-server/migrations/2020-03-25-150003_crate__issue_priority_type/down.sql new file mode 100644 index 00000000..91512dfb --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150003_crate__issue_priority_type/down.sql @@ -0,0 +1 @@ +DROP TYPE IF EXISTS "IssuePriorityType" CASCADE; diff --git a/jirs-server/migrations/2020-03-25-150003_crate__issue_priority_type/up.sql b/jirs-server/migrations/2020-03-25-150003_crate__issue_priority_type/up.sql new file mode 100644 index 00000000..a827e3f5 --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150003_crate__issue_priority_type/up.sql @@ -0,0 +1,8 @@ +DROP TYPE IF EXISTS "IssuePriorityType" CASCADE; +CREATE TYPE "IssuePriorityType" as ENUM ( + 'highest', + 'high', + 'medium', + 'low', + 'lowest' +); diff --git a/jirs-server/migrations/2020-03-25-150004_create__issue_type_type/down.sql b/jirs-server/migrations/2020-03-25-150004_create__issue_type_type/down.sql new file mode 100644 index 00000000..31f280ad --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150004_create__issue_type_type/down.sql @@ -0,0 +1 @@ +DROP TYPE IF EXISTS "IssueTypeType" CASCADE; diff --git a/jirs-server/migrations/2020-03-25-150004_create__issue_type_type/up.sql b/jirs-server/migrations/2020-03-25-150004_create__issue_type_type/up.sql new file mode 100644 index 00000000..f85ac852 --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150004_create__issue_type_type/up.sql @@ -0,0 +1,6 @@ +DROP TYPE IF EXISTS "IssueTypeType" CASCADE; +CREATE TYPE "IssueTypeType" AS ENUM ( + 'task', + 'bug', + 'story' +); diff --git a/jirs-server/migrations/2020-03-25-150005_create__issue_status/down.sql b/jirs-server/migrations/2020-03-25-150005_create__issue_status/down.sql new file mode 100644 index 00000000..5e4368eb --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150005_create__issue_status/down.sql @@ -0,0 +1 @@ +DROP TYPE IF EXISTS "IssueStatusType" CASCADE; diff --git a/jirs-server/migrations/2020-03-25-150005_create__issue_status/up.sql b/jirs-server/migrations/2020-03-25-150005_create__issue_status/up.sql new file mode 100644 index 00000000..a26ceeca --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150005_create__issue_status/up.sql @@ -0,0 +1,7 @@ +DROP TYPE IF EXISTS "IssueStatusType" CASCADE; +CREATE TYPE "IssueStatusType" AS ENUM ( + 'backlog', + 'selected', + 'in_progress', + 'done' +); diff --git a/jirs-server/migrations/2020-03-25-150006_create_projects/down.sql b/jirs-server/migrations/2020-03-25-150006_create_projects/down.sql new file mode 100644 index 00000000..d8ad542a --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150006_create_projects/down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS projects CASCADE; diff --git a/jirs-server/migrations/2020-03-25-150006_create_projects/up.sql b/jirs-server/migrations/2020-03-25-150006_create_projects/up.sql new file mode 100644 index 00000000..3cecf52c --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150006_create_projects/up.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS projects CASCADE; +CREATE TABLE projects ( + id serial primary key not null, + name text not null, + url text not null default '', + description text not null default '', + category text not null default 'software', + created_at timestamp not null default now(), + updated_at timestamp not null default now() +); diff --git a/jirs-server/migrations/2020-03-25-150007_create_users/down.sql b/jirs-server/migrations/2020-03-25-150007_create_users/down.sql new file mode 100644 index 00000000..12596282 --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150007_create_users/down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS users CASCADE; diff --git a/jirs-server/migrations/2020-03-25-150007_create_users/up.sql b/jirs-server/migrations/2020-03-25-150007_create_users/up.sql new file mode 100644 index 00000000..aa25e703 --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150007_create_users/up.sql @@ -0,0 +1,9 @@ +CREATE TABLE users ( + id serial primary key not null, + name text not null, + email text not null, + avatar_url text, + project_id integer not null references projects (id), + created_at timestamp not null default now(), + updated_at timestamp not null default now() +); diff --git a/jirs-server/migrations/2020-03-25-150008_create_issues/down.sql b/jirs-server/migrations/2020-03-25-150008_create_issues/down.sql new file mode 100644 index 00000000..f65e3a87 --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150008_create_issues/down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS issues CASCADE; diff --git a/jirs-server/migrations/2020-03-25-150008_create_issues/up.sql b/jirs-server/migrations/2020-03-25-150008_create_issues/up.sql new file mode 100644 index 00000000..f6b3fa4a --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150008_create_issues/up.sql @@ -0,0 +1,17 @@ +CREATE TABLE issues ( + id serial primary key not null, + title text not null, + issue_type "IssueTypeType" NOT NULL DEFAULT 'task', + status "IssueStatusType" NOT NULL DEFAULT 'backlog', + priority "IssuePriorityType" NOT NULL DEFAULT 'low', + list_position double precision not null default 0, + description text, + description_text text, + estimate integer, + time_spent integer, + time_remaining integer, + reporter_id integer not null references users (id), + project_id integer not null references projects (id), + created_at timestamp not null default now(), + updated_at timestamp not null default now() +); diff --git a/jirs-server/migrations/2020-03-25-150009_create_comments/down.sql b/jirs-server/migrations/2020-03-25-150009_create_comments/down.sql new file mode 100644 index 00000000..276415cc --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150009_create_comments/down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS comments CASCADE; diff --git a/jirs-server/migrations/2020-03-25-150009_create_comments/up.sql b/jirs-server/migrations/2020-03-25-150009_create_comments/up.sql new file mode 100644 index 00000000..ef2d3d00 --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150009_create_comments/up.sql @@ -0,0 +1,8 @@ +CREATE TABLE comments ( + id serial primary key not null, + body text not null, + user_id integer not null references users (id), + issue_id integer not null references issues (id), + created_at timestamp not null default now(), + updated_at timestamp not null default now() +); diff --git a/jirs-server/migrations/2020-03-25-150010_create_tokens/down.sql b/jirs-server/migrations/2020-03-25-150010_create_tokens/down.sql new file mode 100644 index 00000000..608aadba --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150010_create_tokens/down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS tokens CASCADE; diff --git a/jirs-server/migrations/2020-03-25-150010_create_tokens/up.sql b/jirs-server/migrations/2020-03-25-150010_create_tokens/up.sql new file mode 100644 index 00000000..5c77de74 --- /dev/null +++ b/jirs-server/migrations/2020-03-25-150010_create_tokens/up.sql @@ -0,0 +1,8 @@ +CREATE TABLE tokens ( + id serial primary key not null, + user_id integer not null references users (id), + access_token uuid not null, + refresh_token uuid not null, + created_at timestamp not null default now(), + updated_at timestamp not null default now() +); diff --git a/jirs-server/migrations/2020-03-25-161803_initial/down.sql b/jirs-server/migrations/2020-03-25-161803_initial/down.sql deleted file mode 100644 index 85935a32..00000000 --- a/jirs-server/migrations/2020-03-25-161803_initial/down.sql +++ /dev/null @@ -1,16 +0,0 @@ -DROP TYPE IF EXISTS "ProjectCategoryType" CASCADE; -DROP TYPE IF EXISTS "IssuePriorityType" CASCADE; -DROP TYPE IF EXISTS "IssueTypeType" CASCADE; - -DROP TABLE IF EXISTS projects CASCADE; - -DROP TABLE IF EXISTS users CASCADE; - -DROP TABLE IF EXISTS issues CASCADE; - -DROP TABLE IF EXISTS comments CASCADE; - -DROP TABLE IF EXISTS tokens CASCADE; - -DROP EXTENSION IF EXISTS "uuid-ossp"; - diff --git a/jirs-server/migrations/2020-03-25-161803_initial/up.sql b/jirs-server/migrations/2020-03-25-161803_initial/up.sql deleted file mode 100644 index 0117c791..00000000 --- a/jirs-server/migrations/2020-03-25-161803_initial/up.sql +++ /dev/null @@ -1,77 +0,0 @@ -CREATE EXTENSION "uuid-ossp"; - -CREATE TYPE "ProjectCategoryType" as ENUM ( - 'software', - 'marketing', - 'business' -); - -CREATE TYPE "IssuePriorityType" as ENUM ( - 'highest', - 'high', - 'medium', - 'low', - 'lowest' -); - -CREATE TYPE "IssueTypeType" AS ENUM ( - 'task', - 'bug', - 'story' -); - -CREATE TABLE projects ( - id serial primary key not null, - name text not null, - url text not null default '', - description text not null default '', - category text not null default 'software', - created_at timestamp not null default now(), - updated_at timestamp not null default now() -); - -CREATE TABLE users ( - id serial primary key not null, - name text not null, - email text not null, - avatar_url text, - project_id integer not null references projects (id), - created_at timestamp not null default now(), - updated_at timestamp not null default now() -); - -CREATE TABLE issues ( - id serial primary key not null, - title text not null, - issue_type "IssueTypeType" not null, - status text not null, - priority "IssuePriorityType" not null, - list_position double precision not null default 0, - description text, - description_text text, - estimate integer, - time_spent integer, - time_remaining integer, - reporter_id integer not null references users (id), - project_id integer not null references projects (id), - created_at timestamp not null default now(), - updated_at timestamp not null default now() -); - -CREATE TABLE comments ( - id serial primary key not null, - body text not null, - user_id integer not null references users (id), - issue_id integer not null references issues (id), - created_at timestamp not null default now(), - updated_at timestamp not null default now() -); - -CREATE TABLE tokens ( - id serial primary key not null, - user_id integer not null references users (id), - access_token uuid not null, - refresh_token uuid not null, - created_at timestamp not null default now(), - updated_at timestamp not null default now() -); diff --git a/jirs-server/src/db/issues.rs b/jirs-server/src/db/issues.rs index 28d55ef6..15c89179 100644 --- a/jirs-server/src/db/issues.rs +++ b/jirs-server/src/db/issues.rs @@ -4,12 +4,14 @@ use diesel::expression::sql_literal::sql; use diesel::prelude::*; use serde::{Deserialize, Serialize}; -use jirs_data::{IssuePriority, IssueType}; +use jirs_data::{IssuePriority, IssueStatus, IssueType}; use crate::db::DbExecutor; use crate::errors::ServiceErrors; use crate::models::Issue; +const FAILED_CONNECT_USER_AND_ISSUE: &str = "Failed to create connection between user and issue"; + #[derive(Serialize, Deserialize)] pub struct LoadIssue { pub issue_id: i32, @@ -69,7 +71,7 @@ pub struct UpdateIssue { pub issue_id: i32, pub title: Option, pub issue_type: Option, - pub status: Option, + pub status: Option, pub priority: Option, pub list_position: Option, pub description: Option>, @@ -78,8 +80,6 @@ pub struct UpdateIssue { pub time_spent: Option>, pub time_remaining: Option>, pub project_id: Option, - - pub users: Option>, pub user_ids: Option>, } @@ -121,9 +121,9 @@ impl Handler for DbExecutor { dsl::updated_at.eq(chrono::Utc::now().naive_utc()), )); diesel::debug_query::(&chain); - chain - .get_result::(conn) - .map_err(|_| ServiceErrors::DatabaseConnectionLost)?; + chain.get_result::(conn).map_err(|_| { + ServiceErrors::DatabaseQueryFailed("Failed to update issue".to_string()) + })?; if let Some(user_ids) = msg.user_ids.as_ref() { use crate::schema::issue_assignees::dsl; @@ -148,7 +148,9 @@ impl Handler for DbExecutor { diesel::insert_into(dsl::issue_assignees) .values(values) .execute(conn) - .map_err(|_| ServiceErrors::DatabaseConnectionLost)?; + .map_err(|_| { + ServiceErrors::DatabaseQueryFailed(FAILED_CONNECT_USER_AND_ISSUE.to_string()) + })?; } let row = issues @@ -194,7 +196,7 @@ impl Handler for DbExecutor { pub struct CreateIssue { pub title: String, pub issue_type: IssueType, - pub status: String, + pub status: IssueStatus, pub priority: IssuePriority, pub description: Option, pub description_text: Option, @@ -223,7 +225,7 @@ impl Handler for DbExecutor { .map_err(|_| ServiceErrors::DatabaseConnectionLost)?; let list_position = issues - .filter(status.eq("backlog")) + .filter(status.eq(IssueStatus::Backlog)) .select(sql("max(list_position) + 1.0")) .get_result::(conn) .map_err(|_| ServiceErrors::DatabaseConnectionLost)?; diff --git a/jirs-server/src/errors.rs b/jirs-server/src/errors.rs index fbaf14f1..e1a1703b 100644 --- a/jirs-server/src/errors.rs +++ b/jirs-server/src/errors.rs @@ -1,4 +1,5 @@ use actix_web::HttpResponse; + use jirs_data::ErrorResponse; const TOKEN_NOT_FOUND: &str = "Token not found"; @@ -7,6 +8,7 @@ const DATABASE_CONNECTION_FAILED: &str = "Database connection failed"; pub enum ServiceErrors { Unauthorized, DatabaseConnectionLost, + DatabaseQueryFailed(String), RecordNotFound(String), } @@ -27,6 +29,11 @@ impl Into for ServiceErrors { errors: vec![DATABASE_CONNECTION_FAILED.to_owned()], }) } + ServiceErrors::DatabaseQueryFailed(error) => { + HttpResponse::BadRequest().json(ErrorResponse { + errors: vec![error.to_owned()], + }) + } ServiceErrors::RecordNotFound(resource_name) => { HttpResponse::BadRequest().json(ErrorResponse { errors: vec![format!("Resource not found {}", resource_name)], diff --git a/jirs-server/src/models.rs b/jirs-server/src/models.rs index 371224d0..973005c8 100644 --- a/jirs-server/src/models.rs +++ b/jirs-server/src/models.rs @@ -49,7 +49,7 @@ pub struct Issue { pub title: String, #[serde(rename = "type")] pub issue_type: IssueType, - pub status: String, + pub status: IssueStatus, pub priority: IssuePriority, pub list_position: f64, pub description: Option, @@ -69,11 +69,7 @@ impl Into for Issue { id: self.id, title: self.title, issue_type: self.issue_type, - status: self - .status - .as_str() - .parse::() - .unwrap_or_else(|_| IssueStatus::Backlog), + status: self.status, priority: self.priority, list_position: self.list_position, description: self.description, @@ -123,7 +119,7 @@ pub struct CreateIssueForm { pub title: String, #[serde(rename = "type")] pub issue_type: IssueType, - pub status: String, + pub status: IssueStatus, pub priority: IssuePriority, pub list_position: f64, pub description: Option, diff --git a/jirs-server/src/routes/issues.rs b/jirs-server/src/routes/issues.rs index 0fa71ea3..bf5984b6 100644 --- a/jirs-server/src/routes/issues.rs +++ b/jirs-server/src/routes/issues.rs @@ -4,8 +4,6 @@ use actix::Addr; use actix_web::web::{Data, Json, Path}; use actix_web::{delete, get, post, put, HttpRequest, HttpResponse}; -use jirs_data::ResponseData; - use crate::db::authorize_user::AuthorizeUser; use crate::db::comments::LoadIssueComments; use crate::db::issues::{CreateIssue, DeleteIssue, LoadIssue, UpdateIssue}; @@ -44,7 +42,7 @@ pub async fn issue_with_users_and_comments( }; match load_issue(issue_id, db).await { - Ok(full_issue) => HttpResponse::Ok().json(full_issue.into_response()), + Ok(full_issue) => HttpResponse::Ok().json(full_issue), Err(e) => e.into_http_response(), } } @@ -92,13 +90,13 @@ pub async fn update( Ok(uuid) => uuid, _ => return crate::errors::ServiceErrors::Unauthorized.into_http_response(), }; - let _user = match db + match db .send(AuthorizeUser { access_token: token, }) .await { - Ok(Ok(user)) => user, + Ok(Ok(_)) => (), _ => return crate::errors::ServiceErrors::Unauthorized.into_http_response(), }; let signal = UpdateIssue { @@ -115,7 +113,6 @@ pub async fn update( time_remaining: payload.time_remaining.clone(), project_id: payload.project_id.clone(), user_ids: payload.user_ids.clone(), - users: payload.users.clone(), }; match db.send(signal).await { Ok(Ok(_)) => (), @@ -123,7 +120,7 @@ pub async fn update( _ => return ServiceErrors::DatabaseConnectionLost.into_http_response(), }; match load_issue(issue_id, db).await { - Ok(full_issue) => HttpResponse::Ok().json(full_issue.into_response()), + Ok(full_issue) => HttpResponse::Ok().json(full_issue), Err(e) => e.into_http_response(), } } diff --git a/jirs-server/src/routes/projects.rs b/jirs-server/src/routes/projects.rs index 0b759b63..60dd1350 100644 --- a/jirs-server/src/routes/projects.rs +++ b/jirs-server/src/routes/projects.rs @@ -2,8 +2,6 @@ use actix::Addr; use actix_web::web::{Data, Json, Path}; use actix_web::{get, put, HttpRequest, HttpResponse}; -use jirs_data::ResponseData; - use crate::db::authorize_user::AuthorizeUser; use crate::db::issues::LoadProjectIssues; use crate::db::projects::{LoadCurrentProject, UpdateProject}; @@ -73,7 +71,7 @@ pub async fn project_with_users_and_issues( .collect(), users: users.into_iter().map(|u| u.into()).collect(), }; - HttpResponse::Ok().json(res.into_response()) + HttpResponse::Ok().json(res) } #[put("/{id}")] diff --git a/jirs-server/src/schema.rs b/jirs-server/src/schema.rs index 418a9c58..cf59d64d 100644 --- a/jirs-server/src/schema.rs +++ b/jirs-server/src/schema.rs @@ -114,10 +114,10 @@ table! { issue_type -> IssueTypeType, /// The `status` column of the `issues` table. /// - /// Its SQL type is `Text`. + /// Its SQL type is `IssueStatusType`. /// /// (Automatically generated by Diesel.) - status -> Text, + status -> IssueStatusType, /// The `priority` column of the `issues` table. /// /// Its SQL type is `IssuePriorityType`. diff --git a/react-client/src/App/BaseStyles.js b/react-client/src/App/BaseStyles.js index 68ba99ed..614b38d4 100644 --- a/react-client/src/App/BaseStyles.js +++ b/react-client/src/App/BaseStyles.js @@ -1,6 +1,6 @@ import { createGlobalStyle } from 'styled-components'; -import { color, font, mixin } from 'shared/utils/styles'; +import { color, font } from '../shared/utils/styles'; export default createGlobalStyle` html, body, #root { @@ -89,7 +89,15 @@ export default createGlobalStyle` p { line-height: 1.4285; a { - ${mixin.link()} + cursor: pointer; + color: ${color.textLink}; + ${font.medium} + &:hover, &:visited, &:active { + color: ${color.textLink}; + } + &:hover { + text-decoration: underline; + } } } @@ -106,5 +114,20 @@ export default createGlobalStyle` touch-action: manipulation; } - ${mixin.placeholderColor(color.textLight)} + ::-webkit-input-placeholder { + color: ${color.textLight} !important; + opacity: 1 !important; + } + :-moz-placeholder { + color: ${color.textLight} !important; + opacity: 1 !important; + } + ::-moz-placeholder { + color: ${color.textLight} !important; + opacity: 1 !important; + } + :-ms-input-placeholder { + color: ${color.textLight} !important; + opacity: 1 !important; + } `; diff --git a/react-client/src/App/Routes.jsx b/react-client/src/App/Routes.jsx index 33539fad..1e70b148 100644 --- a/react-client/src/App/Routes.jsx +++ b/react-client/src/App/Routes.jsx @@ -1,20 +1,20 @@ -import React from 'react'; -import { Router, Switch, Route, Redirect } from 'react-router-dom'; +import React from 'react'; +import { Redirect, Route, Router, Switch } from 'react-router-dom'; -import history from 'browserHistory'; -import Project from 'Project'; -import Authenticate from 'Auth/Authenticate'; -import PageError from 'shared/components/PageError'; +import history from '../browserHistory'; +import Project from '../Project'; +import Authenticate from '../Auth/Authenticate'; +import PageError from '../shared/components/PageError'; const Routes = () => ( - - - - - - - - + + + + + + + + ); export default Routes; diff --git a/react-client/src/App/Toast/Styles.js b/react-client/src/App/Toast/Styles.js index 4f0a68b9..d7a6a239 100644 --- a/react-client/src/App/Toast/Styles.js +++ b/react-client/src/App/Toast/Styles.js @@ -1,7 +1,7 @@ import styled from 'styled-components'; -import { color, font, mixin, zIndexValues } from 'shared/utils/styles'; -import { Icon } from 'shared/components'; +import { color, font, mixin, zIndexValues } from '../../shared/utils/styles'; +import { Icon } from '../../shared/components'; export const Container = styled.div` z-index: ${zIndexValues.modal + 1}; @@ -21,7 +21,7 @@ export const StyledToast = styled.div` cursor: pointer; transition: all 0.15s; ${mixin.clearfix} - ${mixin.hardwareAccelerate} + transform: translateZ(0); &.jira-toast-enter, &.jira-toast-exit.jira-toast-exit-active { diff --git a/react-client/src/Auth/Authenticate.jsx b/react-client/src/Auth/Authenticate.jsx index 039f7b8b..f924bc16 100644 --- a/react-client/src/Auth/Authenticate.jsx +++ b/react-client/src/Auth/Authenticate.jsx @@ -1,9 +1,9 @@ -import React from 'react'; -import { connect } from "react-redux"; +import React from 'react'; +import { connect } from "react-redux"; import { Redirect } from 'react-router-dom'; -import * as formActions from 'actions/forms'; -import { getStoredAuthToken } from 'shared/utils/authToken'; +import * as formActions from '../actions/forms'; +import { getStoredAuthToken } from '../shared/utils/authToken'; import { ActionButton, @@ -13,7 +13,7 @@ import { Header, SignIn, SignInSection, -} from 'Project/IssueCreate/Styles'; +} from '../Project/IssueCreate/Styles'; const Authenticate = ({ onEmailChanged, diff --git a/react-client/src/Auth/Styles.js b/react-client/src/Auth/Styles.js index 6f2f7333..ac848a6b 100644 --- a/react-client/src/Auth/Styles.js +++ b/react-client/src/Auth/Styles.js @@ -1,7 +1,7 @@ import styled from 'styled-components/dist/styled-components.esm'; -import { color, font } from 'shared/utils/styles'; -import { Button, Form } from 'shared/components'; +import { color, font } from '../shared/utils/styles'; +import { Button, Form } from '../shared/components'; export const FormElement = styled(Form.Element)`; padding: 25px 40px 35px; @@ -9,7 +9,7 @@ export const FormElement = styled(Form.Element)`; export const FormHeading = styled.div` padding-bottom: 15px; - ${ font.size(21) } + ${font.size(21)} `; export const SelectItem = styled.div` diff --git a/react-client/src/Project/Board/Filters/Styles.js b/react-client/src/Project/Board/Filters/Styles.js index a75381be..67e2728f 100644 --- a/react-client/src/Project/Board/Filters/Styles.js +++ b/react-client/src/Project/Board/Filters/Styles.js @@ -1,7 +1,7 @@ import styled from 'styled-components'; -import { color, font, mixin } from 'shared/utils/styles'; -import { InputDebounced, Avatar, Button } from 'shared/components'; +import { color } from '../../../shared/utils/styles'; +import { Avatar, Button, InputDebounced } from '../../../shared/components'; export const Filters = styled.div` display: flex; diff --git a/react-client/src/Project/Board/Filters/index.jsx b/react-client/src/Project/Board/Filters/index.jsx index fc9ea9c8..25a2c0a8 100644 --- a/react-client/src/Project/Board/Filters/index.jsx +++ b/react-client/src/Project/Board/Filters/index.jsx @@ -1,23 +1,8 @@ -import React from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; -import { xor } from 'lodash'; +import { xor } from 'lodash'; -import { - Filters, - SearchInput, - Avatars, - AvatarIsActiveBorder, - StyledAvatar, - StyledButton, - ClearAll, -} from './Styles'; - -const propTypes = { - projectUsers: PropTypes.array.isRequired, - defaultFilters: PropTypes.object.isRequired, - filters: PropTypes.object.isRequired, - mergeFilters: PropTypes.func.isRequired, -}; +import { AvatarIsActiveBorder, Avatars, ClearAll, Filters, SearchInput, StyledAvatar, StyledButton, } from './Styles'; const ProjectBoardFilters = ({ projectUsers, defaultFilters, filters, mergeFilters }) => { const { searchTerm, userIds, myOnly, recent } = filters; @@ -63,6 +48,11 @@ const ProjectBoardFilters = ({ projectUsers, defaultFilters, filters, mergeFilte ); }; -ProjectBoardFilters.propTypes = propTypes; +ProjectBoardFilters.propTypes = { + projectUsers: PropTypes.array.isRequired, + defaultFilters: PropTypes.object.isRequired, + filters: PropTypes.object.isRequired, + mergeFilters: PropTypes.func.isRequired, +}; export default ProjectBoardFilters; diff --git a/react-client/src/Project/Board/Header/Styles.js b/react-client/src/Project/Board/Header/Styles.js index d35fb5ca..488d00cb 100644 --- a/react-client/src/Project/Board/Header/Styles.js +++ b/react-client/src/Project/Board/Header/Styles.js @@ -1,6 +1,6 @@ import styled from 'styled-components'; -import { font } from 'shared/utils/styles'; +import { font } from '../../../shared/utils/styles'; export const Header = styled.div` margin-top: 6px; diff --git a/react-client/src/Project/Board/Header/index.jsx b/react-client/src/Project/Board/Header/index.jsx index 231df521..b914de2d 100644 --- a/react-client/src/Project/Board/Header/index.jsx +++ b/react-client/src/Project/Board/Header/index.jsx @@ -1,6 +1,6 @@ import React from 'react'; -import { Button } from 'shared/components'; +import { Button } from '../../../shared/components'; import { BoardName, Header } from './Styles'; diff --git a/react-client/src/Project/Board/IssueDetails/AssigneesReporter/Styles.js b/react-client/src/Project/Board/IssueDetails/AssigneesReporter/Styles.js index 15b11413..cea4f5ba 100644 --- a/react-client/src/Project/Board/IssueDetails/AssigneesReporter/Styles.js +++ b/react-client/src/Project/Board/IssueDetails/AssigneesReporter/Styles.js @@ -1,6 +1,6 @@ import styled, { css } from 'styled-components'; -import { color, font, mixin } from 'shared/utils/styles'; +import { color } from '../../../../shared/utils/styles'; export const User = styled.div` display: flex; diff --git a/react-client/src/Project/Board/IssueDetails/AssigneesReporter/index.jsx b/react-client/src/Project/Board/IssueDetails/AssigneesReporter/index.jsx index 1b7d1da5..f788a914 100644 --- a/react-client/src/Project/Board/IssueDetails/AssigneesReporter/index.jsx +++ b/react-client/src/Project/Board/IssueDetails/AssigneesReporter/index.jsx @@ -1,17 +1,11 @@ import React, { Fragment } from 'react'; -import PropTypes from 'prop-types'; +import PropTypes from 'prop-types'; -import { Avatar, Select, Icon } from 'shared/components'; +import { Avatar, Icon, Select } from '../../../../shared/components'; -import { SectionTitle } from '../Styles'; +import { SectionTitle } from '../Styles'; import { User, Username } from './Styles'; -const propTypes = { - issue: PropTypes.object.isRequired, - updateIssue: PropTypes.func.isRequired, - projectUsers: PropTypes.array.isRequired, -}; - const ProjectBoardIssueDetailsAssigneesReporter = ({ issue, updateIssue, projectUsers }) => { const getUserById = userId => projectUsers.find(user => user.id === userId); @@ -66,6 +60,10 @@ const renderUser = (user, isSelectValue, removeOptionValue) => ( ); -ProjectBoardIssueDetailsAssigneesReporter.propTypes = propTypes; +ProjectBoardIssueDetailsAssigneesReporter.propTypes = { + issue: PropTypes.object.isRequired, + updateIssue: PropTypes.func.isRequired, + projectUsers: PropTypes.array.isRequired, +}; export default ProjectBoardIssueDetailsAssigneesReporter; diff --git a/react-client/src/Project/Board/IssueDetails/Comments/BodyForm/Styles.js b/react-client/src/Project/Board/IssueDetails/Comments/BodyForm/Styles.js index c25a3d62..095d5f1c 100644 --- a/react-client/src/Project/Board/IssueDetails/Comments/BodyForm/Styles.js +++ b/react-client/src/Project/Board/IssueDetails/Comments/BodyForm/Styles.js @@ -1,6 +1,6 @@ import styled from 'styled-components'; -import { Button } from 'shared/components'; +import { Button } from '../../../../../shared/components'; export const Actions = styled.div` display: flex; diff --git a/react-client/src/Project/Board/IssueDetails/Comments/BodyForm/index.jsx b/react-client/src/Project/Board/IssueDetails/Comments/BodyForm/index.jsx index 6e475fd2..54abb6b3 100644 --- a/react-client/src/Project/Board/IssueDetails/Comments/BodyForm/index.jsx +++ b/react-client/src/Project/Board/IssueDetails/Comments/BodyForm/index.jsx @@ -1,18 +1,10 @@ import React, { Fragment } from 'react'; -import PropTypes from 'prop-types'; +import PropTypes from 'prop-types'; -import { Textarea } from 'shared/components'; +import { Textarea } from '../../../../../shared/components'; import { Actions, FormButton } from './Styles'; -const propTypes = { - value: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - isWorking: PropTypes.bool.isRequired, - onSubmit: PropTypes.func.isRequired, - onCancel: PropTypes.func.isRequired, -}; - class ProjectBoardIssueDetailsCommentsBodyForm extends React.Component { state = { textArea: React.createRef() }; @@ -53,6 +45,12 @@ class ProjectBoardIssueDetailsCommentsBodyForm extends React.Component { } } -ProjectBoardIssueDetailsCommentsBodyForm.propTypes = propTypes; +ProjectBoardIssueDetailsCommentsBodyForm.propTypes = { + value: PropTypes.string.isRequired, + onChange: PropTypes.func.isRequired, + isWorking: PropTypes.bool.isRequired, + onSubmit: PropTypes.func.isRequired, + onCancel: PropTypes.func.isRequired, +}; export default ProjectBoardIssueDetailsCommentsBodyForm; diff --git a/react-client/src/Project/Board/IssueDetails/Comments/Comment/Styles.js b/react-client/src/Project/Board/IssueDetails/Comments/Comment/Styles.js index 2f64497f..9ef61242 100644 --- a/react-client/src/Project/Board/IssueDetails/Comments/Comment/Styles.js +++ b/react-client/src/Project/Board/IssueDetails/Comments/Comment/Styles.js @@ -1,7 +1,7 @@ -import styled, { css } from 'styled-components'; +import styled from 'styled-components'; -import { color, font, mixin } from 'shared/utils/styles'; -import { Avatar } from 'shared/components'; +import { color, font } from '../../../../../shared/utils/styles'; +import { Avatar } from '../../../../../shared/components'; export const Comment = styled.div` position: relative; @@ -39,7 +39,8 @@ export const Body = styled.p` white-space: pre-wrap; `; -const actionLinkStyles = css` +export const EditLink = styled.div` + margin-right: 12px; display: inline-block; padding: 2px 0; color: ${color.textMedium}; @@ -51,13 +52,16 @@ const actionLinkStyles = css` } `; -export const EditLink = styled.div` - margin-right: 12px; - ${actionLinkStyles} -`; - export const DeleteLink = styled.div` - ${actionLinkStyles} + display: inline-block; + padding: 2px 0; + color: ${color.textMedium}; + font-size: 14.5px + cursor: pointer; + user-select: none; + &:hover { + text-decoration: underline; + } &:before { position: relative; right: 6px; diff --git a/react-client/src/Project/Board/IssueDetails/Comments/Comment/index.jsx b/react-client/src/Project/Board/IssueDetails/Comments/Comment/index.jsx index c1cb46fe..bcd6f30c 100644 --- a/react-client/src/Project/Board/IssueDetails/Comments/Comment/index.jsx +++ b/react-client/src/Project/Board/IssueDetails/Comments/Comment/index.jsx @@ -1,27 +1,13 @@ import React, { Fragment, useState } from 'react'; -import PropTypes from 'prop-types'; +import PropTypes from 'prop-types'; -import api from 'shared/utils/api'; -import toast from 'shared/utils/toast'; -import { formatDateTimeConversational } from 'shared/utils/dateTime'; -import { ConfirmModal } from 'shared/components'; +import api from '../../../../../shared/utils/api'; +import toast from '../../../../../shared/utils/toast'; +import { formatDateTimeConversational } from '../../../../../shared/utils/dateTime'; +import { ConfirmModal } from '../../../../../shared/components'; -import BodyForm from '../BodyForm'; -import { - Comment, - UserAvatar, - Content, - Username, - CreatedAt, - Body, - EditLink, - DeleteLink, -} from './Styles'; - -const propTypes = { - comment: PropTypes.object.isRequired, - fetchIssue: PropTypes.func.isRequired, -}; +import BodyForm from '../BodyForm'; +import { Body, Comment, Content, CreatedAt, DeleteLink, EditLink, UserAvatar, Username, } from './Styles'; const ProjectBoardIssueDetailsComment = ({ comment, fetchIssue }) => { const [isFormOpen, setFormOpen] = useState(false); @@ -82,6 +68,9 @@ const ProjectBoardIssueDetailsComment = ({ comment, fetchIssue }) => { ); }; -ProjectBoardIssueDetailsComment.propTypes = propTypes; +ProjectBoardIssueDetailsComment.propTypes = { + comment: PropTypes.object.isRequired, + fetchIssue: PropTypes.func.isRequired, +}; export default ProjectBoardIssueDetailsComment; diff --git a/react-client/src/Project/Board/IssueDetails/Comments/Create/ProTip/Styles.js b/react-client/src/Project/Board/IssueDetails/Comments/Create/ProTip/Styles.js index b524d19f..caad2db6 100644 --- a/react-client/src/Project/Board/IssueDetails/Comments/Create/ProTip/Styles.js +++ b/react-client/src/Project/Board/IssueDetails/Comments/Create/ProTip/Styles.js @@ -1,6 +1,6 @@ import styled from 'styled-components'; -import { color } from 'shared/utils/styles'; +import { color } from '../../../../../../shared/utils/styles'; export const Tip = styled.div` display: flex; diff --git a/react-client/src/Project/Board/IssueDetails/Comments/Create/ProTip/index.jsx b/react-client/src/Project/Board/IssueDetails/Comments/Create/ProTip/index.jsx index 5ea6335b..d132b6fc 100644 --- a/react-client/src/Project/Board/IssueDetails/Comments/Create/ProTip/index.jsx +++ b/react-client/src/Project/Board/IssueDetails/Comments/Create/ProTip/index.jsx @@ -1,15 +1,11 @@ import React, { useEffect } from 'react'; -import PropTypes from 'prop-types'; +import PropTypes from 'prop-types'; -import { KeyCodes } from 'shared/constants/keyCodes'; -import { isFocusedElementEditable } from 'shared/utils/browser'; +import { KeyCodes } from '../../../../../../shared/constants/keyCodes'; +import { isFocusedElementEditable } from '../../../../../../shared/utils/browser'; import { Tip, TipLetter } from './Styles'; -const propTypes = { - setFormOpen: PropTypes.func.isRequired, -}; - const ProjectBoardIssueDetailsCommentsCreateProTip = ({ setFormOpen }) => { useEffect(() => { const handleKeyDown = event => { @@ -33,6 +29,8 @@ const ProjectBoardIssueDetailsCommentsCreateProTip = ({ setFormOpen }) => { ); }; -ProjectBoardIssueDetailsCommentsCreateProTip.propTypes = propTypes; +ProjectBoardIssueDetailsCommentsCreateProTip.propTypes = { + setFormOpen: PropTypes.func.isRequired, +}; export default ProjectBoardIssueDetailsCommentsCreateProTip; diff --git a/react-client/src/Project/Board/IssueDetails/Comments/Create/Styles.js b/react-client/src/Project/Board/IssueDetails/Comments/Create/Styles.js index 30983fad..0eaefd5d 100644 --- a/react-client/src/Project/Board/IssueDetails/Comments/Create/Styles.js +++ b/react-client/src/Project/Board/IssueDetails/Comments/Create/Styles.js @@ -1,7 +1,7 @@ import styled from 'styled-components'; -import { color, font, mixin } from 'shared/utils/styles'; -import { Avatar } from 'shared/components'; +import { color } from '../../../../../shared/utils/styles'; +import { Avatar } from '../../../../../shared/components'; export const Create = styled.div` position: relative; diff --git a/react-client/src/Project/Board/IssueDetails/Comments/Create/index.jsx b/react-client/src/Project/Board/IssueDetails/Comments/Create/index.jsx index 48d0f53e..51b66015 100644 --- a/react-client/src/Project/Board/IssueDetails/Comments/Create/index.jsx +++ b/react-client/src/Project/Board/IssueDetails/Comments/Create/index.jsx @@ -1,13 +1,13 @@ import React, { Fragment } from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; -import api from 'shared/utils/api'; -import toast from 'shared/utils/toast'; -import { fetchCurrentUser } from "actions/users"; +import api from '../../../../../shared/utils/api'; +import toast from '../../../../../shared/utils/toast'; +import { fetchCurrentUser } from "../../../../../actions/users"; -import BodyForm from '../BodyForm'; -import ProTip from './ProTip'; +import BodyForm from '../BodyForm'; +import ProTip from './ProTip'; import { Create, FakeTextarea, Right, UserAvatar } from './Styles'; class ProjectBoardIssueDetailsCommentsCreate extends React.Component { diff --git a/react-client/src/Project/Board/IssueDetails/Comments/Styles.js b/react-client/src/Project/Board/IssueDetails/Comments/Styles.js index 3c0be4db..27b05478 100644 --- a/react-client/src/Project/Board/IssueDetails/Comments/Styles.js +++ b/react-client/src/Project/Board/IssueDetails/Comments/Styles.js @@ -1,6 +1,6 @@ import styled from 'styled-components'; -import { font } from 'shared/utils/styles'; +import { font } from '../../../../shared/utils/styles'; export const Comments = styled.div` padding-top: 40px; diff --git a/react-client/src/Project/Board/IssueDetails/Comments/index.jsx b/react-client/src/Project/Board/IssueDetails/Comments/index.jsx index 9decd8c8..8142fa20 100644 --- a/react-client/src/Project/Board/IssueDetails/Comments/index.jsx +++ b/react-client/src/Project/Board/IssueDetails/Comments/index.jsx @@ -1,28 +1,26 @@ -import React from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; -import { sortByNewest } from 'shared/utils/javascript'; +import { sortByNewest } from '../../../../shared/utils/javascript'; -import Create from './Create'; -import Comment from './Comment'; +import Create from './Create'; +import Comment from './Comment'; import { Comments, Title } from './Styles'; -const propTypes = { - issue: PropTypes.object.isRequired, - fetchIssue: PropTypes.func.isRequired, -}; - const ProjectBoardIssueDetailsComments = ({ issue, fetchIssue }) => ( - - Comments - + + Comments + - {sortByNewest(issue.comments, 'createdAt').map(comment => ( - - ))} + {sortByNewest(issue.comments, 'createdAt').map(comment => ( + + ))} ); -ProjectBoardIssueDetailsComments.propTypes = propTypes; +ProjectBoardIssueDetailsComments.propTypes = { + issue: PropTypes.object.isRequired, + fetchIssue: PropTypes.func.isRequired, +}; export default ProjectBoardIssueDetailsComments; diff --git a/react-client/src/Project/Board/IssueDetails/Dates/Styles.js b/react-client/src/Project/Board/IssueDetails/Dates/Styles.js index 0338afcc..979cc3ef 100644 --- a/react-client/src/Project/Board/IssueDetails/Dates/Styles.js +++ b/react-client/src/Project/Board/IssueDetails/Dates/Styles.js @@ -1,6 +1,6 @@ import styled from 'styled-components'; -import { color, font } from 'shared/utils/styles'; +import { color } from '../../../../shared/utils/styles'; export const Dates = styled.div` margin-top: 11px; diff --git a/react-client/src/Project/Board/IssueDetails/Dates/index.jsx b/react-client/src/Project/Board/IssueDetails/Dates/index.jsx index 1e3d2d64..9a0ee9ec 100644 --- a/react-client/src/Project/Board/IssueDetails/Dates/index.jsx +++ b/react-client/src/Project/Board/IssueDetails/Dates/index.jsx @@ -1,14 +1,10 @@ -import React from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; -import { formatDateTimeConversational } from 'shared/utils/dateTime'; +import { formatDateTimeConversational } from '../../../../shared/utils/dateTime'; import { Dates } from './Styles'; -const propTypes = { - issue: PropTypes.object.isRequired, -}; - const ProjectBoardIssueDetailsDates = ({ issue }) => (
Created at {formatDateTimeConversational(issue.createdAt)}
@@ -16,6 +12,8 @@ const ProjectBoardIssueDetailsDates = ({ issue }) => (
); -ProjectBoardIssueDetailsDates.propTypes = propTypes; +ProjectBoardIssueDetailsDates.propTypes = { + issue: PropTypes.object.isRequired, +}; export default ProjectBoardIssueDetailsDates; diff --git a/react-client/src/Project/Board/IssueDetails/Delete.jsx b/react-client/src/Project/Board/IssueDetails/Delete.jsx index 96aeb732..1a202c9b 100644 --- a/react-client/src/Project/Board/IssueDetails/Delete.jsx +++ b/react-client/src/Project/Board/IssueDetails/Delete.jsx @@ -1,15 +1,9 @@ -import React from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; -import api from 'shared/utils/api'; -import toast from 'shared/utils/toast'; -import { Button, ConfirmModal } from 'shared/components'; - -const propTypes = { - issue: PropTypes.object.isRequired, - fetchProject: PropTypes.func.isRequired, - modalClose: PropTypes.func.isRequired, -}; +import api from '../../../shared/utils/api'; +import toast from '../../../shared/utils/toast'; +import { Button, ConfirmModal } from '../../../shared/components'; const ProjectBoardIssueDetailsDelete = ({ issue, fetchProject, modalClose }) => { const handleIssueDelete = async () => { @@ -35,6 +29,10 @@ const ProjectBoardIssueDetailsDelete = ({ issue, fetchProject, modalClose }) => ); }; -ProjectBoardIssueDetailsDelete.propTypes = propTypes; +ProjectBoardIssueDetailsDelete.propTypes = { + issue: PropTypes.object.isRequired, + fetchProject: PropTypes.func.isRequired, + modalClose: PropTypes.func.isRequired, +}; export default ProjectBoardIssueDetailsDelete; diff --git a/react-client/src/Project/Board/IssueDetails/Description/Styles.js b/react-client/src/Project/Board/IssueDetails/Description/Styles.js index 736d961b..36176651 100644 --- a/react-client/src/Project/Board/IssueDetails/Description/Styles.js +++ b/react-client/src/Project/Board/IssueDetails/Description/Styles.js @@ -1,6 +1,6 @@ import styled from 'styled-components'; -import { color, font, mixin } from 'shared/utils/styles'; +import { color, font } from '../../../../shared/utils/styles'; export const Title = styled.div` padding: 20px 0 6px; diff --git a/react-client/src/Project/Board/IssueDetails/Description/index.jsx b/react-client/src/Project/Board/IssueDetails/Description/index.jsx index 2340fdeb..25325c63 100644 --- a/react-client/src/Project/Board/IssueDetails/Description/index.jsx +++ b/react-client/src/Project/Board/IssueDetails/Description/index.jsx @@ -1,15 +1,10 @@ import React, { Fragment, useState } from 'react'; -import PropTypes from 'prop-types'; +import PropTypes from 'prop-types'; -import { getTextContentsFromHtmlString } from 'shared/utils/browser'; -import { TextEditor, TextEditedContent, Button } from 'shared/components'; +import { getTextContentsFromHtmlString } from '../../../../shared/utils/browser'; +import { Button, TextEditedContent, TextEditor } from '../../../../shared/components'; -import { Title, EmptyLabel, Actions } from './Styles'; - -const propTypes = { - issue: PropTypes.object.isRequired, - updateIssue: PropTypes.func.isRequired, -}; +import { Actions, EmptyLabel, Title } from './Styles'; const ProjectBoardIssueDetailsDescription = ({ issue, updateIssue }) => { const [description, setDescription] = useState(issue.description); @@ -54,6 +49,9 @@ const ProjectBoardIssueDetailsDescription = ({ issue, updateIssue }) => { ); }; -ProjectBoardIssueDetailsDescription.propTypes = propTypes; +ProjectBoardIssueDetailsDescription.propTypes = { + issue: PropTypes.object.isRequired, + updateIssue: PropTypes.func.isRequired, +}; export default ProjectBoardIssueDetailsDescription; diff --git a/react-client/src/Project/Board/IssueDetails/EstimateTracking/Styles.js b/react-client/src/Project/Board/IssueDetails/EstimateTracking/Styles.js index 970f88b6..d7a0e45d 100644 --- a/react-client/src/Project/Board/IssueDetails/EstimateTracking/Styles.js +++ b/react-client/src/Project/Board/IssueDetails/EstimateTracking/Styles.js @@ -1,6 +1,6 @@ import styled from 'styled-components'; -import { color, font, mixin } from 'shared/utils/styles'; +import { color, font } from '../../../../shared/utils/styles'; export const TrackingLink = styled.div` padding: 4px 4px 2px 0; diff --git a/react-client/src/Project/Board/IssueDetails/EstimateTracking/TrackingWidget/Styles.js b/react-client/src/Project/Board/IssueDetails/EstimateTracking/TrackingWidget/Styles.js index a70fcc6d..ec8efc95 100644 --- a/react-client/src/Project/Board/IssueDetails/EstimateTracking/TrackingWidget/Styles.js +++ b/react-client/src/Project/Board/IssueDetails/EstimateTracking/TrackingWidget/Styles.js @@ -1,7 +1,7 @@ import styled from 'styled-components'; -import { color, font } from 'shared/utils/styles'; -import { Icon } from 'shared/components'; +import { color } from '../../../../../shared/utils/styles'; +import { Icon } from '../../../../../shared/components'; export const TrackingWidget = styled.div` display: flex; diff --git a/react-client/src/Project/Board/IssueDetails/EstimateTracking/TrackingWidget/index.jsx b/react-client/src/Project/Board/IssueDetails/EstimateTracking/TrackingWidget/index.jsx index 2142106b..ee3bf0f6 100644 --- a/react-client/src/Project/Board/IssueDetails/EstimateTracking/TrackingWidget/index.jsx +++ b/react-client/src/Project/Board/IssueDetails/EstimateTracking/TrackingWidget/index.jsx @@ -1,12 +1,8 @@ -import React from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; import { isNil } from 'lodash'; -import { TrackingWidget, WatchIcon, Right, BarCont, Bar, Values } from './Styles'; - -const propTypes = { - issue: PropTypes.object.isRequired, -}; +import { Bar, BarCont, Right, TrackingWidget, Values, WatchIcon } from './Styles'; const ProjectBoardIssueDetailsTrackingWidget = ({ issue }) => ( @@ -50,6 +46,8 @@ const renderRemainingOrEstimate = ({ timeRemaining, estimate }) => { } }; -ProjectBoardIssueDetailsTrackingWidget.propTypes = propTypes; +ProjectBoardIssueDetailsTrackingWidget.propTypes = { + issue: PropTypes.object.isRequired, +}; export default ProjectBoardIssueDetailsTrackingWidget; diff --git a/react-client/src/Project/Board/IssueDetails/EstimateTracking/index.jsx b/react-client/src/Project/Board/IssueDetails/EstimateTracking/index.jsx index cc03e676..ba169af4 100644 --- a/react-client/src/Project/Board/IssueDetails/EstimateTracking/index.jsx +++ b/react-client/src/Project/Board/IssueDetails/EstimateTracking/index.jsx @@ -1,35 +1,22 @@ import React, { Fragment } from 'react'; -import PropTypes from 'prop-types'; -import { isNil } from 'lodash'; +import PropTypes from 'prop-types'; +import { isNil } from 'lodash'; -import { InputDebounced, Modal, Button } from 'shared/components'; +import { Button, InputDebounced, Modal } from '../../../../shared/components'; -import TrackingWidget from './TrackingWidget'; -import { SectionTitle } from '../Styles'; -import { - TrackingLink, - ModalContents, - ModalTitle, - Inputs, - InputCont, - InputLabel, - Actions, -} from './Styles'; - -const propTypes = { - issue: PropTypes.object.isRequired, - updateIssue: PropTypes.func.isRequired, -}; +import TrackingWidget from './TrackingWidget'; +import { SectionTitle } from '../Styles'; +import { Actions, InputCont, InputLabel, Inputs, ModalContents, ModalTitle, TrackingLink, } from './Styles'; const ProjectBoardIssueDetailsEstimateTracking = ({ issue, updateIssue }) => ( - - Original Estimate (hours) - {renderHourInput('estimate', issue, updateIssue)} + + Original Estimate (hours) + {renderHourInput('estimate', issue, updateIssue)} - Time Tracking - Time Tracking + ( @@ -72,6 +59,9 @@ const renderHourInput = (fieldName, issue, updateIssue) => ( /> ); -ProjectBoardIssueDetailsEstimateTracking.propTypes = propTypes; +ProjectBoardIssueDetailsEstimateTracking.propTypes = { + issue: PropTypes.object.isRequired, + updateIssue: PropTypes.func.isRequired, +}; export default ProjectBoardIssueDetailsEstimateTracking; diff --git a/react-client/src/Project/Board/IssueDetails/Priority/Styles.js b/react-client/src/Project/Board/IssueDetails/Priority/Styles.js index 61bbe039..d7aa0768 100644 --- a/react-client/src/Project/Board/IssueDetails/Priority/Styles.js +++ b/react-client/src/Project/Board/IssueDetails/Priority/Styles.js @@ -1,6 +1,6 @@ import styled, { css } from 'styled-components'; -import { color, font } from 'shared/utils/styles'; +import { color } from '../../../../shared/utils/styles'; export const Priority = styled.div` display: flex; diff --git a/react-client/src/Project/Board/IssueDetails/Priority/index.jsx b/react-client/src/Project/Board/IssueDetails/Priority/index.jsx index 1f033619..2a754657 100644 --- a/react-client/src/Project/Board/IssueDetails/Priority/index.jsx +++ b/react-client/src/Project/Board/IssueDetails/Priority/index.jsx @@ -1,26 +1,21 @@ import React, { Fragment } from 'react'; -import PropTypes from 'prop-types'; +import PropTypes from 'prop-types'; -import { IssuePriority, IssuePriorityCopy } from 'shared/constants/issues'; -import { Select, IssuePriorityIcon } from 'shared/components'; +import { IssuePriority, IssuePriorityCopy } from '../../../../shared/constants/issues'; +import { IssuePriorityIcon, Select } from '../../../../shared/components'; -import { SectionTitle } from '../Styles'; -import { Priority, Label } from './Styles'; - -const propTypes = { - issue: PropTypes.object.isRequired, - updateIssue: PropTypes.func.isRequired, -}; +import { SectionTitle } from '../Styles'; +import { Label, Priority } from './Styles'; const ProjectBoardIssueDetailsPriority = ({ issue, updateIssue }) => ( - - Priority - ({ value: priority, label: IssuePriorityCopy[priority], @@ -39,6 +34,9 @@ const renderPriorityItem = (priority, isValue) => ( ); -ProjectBoardIssueDetailsPriority.propTypes = propTypes; +ProjectBoardIssueDetailsPriority.propTypes = { + issue: PropTypes.object.isRequired, + updateIssue: PropTypes.func.isRequired, +}; export default ProjectBoardIssueDetailsPriority; diff --git a/react-client/src/Project/Board/IssueDetails/Status/Styles.js b/react-client/src/Project/Board/IssueDetails/Status/Styles.js index 2cffb302..a340f157 100644 --- a/react-client/src/Project/Board/IssueDetails/Status/Styles.js +++ b/react-client/src/Project/Board/IssueDetails/Status/Styles.js @@ -1,11 +1,28 @@ import styled, { css } from 'styled-components'; -import { issueStatusColors, issueStatusBackgroundColors, mixin } from 'shared/utils/styles'; +import { issueStatusBackgroundColors, issueStatusColors } from '../../../../shared/utils/styles'; export const Status = styled.div` text-transform: uppercase; transition: all 0.1s; - ${props => mixin.tag(issueStatusBackgroundColors[props.color], issueStatusColors[props.color])} + ${props => + css` + display: inline-flex; + align-items: center; + height: 24px; + padding: 0 8px; + border-radius: 4px; + cursor: pointer; + user-select: none; + color: ${issueStatusColors[props.color]}; + background: ${issueStatusBackgroundColors[props.color]}; + font-family: "CircularStdBold"; font-weight: normal + font-size: 12px + i { + margin-left: 4px; + } + ` +} ${props => props.isValue && css` diff --git a/react-client/src/Project/Board/IssueDetails/Status/index.jsx b/react-client/src/Project/Board/IssueDetails/Status/index.jsx index 177d7e35..a5aa1282 100644 --- a/react-client/src/Project/Board/IssueDetails/Status/index.jsx +++ b/react-client/src/Project/Board/IssueDetails/Status/index.jsx @@ -1,23 +1,18 @@ import React, { Fragment } from 'react'; -import PropTypes from 'prop-types'; +import PropTypes from 'prop-types'; -import { IssueStatus, IssueStatusCopy } from 'shared/constants/issues'; -import { Select, Icon } from 'shared/components'; +import { IssueStatus, IssueStatusCopy } from '../../../../shared/constants/issues'; +import { Icon, Select } from '../../../../shared/components'; import { SectionTitle } from '../Styles'; -import { Status } from './Styles'; - -const propTypes = { - issue: PropTypes.object.isRequired, - updateIssue: PropTypes.func.isRequired, -}; +import { Status } from './Styles'; const ProjectBoardIssueDetailsStatus = ({ issue, updateIssue }) => ( - - Status - ( ); -ProjectBoardIssueDetailsStatus.propTypes = propTypes; +ProjectBoardIssueDetailsStatus.propTypes = { + issue: PropTypes.object.isRequired, + updateIssue: PropTypes.func.isRequired, +}; export default ProjectBoardIssueDetailsStatus; diff --git a/react-client/src/Project/Board/IssueDetails/Styles.js b/react-client/src/Project/Board/IssueDetails/Styles.js index dd0b7d7b..8b933270 100644 --- a/react-client/src/Project/Board/IssueDetails/Styles.js +++ b/react-client/src/Project/Board/IssueDetails/Styles.js @@ -1,6 +1,6 @@ import styled from 'styled-components'; -import { color } from 'shared/utils/styles'; +import { color } from '../../../shared/utils/styles'; export const Content = styled.div` display: flex; diff --git a/react-client/src/Project/Board/IssueDetails/Title/Styles.js b/react-client/src/Project/Board/IssueDetails/Title/Styles.js index 3d74da01..b4b114e8 100644 --- a/react-client/src/Project/Board/IssueDetails/Title/Styles.js +++ b/react-client/src/Project/Board/IssueDetails/Title/Styles.js @@ -1,7 +1,7 @@ import styled from 'styled-components'; -import { color, font } from 'shared/utils/styles'; -import { Textarea } from 'shared/components'; +import { color, font } from '../../../../shared/utils/styles'; +import { Textarea } from '../../../../shared/components'; export const TitleTextarea = styled(Textarea)` margin: 18px 0 0 -8px; diff --git a/react-client/src/Project/Board/IssueDetails/Title/index.jsx b/react-client/src/Project/Board/IssueDetails/Title/index.jsx index d569f24b..25a857ba 100644 --- a/react-client/src/Project/Board/IssueDetails/Title/index.jsx +++ b/react-client/src/Project/Board/IssueDetails/Title/index.jsx @@ -1,15 +1,10 @@ import React, { Fragment, useRef, useState } from 'react'; -import PropTypes from 'prop-types'; +import PropTypes from 'prop-types'; -import { KeyCodes } from 'shared/constants/keyCodes'; -import { is, generateErrors } from 'shared/utils/validation'; +import { KeyCodes } from '../../../../shared/constants/keyCodes'; +import { generateErrors, is } from '../../../../shared/utils/validation'; -import { TitleTextarea, ErrorText } from './Styles'; - -const propTypes = { - issue: PropTypes.object.isRequired, - updateIssue: PropTypes.func.isRequired, -}; +import { ErrorText, TitleTextarea } from './Styles'; const ProjectBoardIssueDetailsTitle = ({ issue, updateIssue }) => { const $titleInputRef = useRef(); @@ -49,6 +44,9 @@ const ProjectBoardIssueDetailsTitle = ({ issue, updateIssue }) => { ); }; -ProjectBoardIssueDetailsTitle.propTypes = propTypes; +ProjectBoardIssueDetailsTitle.propTypes = { + issue: PropTypes.object.isRequired, + updateIssue: PropTypes.func.isRequired, +}; export default ProjectBoardIssueDetailsTitle; diff --git a/react-client/src/Project/Board/IssueDetails/Type/Styles.js b/react-client/src/Project/Board/IssueDetails/Type/Styles.js index e5a0acae..87e4a27c 100644 --- a/react-client/src/Project/Board/IssueDetails/Type/Styles.js +++ b/react-client/src/Project/Board/IssueDetails/Type/Styles.js @@ -1,7 +1,7 @@ import styled from 'styled-components'; -import { color, font } from 'shared/utils/styles'; -import { Button } from 'shared/components'; +import { color } from '../../../../shared/utils/styles'; +import { Button } from '../../../../shared/components'; export const TypeButton = styled(Button)` text-transform: uppercase; diff --git a/react-client/src/Project/Board/IssueDetails/index.jsx b/react-client/src/Project/Board/IssueDetails/index.jsx index bf708fbc..75fa0837 100644 --- a/react-client/src/Project/Board/IssueDetails/index.jsx +++ b/react-client/src/Project/Board/IssueDetails/index.jsx @@ -1,38 +1,30 @@ import React, { Fragment } from 'react'; -import PropTypes from 'prop-types'; +import PropTypes from 'prop-types'; -import api from 'shared/utils/api'; -import useApi from 'shared/hooks/api'; -import { PageError, CopyLinkButton, Button, AboutTooltip } from 'shared/components'; +import api from '../../../shared/utils/api'; +import useApi from '../../../shared/hooks/api'; +import { AboutTooltip, Button, CopyLinkButton, PageError } from '../../../shared/components'; -import Loader from './Loader'; -import Type from './Type'; -import Delete from './Delete'; -import Title from './Title'; -import Description from './Description'; -import Comments from './Comments'; -import Status from './Status'; -import AssigneesReporter from './AssigneesReporter'; -import Priority from './Priority'; -import EstimateTracking from './EstimateTracking'; -import Dates from './Dates'; -import { TopActions, TopActionsRight, Content, Left, Right } from './Styles'; - -const propTypes = { - issueId: PropTypes.string.isRequired, - projectUsers: PropTypes.array.isRequired, - fetchProject: PropTypes.func.isRequired, - updateLocalProjectIssues: PropTypes.func.isRequired, - modalClose: PropTypes.func.isRequired, -}; +import Loader from './Loader'; +import Type from './Type'; +import Delete from './Delete'; +import Title from './Title'; +import Description from './Description'; +import Comments from './Comments'; +import Status from './Status'; +import AssigneesReporter from './AssigneesReporter'; +import Priority from './Priority'; +import EstimateTracking from './EstimateTracking'; +import Dates from './Dates'; +import { Content, Left, Right, TopActions, TopActionsRight } from './Styles'; const ProjectBoardIssueDetails = ({ - issueId, - projectUsers, - fetchProject, - updateLocalProjectIssues, - modalClose, -}) => { + issueId, + projectUsers, + fetchProject, + updateLocalProjectIssues, + modalClose, + }) => { const [{ data, error, setLocalData }, fetchIssue] = useApi.get(`/issues/${issueId}`); if (!data) return ; @@ -89,6 +81,12 @@ const ProjectBoardIssueDetails = ({ ); }; -ProjectBoardIssueDetails.propTypes = propTypes; +ProjectBoardIssueDetails.propTypes = { + issueId: PropTypes.string.isRequired, + projectUsers: PropTypes.array.isRequired, + fetchProject: PropTypes.func.isRequired, + updateLocalProjectIssues: PropTypes.func.isRequired, + modalClose: PropTypes.func.isRequired, +}; export default ProjectBoardIssueDetails; diff --git a/react-client/src/Project/Board/Lists/List/Issue/Styles.js b/react-client/src/Project/Board/Lists/List/Issue/Styles.js index 720da2f7..79318882 100644 --- a/react-client/src/Project/Board/Lists/List/Issue/Styles.js +++ b/react-client/src/Project/Board/Lists/List/Issue/Styles.js @@ -1,8 +1,8 @@ import styled, { css } from 'styled-components'; import { Link } from 'react-router-dom'; -import { color, font, mixin } from 'shared/utils/styles'; -import { Avatar } from 'shared/components'; +import { color } from '../../../../../shared/utils/styles'; +import { Avatar } from '../../../../../shared/components'; export const IssueLink = styled(Link)` display: block; diff --git a/react-client/src/Project/Board/Lists/List/Issue/index.jsx b/react-client/src/Project/Board/Lists/List/Issue/index.jsx index a1cd4315..fb9f65e4 100644 --- a/react-client/src/Project/Board/Lists/List/Issue/index.jsx +++ b/react-client/src/Project/Board/Lists/List/Issue/index.jsx @@ -1,18 +1,12 @@ -import React from 'react'; -import PropTypes from 'prop-types'; +import React from 'react'; +import PropTypes from 'prop-types'; import { useRouteMatch } from 'react-router-dom'; -import { Draggable } from 'react-beautiful-dnd'; +import { Draggable } from 'react-beautiful-dnd'; import { IssuePriorityIcon, IssueTypeIcon } from '../../../../../shared/components'; import { AssigneeAvatar, Assignees, Bottom, Issue, IssueLink, Title } from './Styles'; -const propTypes = { - projectUsers: PropTypes.array.isRequired, - issue: PropTypes.object.isRequired, - index: PropTypes.number.isRequired, -}; - const ProjectBoardListIssue = ({ projectUsers, issue, index }) => { const match = useRouteMatch(); @@ -54,6 +48,10 @@ const ProjectBoardListIssue = ({ projectUsers, issue, index }) => { ); }; -ProjectBoardListIssue.propTypes = propTypes; +ProjectBoardListIssue.propTypes = { + projectUsers: PropTypes.array.isRequired, + issue: PropTypes.object.isRequired, + index: PropTypes.number.isRequired, +}; export default ProjectBoardListIssue; diff --git a/react-client/src/Project/Board/Lists/List/Styles.js b/react-client/src/Project/Board/Lists/List/Styles.js index ef90b0a8..43b1c14e 100644 --- a/react-client/src/Project/Board/Lists/List/Styles.js +++ b/react-client/src/Project/Board/Lists/List/Styles.js @@ -1,6 +1,6 @@ import styled from 'styled-components'; -import { color } from 'shared/utils/styles'; +import { color } from '../../../../shared/utils/styles'; export const List = styled.div` display: flex; diff --git a/react-client/src/Project/Board/Lists/List/index.jsx b/react-client/src/Project/Board/Lists/List/index.jsx index a5c8baff..8b573526 100644 --- a/react-client/src/Project/Board/Lists/List/index.jsx +++ b/react-client/src/Project/Board/Lists/List/index.jsx @@ -1,12 +1,12 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import moment from 'moment'; -import { Droppable } from 'react-beautiful-dnd'; +import React from 'react'; +import PropTypes from 'prop-types'; +import moment from 'moment'; +import { Droppable } from 'react-beautiful-dnd'; import { intersection } from 'lodash'; -import { IssueStatusCopy } from 'shared/constants/issues'; +import { IssueStatusCopy } from '../../../../shared/constants/issues'; -import Issue from './Issue'; +import Issue from './Issue'; import { Issues, IssuesCount, List, Title } from './Styles'; const ProjectBoardList = ({ status, project, filters, currentUserId }) => { diff --git a/react-client/src/Project/Board/Lists/index.jsx b/react-client/src/Project/Board/Lists/index.jsx index 3d817018..a5d40dcc 100644 --- a/react-client/src/Project/Board/Lists/index.jsx +++ b/react-client/src/Project/Board/Lists/index.jsx @@ -1,13 +1,13 @@ -import React from 'react'; -import PropTypes from 'prop-types'; +import React from 'react'; +import PropTypes from 'prop-types'; import { DragDropContext } from 'react-beautiful-dnd'; -import useCurrentUser from 'shared/hooks/currentUser'; -import api from 'shared/utils/api'; -import { insertItemIntoArray, moveItemWithinArray } from 'shared/utils/javascript'; -import { IssueStatus } from 'shared/constants/issues'; +import useCurrentUser from '../../../shared/hooks/currentUser'; +import api from '../../../shared/utils/api'; +import { insertItemIntoArray, moveItemWithinArray } from '../../../shared/utils/javascript'; +import { IssueStatus } from '../../../shared/constants/issues'; -import List from './List'; +import List from './List'; import { Lists } from './Styles'; const ProjectBoardLists = ({ project, filters, updateLocalProjectIssues }) => { diff --git a/react-client/src/Project/Board/index.jsx b/react-client/src/Project/Board/index.jsx index de01145b..6fd35053 100644 --- a/react-client/src/Project/Board/index.jsx +++ b/react-client/src/Project/Board/index.jsx @@ -1,20 +1,20 @@ -import React, { Fragment } from 'react'; -import PropTypes from 'prop-types'; +import React, { Fragment } from 'react'; +import PropTypes from 'prop-types'; import { Route, useHistory, useRouteMatch } from 'react-router-dom'; -import useMergeState from 'shared/hooks/mergeState'; -import { Breadcrumbs, Modal } from 'shared/components'; +import useMergeState from '../../shared/hooks/mergeState'; +import { Breadcrumbs, Modal } from '../../shared/components'; -import Header from './Header'; -import Filters from './Filters'; -import Lists from './Lists'; +import Header from './Header'; +import Filters from './Filters'; +import Lists from './Lists'; import IssueDetails from './IssueDetails'; const defaultFilters = { - searchTerm: '', - userIds: [], - myOnly: false, - recent: false, + searchTerm: '', + userIds: [], + myOnly: false, + recent: false, }; const ProjectBoard = ({ project, fetchProject, updateLocalProjectIssues }) => { diff --git a/react-client/src/Project/IssueCreate/Styles.js b/react-client/src/Project/IssueCreate/Styles.js index b6ab2230..ca069fbb 100644 --- a/react-client/src/Project/IssueCreate/Styles.js +++ b/react-client/src/Project/IssueCreate/Styles.js @@ -1,7 +1,7 @@ import styled from 'styled-components'; -import { color, font } from 'shared/utils/styles'; -import { Button } from 'shared/components'; +import { color } from '../../shared/utils/styles'; +import { Button } from '../../shared/components'; export const SignIn = styled.article` margin: 24px auto; @@ -30,7 +30,7 @@ export const FormElement = styled.div` export const FormHeading = styled.div` padding-bottom: 15px; - ${ font.size(21) } + font-size: 21px; `; export const SelectItem = styled.div` diff --git a/react-client/src/Project/IssueCreate/index.jsx b/react-client/src/Project/IssueCreate/index.jsx index 86f6643d..839f416b 100644 --- a/react-client/src/Project/IssueCreate/index.jsx +++ b/react-client/src/Project/IssueCreate/index.jsx @@ -1,20 +1,26 @@ -import React from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; -import { IssuePriority, IssuePriorityCopy, IssueStatus, IssueType, IssueTypeCopy, } from 'shared/constants/issues'; -import toast from 'shared/utils/toast'; -import api from 'shared/utils/api'; -import { Avatar, Form, Icon, IssuePriorityIcon, IssueTypeIcon } from 'shared/components'; +import { + IssuePriority, + IssuePriorityCopy, + IssueStatus, + IssueType, + IssueTypeCopy, +} from '../../shared/constants/issues'; +import toast from '../../shared/utils/toast'; +import api from '../../shared/utils/api'; +import { Avatar, Form, Icon, IssuePriorityIcon, IssueTypeIcon } from '../../shared/components'; import { ActionButton, Actions, Divider, FormElement, FormHeading, SelectItem, SelectItemLabel, } from './Styles'; class ProjectIssueCreate extends React.Component { state = { isCreating: false, form: { - type: IssueType.TASK, - title: '', + type: IssueType.TASK, + title: '', description: '', - reporterId: null, + reporterId: null, userIds: [], priority: IssuePriority.MEDIUM, } diff --git a/react-client/src/Project/IssueSearch/Styles.js b/react-client/src/Project/IssueSearch/Styles.js index c8160434..adb5d21e 100644 --- a/react-client/src/Project/IssueSearch/Styles.js +++ b/react-client/src/Project/IssueSearch/Styles.js @@ -1,7 +1,7 @@ import styled from 'styled-components'; -import { color, font } from 'shared/utils/styles'; -import { Icon, InputDebounced, Spinner } from 'shared/components'; +import { color, font } from '../../shared/utils/styles'; +import { Icon, InputDebounced, Spinner } from '../../shared/components'; export const IssueSearch = styled.div` padding: 25px 35px 60px; diff --git a/react-client/src/Project/IssueSearch/index.jsx b/react-client/src/Project/IssueSearch/index.jsx index aeaeb227..f172e200 100644 --- a/react-client/src/Project/IssueSearch/index.jsx +++ b/react-client/src/Project/IssueSearch/index.jsx @@ -1,32 +1,28 @@ import React, { Fragment, useState } from 'react'; -import PropTypes from 'prop-types'; -import { Link } from 'react-router-dom'; -import { get } from 'lodash'; +import PropTypes from 'prop-types'; +import { Link } from 'react-router-dom'; +import { get } from 'lodash'; -import useApi from 'shared/hooks/api'; -import { sortByNewest } from 'shared/utils/javascript'; -import { IssueTypeIcon } from 'shared/components'; +import useApi from '../../shared/hooks/api'; +import { sortByNewest } from '../../shared/utils/javascript'; +import { IssueTypeIcon } from '../../shared/components'; import NoResultsSVG from './NoResultsSvg'; import { - IssueSearch, - SearchInputCont, - SearchInputDebounced, - SearchIcon, - SearchSpinner, Issue, IssueData, + IssueSearch, IssueTitle, IssueTypeId, - SectionTitle, NoResults, - NoResultsTitle, NoResultsTip, -} from './Styles'; - -const propTypes = { - project: PropTypes.object.isRequired, -}; + NoResultsTitle, + SearchIcon, + SearchInputCont, + SearchInputDebounced, + SearchSpinner, + SectionTitle, +} from './Styles'; const ProjectIssueSearch = ({ project }) => { const [isSearchTermEmpty, setIsSearchTermEmpty] = useState(true); @@ -96,6 +92,8 @@ const renderIssue = issue => ( ); -ProjectIssueSearch.propTypes = propTypes; +ProjectIssueSearch.propTypes = { + project: PropTypes.object.isRequired, +}; export default ProjectIssueSearch; diff --git a/react-client/src/Project/NavbarLeft/Styles.js b/react-client/src/Project/NavbarLeft/Styles.js index 776836d7..ebba1b89 100644 --- a/react-client/src/Project/NavbarLeft/Styles.js +++ b/react-client/src/Project/NavbarLeft/Styles.js @@ -1,8 +1,8 @@ import styled from 'styled-components'; import { NavLink } from 'react-router-dom'; -import { color, mixin, sizes, zIndexValues } from 'shared/utils/styles'; -import { Logo } from 'shared/components'; +import { color, sizes, zIndexValues } from '../../shared/utils/styles'; +import { Logo } from '../../shared/components'; export const NavLeft = styled.aside` z-index: ${zIndexValues.navLeft}; @@ -14,7 +14,7 @@ export const NavLeft = styled.aside` width: ${sizes.appNavBarLeftWidth}px; background: ${color.backgroundDarkPrimary}; transition: all 0.1s; - ${mixin.hardwareAccelerate} + transform: translateZ(0); &:hover { width: 200px; box-shadow: 0 0 50px 0 rgba(0, 0, 0, 0.6); diff --git a/react-client/src/Project/NavbarLeft/index.jsx b/react-client/src/Project/NavbarLeft/index.jsx index 4a6c520f..2db80df1 100644 --- a/react-client/src/Project/NavbarLeft/index.jsx +++ b/react-client/src/Project/NavbarLeft/index.jsx @@ -1,15 +1,10 @@ -import React from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; -import { AboutTooltip, Icon } from 'shared/components'; +import { AboutTooltip, Icon } from '../../shared/components'; import { Bottom, Item, ItemText, LogoLink, NavLeft, StyledLogo } from './Styles'; -const propTypes = { - issueSearchModalOpen: PropTypes.func.isRequired, - issueCreateModalOpen: PropTypes.func.isRequired, -}; - const ProjectNavbarLeft = ({ issueSearchModalOpen, issueCreateModalOpen }) => ( @@ -41,6 +36,9 @@ const ProjectNavbarLeft = ({ issueSearchModalOpen, issueCreateModalOpen }) => ( ); -ProjectNavbarLeft.propTypes = propTypes; +ProjectNavbarLeft.propTypes = { + issueSearchModalOpen: PropTypes.func.isRequired, + issueCreateModalOpen: PropTypes.func.isRequired, +}; export default ProjectNavbarLeft; diff --git a/react-client/src/Project/ProjectSettings/Styles.js b/react-client/src/Project/ProjectSettings/Styles.js index 0b66ddde..ea2b24fa 100644 --- a/react-client/src/Project/ProjectSettings/Styles.js +++ b/react-client/src/Project/ProjectSettings/Styles.js @@ -1,7 +1,7 @@ import styled from 'styled-components'; -import { font } from 'shared/utils/styles'; -import { Button, Form } from 'shared/components'; +import { font } from '../../shared/utils/styles'; +import { Button, Form } from '../../shared/components'; export const FormCont = styled.div` display: flex; @@ -16,7 +16,7 @@ export const FormElement = styled(Form.Element)` export const FormHeading = styled.h1` padding: 6px 0 15px; font-size: 24px - ${font.medium} + ${font.medium}; font-weight: normal; `; export const ActionButton = styled(Button)` diff --git a/react-client/src/Project/ProjectSettings/index.jsx b/react-client/src/Project/ProjectSettings/index.jsx index ab8f91ce..c6b6db1d 100644 --- a/react-client/src/Project/ProjectSettings/index.jsx +++ b/react-client/src/Project/ProjectSettings/index.jsx @@ -1,21 +1,28 @@ -import React from 'react'; -import PropTypes from 'prop-types'; +import React from 'react'; +import PropTypes from 'prop-types'; import { connect } from "react-redux"; -import { ProjectCategory, ProjectCategoryCopy } from 'shared/constants/projects'; -import toast from 'shared/utils/toast'; -import api from 'shared/utils/api'; -import { Breadcrumbs, Form } from 'shared/components'; -import { updateProjectFormFieldChanged, updateProjectFormRequest, updateProjectFormSuccess, } from 'actions/forms'; +import { ProjectCategory, ProjectCategoryCopy } from '../../shared/constants/projects'; +import toast from '../../shared/utils/toast'; +import api from '../../shared/utils/api'; +import { + Breadcrumbs, + Form +} from '../../shared/components'; +import { + updateProjectFormFieldChanged, + updateProjectFormRequest, + updateProjectFormSuccess, +} from '../../actions/forms'; import { ActionButton, FormCont, FormElement, FormHeading } from './Styles'; class ProjectSettings extends React.Component { state = { isUpdating: false, form: { - name: '', - url: '', - category: '', + name: '', + url: '', + category: '', description: '', } }; diff --git a/react-client/src/Project/Sidebar/Styles.js b/react-client/src/Project/Sidebar/Styles.js index 2e6841b8..02565e10 100644 --- a/react-client/src/Project/Sidebar/Styles.js +++ b/react-client/src/Project/Sidebar/Styles.js @@ -1,6 +1,6 @@ import styled from 'styled-components'; -import { color, font, mixin, sizes, zIndexValues } from 'shared/utils/styles'; +import { color, font, sizes, zIndexValues } from '../../shared/utils/styles'; export const Sidebar = styled.div` position: fixed; @@ -15,7 +15,17 @@ export const Sidebar = styled.div` overflow-x: hidden; overflow-y: auto; -webkit-overflow-scrolling: touch; - ${mixin.customScrollbar()} + &::-webkit-scrollbar { + width: 8px; + } + &::-webkit-scrollbar-track { + background: none; + } + &::-webkit-scrollbar-thumb { + border-radius: 99px; + background: ${color.backgroundMedium}; + } + @media (max-width: 1100px) { width: ${sizes.secondarySideBarWidth - 10}px; } diff --git a/react-client/src/Project/Sidebar/index.jsx b/react-client/src/Project/Sidebar/index.jsx index b2ff0707..d51e3273 100644 --- a/react-client/src/Project/Sidebar/index.jsx +++ b/react-client/src/Project/Sidebar/index.jsx @@ -1,26 +1,22 @@ -import React from 'react'; -import PropTypes from 'prop-types'; +import React from 'react'; +import PropTypes from 'prop-types'; import { NavLink, useRouteMatch } from 'react-router-dom'; -import { ProjectCategoryCopy } from 'shared/constants/projects'; -import { Icon, ProjectAvatar } from 'shared/components'; +import { ProjectCategoryCopy } from '../../shared/constants/projects'; +import { Icon, ProjectAvatar } from '../../shared/components'; import { - Sidebar, - ProjectInfo, - ProjectTexts, - ProjectName, - ProjectCategory, Divider, LinkItem, LinkText, NotImplemented, + ProjectCategory, + ProjectInfo, + ProjectName, + ProjectTexts, + Sidebar, } from './Styles'; -const propTypes = { - project: PropTypes.object.isRequired, -}; - const ProjectSidebar = ({ project }) => { const match = useRouteMatch(); @@ -62,6 +58,8 @@ const renderLinkItem = (match, text, iconType, path) => { ); }; -ProjectSidebar.propTypes = propTypes; +ProjectSidebar.propTypes = { + project: PropTypes.object.isRequired, +}; export default ProjectSidebar; diff --git a/react-client/src/Project/index.jsx b/react-client/src/Project/index.jsx index 834aefe5..2e43e92c 100644 --- a/react-client/src/Project/index.jsx +++ b/react-client/src/Project/index.jsx @@ -1,25 +1,25 @@ -import React from 'react'; +import React from 'react'; import { Redirect, Route, useHistory, useRouteMatch } from 'react-router-dom'; -import useApi from 'shared/hooks/api'; -import { updateArrayItemById } from 'shared/utils/javascript'; -import { createQueryParamModalHelpers } from 'shared/utils/queryParamModal'; -import { Modal, PageError, PageLoader } from 'shared/components'; +import useApi from '../shared/hooks/api'; +import { updateArrayItemById } from '../shared/utils/javascript'; +import { createQueryParamModalHelpers } from '../shared/utils/queryParamModal'; +import { Modal, PageError, PageLoader } from '../shared/components'; -import NavbarLeft from './NavbarLeft'; -import Sidebar from './Sidebar'; -import Board from './Board'; -import IssueSearch from './IssueSearch'; -import IssueCreate from './IssueCreate'; +import NavbarLeft from './NavbarLeft'; +import Sidebar from './Sidebar'; +import Board from './Board'; +import IssueSearch from './IssueSearch'; +import IssueCreate from './IssueCreate'; import ProjectSettings from './ProjectSettings'; import { ProjectPage } from './Styles'; const Project = () => { - const match = useRouteMatch(); - const history = useHistory(); + const match = useRouteMatch(); + const history = useHistory(); - const issueSearchModalHelpers = createQueryParamModalHelpers('issue-search'); - const issueCreateModalHelpers = createQueryParamModalHelpers('issue-create'); + const issueSearchModalHelpers = createQueryParamModalHelpers('issue-search'); + const issueCreateModalHelpers = createQueryParamModalHelpers('issue-create'); const [{ data, error, setLocalData }, fetchProject] = useApi.get('/project'); diff --git a/react-client/src/shared/components/CopyLinkButton.jsx b/react-client/src/shared/components/CopyLinkButton.jsx index ee102e95..ecae359b 100644 --- a/react-client/src/shared/components/CopyLinkButton.jsx +++ b/react-client/src/shared/components/CopyLinkButton.jsx @@ -1,16 +1,16 @@ import React, { useState } from 'react'; -import { copyToClipboard } from 'shared/utils/browser'; -import { Button } from 'shared/components'; +import { copyToClipboard } from '../../shared/utils/browser'; +import { Button } from '../../shared/components'; const CopyLinkButton = ({ ...buttonProps }) => { - const [isLinkCopied, setLinkCopied] = useState(false); + const [isLinkCopied, setLinkCopied] = useState(false); - const handleLinkCopy = () => { - setLinkCopied(true); - setTimeout(() => setLinkCopied(false), 2000); - copyToClipboard(window.location.href); - }; + const handleLinkCopy = () => { + setLinkCopied(true); + setTimeout(() => setLinkCopied(false), 2000); + copyToClipboard(window.location.href); + }; return (