Fix use issues

This commit is contained in:
Adrian Woźniak 2021-01-06 23:10:13 +01:00
parent 01ce1794cd
commit 0c62a41f70
74 changed files with 572 additions and 525 deletions

View File

@ -193,36 +193,3 @@ db_create_with_conn! {
user_ids => Vec<jirs_data::UserId>,
epic_id => Option<jirs_data::EpicId>
}
// impl Handler<CreateIssue> for DbExecutor {
// type Result = Result<Issue, crate::DatabaseError>;
//
// fn handle(&mut self, msg: CreateIssue, ctx: &mut Self::Context) -> Self::Result {
// use crate::schema::issue_assignees::dsl;
// use crate::schema::issues::dsl::issues;
//
// let mut values = vec![];
// for user_id in msg.user_ids.iter() {
// values.push(crate::models::CreateIssueAssigneeForm {
// issue_id: issue.id,
// user_id: *user_id,
// });
// }
// if !msg.user_ids.contains(&msg.reporter_id) {
// values.push(crate::models::CreateIssueAssigneeForm {
// issue_id: issue.id,
// user_id: msg.reporter_id,
// });
// }
//
// diesel::insert_into(dsl::issue_assignees)
// .values(values)
// .execute(conn)
// .map_err(|e| {
// log::error!("{:?}", e);
// crate::DatabaseError::DatabaseConnectionLost
// })?;
//
// Ok(issue)
// }
// }

View File

@ -64,52 +64,6 @@ db_create! {
email => EmailString
}
/*impl CreateUser {
pub fn execute(self, conn: &DbPooledConn) -> Result<User, crate::DatabaseError> {
use crate::schema::users::dsl::*;
q!(diesel::insert_into(users)
.values((name.eq(self.name.as_str()), email.eq(self.email.as_str()))))
.get_result(conn)
.map_err(|e| {
log::error!("{:?}", e);
let ws = match e {
Error::InvalidCString(_) => {
crate::DatabaseError::User(UserError::InvalidPair(self.name, self.email))
}
Error::DatabaseError(diesel::result::DatabaseErrorKind::UniqueViolation, _) => {
crate::DatabaseError::User(UserError::TakenPair(self.name, self.email))
}
Error::DatabaseError(_, _) => {
crate::DatabaseError::User(UserError::InvalidPair(self.name, self.email))
}
Error::NotFound => {
crate::DatabaseError::User(UserError::InvalidPair(self.name, self.email))
}
Error::QueryBuilderError(_) => {
crate::DatabaseError::User(UserError::InvalidPair(self.name, self.email))
}
Error::DeserializationError(_) => {
crate::DatabaseError::User(UserError::InvalidPair(self.name, self.email))
}
Error::SerializationError(_) => {
crate::DatabaseError::User(UserError::InvalidPair(self.name, self.email))
}
Error::RollbackTransaction => {
crate::DatabaseError::User(UserError::InvalidPair(self.name, self.email))
}
Error::AlreadyInTransaction => {
crate::DatabaseError::User(UserError::InvalidPair(self.name, self.email))
}
Error::__Nonexhaustive => {
crate::DatabaseError::User(UserError::InvalidPair(self.name, self.email))
}
};
crate::DatabaseError::Error(ws)
})
}
}*/
db_create_with_conn! {
Register,
msg => conn => users => {

View File

@ -1,6 +1,6 @@
use jirs_data::HighlightedCode;
use {
actix::{Actor, Handler, SyncContext},
jirs_data::HighlightedCode,
std::sync::Arc,
syntect::{
easy::HighlightLines,

View File

@ -1,15 +1,9 @@
#![allow(unused_imports)]
#![allow(dead_code)]
use std::io::BufRead;
use std::{rc::Rc, sync::Arc};
use bincode::{deserialize_from, Result};
use flate2::bufread::ZlibDecoder;
use serde::de::DeserializeOwned;
use syntect::easy::HighlightLines;
use syntect::highlighting::ThemeSet;
use syntect::parsing::SyntaxSet;
use {
bincode::{deserialize_from, Result},
flate2::bufread::ZlibDecoder,
serde::de::DeserializeOwned,
std::io::BufRead,
};
fn from_reader<T: DeserializeOwned, R: BufRead>(input: R) -> Result<T> {
let mut decoder = ZlibDecoder::new(input);
@ -29,17 +23,3 @@ pub fn integrated_syntaxset() -> syntect::parsing::SyntaxSet {
pub fn integrated_themeset() -> syntect::highlighting::ThemeSet {
from_binary(include_bytes!("./themes.bin"))
}
pub fn load() -> (Rc<ThemeSet>, Rc<SyntaxSet>) {
let theme_set = Rc::new(integrated_themeset());
let syntax_set = Rc::new(integrated_syntaxset());
(theme_set, syntax_set)
}
pub fn arc() -> (Arc<ThemeSet>, Arc<SyntaxSet>) {
use std::sync::Arc;
let theme_set = Arc::new(integrated_themeset());
let syntax_set = Arc::new(integrated_syntaxset());
(theme_set, syntax_set)
}

View File

@ -1,9 +1,8 @@
use actix::{Handler, Message};
// use lettre;
// use lettre_email;
use uuid::Uuid;
use crate::MailExecutor;
use {
crate::MailExecutor,
actix::{Handler, Message},
uuid::Uuid,
};
#[derive(Debug)]
pub struct Invite {

View File

@ -1,7 +1,5 @@
use actix::{Actor, SyncContext};
// use lettre;
pub mod invite;
pub mod welcome;
@ -27,15 +25,18 @@ impl Default for MailExecutor {
}
fn mail_client(config: &jirs_config::mail::Configuration) -> lettre::SmtpClient {
let mail_user = config.user.as_str();
let mail_pass = config.pass.as_str();
let mail_host = config.host.as_str();
let jirs_config::mail::Configuration {
user: mail_user,
pass: mail_pass,
host: mail_host,
..
} = &config;
lettre::SmtpClient::new_simple(mail_host)
.expect("Failed to init SMTP client")
.credentials(lettre::smtp::authentication::Credentials::new(
mail_user.to_string(),
mail_pass.to_string(),
mail_user.clone(),
mail_pass.clone(),
))
.connection_reuse(lettre::smtp::ConnectionReuseParameters::ReuseUnlimited)
.smtp_utf8(true)

View File

@ -1,9 +1,8 @@
use actix::{Handler, Message};
// use lettre;
// use lettre_email;
use uuid::Uuid;
use crate::MailExecutor;
use {
crate::MailExecutor,
actix::{Handler, Message},
uuid::Uuid,
};
#[derive(Debug)]
pub struct Welcome {

View File

@ -1,9 +1,9 @@
use futures::executor::block_on;
use database_actor::issue_statuses;
use jirs_data::{IssueStatusId, Position, TitleString, WsMsg};
use crate::{WebSocketActor, WsHandler, WsResult};
use {
crate::{WebSocketActor, WsHandler, WsResult},
database_actor::issue_statuses,
futures::executor::block_on,
jirs_data::{IssueStatusId, Position, TitleString, WsMsg},
};
pub struct LoadIssueStatuses;

View File

@ -1,9 +1,9 @@
use futures::executor::block_on;
use database_actor::messages;
use jirs_data::{MessageId, WsMsg};
use crate::{WebSocketActor, WsHandler, WsResult};
use {
crate::{WebSocketActor, WsHandler, WsResult},
database_actor::messages,
futures::executor::block_on,
jirs_data::{MessageId, WsMsg},
};
pub struct LoadMessages;

View File

@ -1,9 +1,9 @@
use futures::executor::block_on;
use database_actor as db;
use jirs_data::{UpdateProjectPayload, UserProject, WsMsg};
use crate::{WebSocketActor, WsHandler, WsResult};
use {
crate::{WebSocketActor, WsHandler, WsResult},
database_actor as db,
futures::executor::block_on,
jirs_data::{UpdateProjectPayload, UserProject, WsMsg},
};
impl WsHandler<UpdateProjectPayload> for WebSocketActor {
fn handle_msg(&mut self, msg: UpdateProjectPayload, _ctx: &mut Self::Context) -> WsResult {

View File

@ -1,9 +1,9 @@
use futures::executor::block_on;
use database_actor as db;
use jirs_data::{UserProjectId, WsMsg};
use crate::{WebSocketActor, WsHandler, WsResult};
use {
crate::{WebSocketActor, WsHandler, WsResult},
database_actor as db,
futures::executor::block_on,
jirs_data::{UserProjectId, WsMsg},
};
pub struct LoadUserProjects;

View File

@ -1,9 +1,8 @@
use futures::executor::block_on;
use jirs_data::{UserId, UserProject, UserRole, WsMsg};
use {
crate::{handlers::auth::Authenticate, WebSocketActor, WsHandler, WsResult},
database_actor::{self, users::Register as DbRegister},
futures::executor::block_on,
jirs_data::{UserId, UserProject, UserRole, WsMsg},
};
pub struct LoadProjectUsers;

View File

@ -1,8 +1,8 @@
use std::collections::HashMap;
use actix::{Actor, Context, Recipient};
use jirs_data::{ProjectId, UserId, WsMsg};
use {
actix::{Actor, Context, Recipient},
jirs_data::{ProjectId, UserId, WsMsg},
std::collections::HashMap,
};
#[derive(actix::Message, Debug)]
#[rtype(result = "()")]

View File

@ -1,16 +1,21 @@
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{mpsc, Arc};
use std::time::Duration;
use std::{error::Error, io /*, thread*/};
// use termion::input::TermRead;
use termion::{event::Key, input::MouseTerminal, raw::IntoRawMode, screen::AlternateScreen};
use tui::{
use {
std::{
error::Error,
io,
sync::{
atomic::{AtomicBool, Ordering},
mpsc, Arc,
},
time::Duration,
},
termion::{event::Key, input::MouseTerminal, raw::IntoRawMode, screen::AlternateScreen},
tui::{
backend::TermionBackend,
layout::{Constraint, Direction, Layout},
style::{Color, Style},
widgets::{Block, Borders, Tabs},
Terminal,
},
};
#[derive(Debug, Clone, Copy)]

View File

@ -1,8 +1,5 @@
use seed::{prelude::*, *};
use jirs_data::{TimeTracking, WsMsg};
use crate::{
use {
crate::{
model::{self, ModalType, Model, Page},
shared::{
find_issue, go_to_board,
@ -12,13 +9,12 @@ use crate::{
},
ws::send_ws_msg,
FieldChange, FieldId, Msg, WebSocketChanged,
},
jirs_data::{TimeTracking, WsMsg},
seed::{prelude::*, *},
};
mod confirm_delete_issue;
#[cfg(debug_assertions)]
mod debug_modal;
pub mod issues;
pub mod time_tracking;
pub fn update(msg: &Msg, model: &mut model::Model, orders: &mut impl Orders<Msg>) {
match msg {
@ -102,7 +98,7 @@ pub fn view(model: &model::Model) -> Node<Msg> {
empty![]
}
}
ModalType::DeleteIssueConfirm(_id) => confirm_delete_issue::view(model),
ModalType::DeleteIssueConfirm(_id) => crate::modals::issues_delete::view(model),
ModalType::AddIssue(modal) => issues_create::view(model, modal),
ModalType::DeleteCommentConfirm(comment_id) => {
let comment_id = *comment_id;
@ -114,12 +110,14 @@ pub fn view(model: &model::Model) -> Node<Msg> {
.build()
.into_node()
}
ModalType::TimeTracking(issue_id) => time_tracking::view(model, *issue_id),
ModalType::TimeTracking(issue_id) => {
crate::modals::time_tracking::view(model, *issue_id)
}
ModalType::DeleteIssueStatusModal(delete_issue_modal) => {
issue_statuses_delete::view(model, delete_issue_modal.delete_id)
}
#[cfg(debug_assertions)]
ModalType::DebugModal => debug_modal::view(model),
ModalType::DebugModal => crate::modals::debug::view(model),
})
.collect();
section![id!["modals"], modals]

View File

@ -1,17 +1,23 @@
use seed::{prelude::*, *};
use {
crate::{
model::{ModalType, Model},
shared::{
find_issue,
styled_button::StyledButton,
styled_field::StyledField,
styled_input::{StyledInput, StyledInputState},
styled_modal::StyledModal,
styled_select::{StyledSelect, StyledSelectState},
tracking_widget::{fibonacci_values, tracking_widget},
ToChild, ToNode,
},
EditIssueModalSection, FieldId, Msg,
},
jirs_data::{IssueFieldId, IssueId, TimeTracking},
seed::{prelude::*, *},
};
use jirs_data::{IssueFieldId, IssueId, TimeTracking};
use crate::model::{ModalType, Model};
use crate::shared::styled_button::StyledButton;
use crate::shared::styled_field::StyledField;
use crate::shared::styled_input::{StyledInput, StyledInputState};
use crate::shared::styled_modal::StyledModal;
use crate::shared::styled_select::{StyledSelect, StyledSelectState};
use crate::shared::{find_issue, ToChild, ToNode};
use crate::{EditIssueModalSection, FieldId, Msg};
// use crate::shared::styled_select_child::*;
use crate::shared::tracking_widget::{fibonacci_values, tracking_widget};
pub fn value_for_time_tracking(v: &Option<i32>, time_tracking_type: &TimeTracking) -> String {
match (time_tracking_type, v.as_ref()) {
@ -82,6 +88,7 @@ pub fn view(model: &Model, issue_id: IssueId) -> Node<Msg> {
.into_node()
}
#[inline]
pub fn time_tracking_field(
time_tracking_type: TimeTracking,
field_id: FieldId,

View File

@ -0,0 +1,5 @@
pub use {model::*, update::*, view::*};
mod model;
mod update;
mod view;

View File

View File

View File

@ -1,9 +1,11 @@
use seed::{prelude::*, *};
use crate::model::Model;
use crate::shared::styled_modal::StyledModal;
use crate::shared::ToNode;
use crate::Msg;
use {
crate::{
model::Model,
shared::{styled_modal::StyledModal, ToNode},
Msg,
},
seed::{prelude::*, *},
};
pub fn view(model: &Model) -> Node<Msg> {
let text = format!("{:#?}", model);

View File

@ -1,6 +1,4 @@
pub use model::*;
pub use update::*;
pub use view::*;
pub use {model::*, update::*, view::*};
mod model;
mod update;

View File

@ -1,11 +1,11 @@
use seed::prelude::*;
use jirs_data::IssueStatusId;
use crate::{
use {
crate::{
model,
shared::{styled_confirm_modal::StyledConfirmModal, ToNode},
Msg,
},
jirs_data::IssueStatusId,
seed::prelude::*,
};
pub fn view(_model: &model::Model, issue_status_id: IssueStatusId) -> Node<Msg> {

View File

@ -1,6 +1,4 @@
pub use model::*;
pub use update::*;
pub use view::*;
pub use {model::*, update::*, view::*};
mod model;
mod update;

View File

@ -10,10 +10,10 @@ use {
};
pub fn update(msg: &Msg, model: &mut crate::model::Model, orders: &mut impl Orders<Msg>) {
let modal = model.modals.iter_mut().find(|modal| match modal {
ModalType::AddIssue(..) => true,
_ => false,
});
let modal = model
.modals
.iter_mut()
.find(|modal| matches!(modal, ModalType::AddIssue(..)));
let modal = match modal {
Some(ModalType::AddIssue(modal)) => modal,
_ => return,

View File

@ -15,7 +15,7 @@ use {
seed::{prelude::*, *},
};
pub fn view(model: &Model, modal: &Box<AddIssueModal>) -> Node<Msg> {
pub fn view(model: &Model, modal: &AddIssueModal) -> Node<Msg> {
let issue_type = modal
.type_state
.values
@ -64,11 +64,8 @@ pub fn view(model: &Model, modal: &Box<AddIssueModal>) -> Node<Msg> {
let reporter_field = reporter_field(model, modal);
let assignees_field = assignees_field(model, modal);
let issue_priority_field = issue_priority_field(modal);
let epic_field = epic_field(
model,
modal.as_ref(),
FieldId::AddIssueModal(IssueFieldId::EpicName),
);
let epic_field =
epic_field(model, modal, FieldId::AddIssueModal(IssueFieldId::EpicName));
form.add_field(short_summary_field)
.add_field(description_field)
@ -120,7 +117,7 @@ pub fn view(model: &Model, modal: &Box<AddIssueModal>) -> Node<Msg> {
.into_node()
}
fn issue_type_field(modal: &Box<AddIssueModal>) -> Node<Msg> {
fn issue_type_field(modal: &AddIssueModal) -> Node<Msg> {
let select_type = StyledSelect::build()
.name("type")
.normal()
@ -148,7 +145,8 @@ fn issue_type_field(modal: &Box<AddIssueModal>) -> Node<Msg> {
.into_node()
}
fn short_summary_field(modal: &Box<AddIssueModal>) -> Node<Msg> {
#[inline]
fn short_summary_field(modal: &AddIssueModal) -> Node<Msg> {
let short_summary = StyledInput::build()
.state(&modal.title_state)
.build(FieldId::AddIssueModal(IssueFieldId::Title))

View File

@ -0,0 +1,5 @@
pub use {model::*, update::*, view::*};
mod model;
mod update;
mod view;

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -1,9 +1,10 @@
use seed::{prelude::*, *};
use crate::model::ModalType;
use crate::shared::styled_confirm_modal::StyledConfirmModal;
use crate::shared::ToNode;
use crate::{model, Msg};
use {
crate::{
model, model::ModalType, shared::styled_confirm_modal::StyledConfirmModal, shared::ToNode,
Msg,
},
seed::{prelude::*, *},
};
pub fn view(model: &model::Model) -> Node<Msg> {
let opt_id = model

View File

@ -1,6 +1,4 @@
pub use model::*;
pub use update::*;
pub use view::*;
pub use {model::*, update::*, view::*};
mod model;
mod update;

View File

@ -1,10 +1,11 @@
use {
crate::{
modal::time_tracking::value_for_time_tracking,
modals::time_tracking::value_for_time_tracking,
model::{CommentForm, IssueModal},
shared::{
styled_date_time_input::StyledDateTimeInputState, styled_editor::Mode,
styled_input::StyledInputState, styled_select::StyledSelectState,
styled_editor::StyledEditorState, styled_input::StyledInputState,
styled_select::StyledSelectState,
},
EditIssueModalSection, FieldId, Msg,
},
@ -12,8 +13,6 @@ use {
seed::prelude::*,
};
use crate::shared::styled_editor::StyledEditorState;
#[derive(Clone, Debug, PartialOrd, PartialEq)]
pub struct Model {
pub id: IssueId,

View File

@ -1,7 +1,7 @@
use {
crate::{
modal::{issues::epic_field, time_tracking::time_tracking_field},
modals::issues_edit::Model as EditIssueModal,
modal::issues::epic_field,
modals::{issues_edit::Model as EditIssueModal, time_tracking::time_tracking_field},
model::{ModalType, Model},
shared::{
styled_avatar::StyledAvatar, styled_button::StyledButton, styled_editor::StyledEditor,

View File

@ -1,3 +1,7 @@
#[cfg(debug_assertions)]
pub mod debug;
pub mod issue_statuses_delete;
pub mod issues_create;
pub mod issues_delete;
pub mod issues_edit;
pub mod time_tracking;

View File

@ -0,0 +1,5 @@
pub use {model::*, update::*, view::*};
mod model;
mod update;
mod view;

View File

@ -0,0 +1,125 @@
use {
crate::{
model::{ModalType, Model},
shared::{
find_issue,
styled_button::StyledButton,
styled_field::StyledField,
styled_input::{StyledInput, StyledInputState},
styled_modal::StyledModal,
styled_select::{StyledSelect, StyledSelectState},
tracking_widget::{fibonacci_values, tracking_widget},
ToChild, ToNode,
},
EditIssueModalSection, FieldId, Msg,
},
jirs_data::{IssueFieldId, IssueId, TimeTracking},
seed::{prelude::*, *},
};
// use crate::shared::styled_select_child::*;
pub fn value_for_time_tracking(v: &Option<i32>, time_tracking_type: &TimeTracking) -> String {
match (time_tracking_type, v.as_ref()) {
(TimeTracking::Untracked, _) => "".to_string(),
(TimeTracking::Fibonacci, Some(n)) => n.to_string(),
(TimeTracking::Hourly, Some(n)) => format!("{:.1}", *n as f64 / 10.0f64),
_ => "".to_string(),
}
}
pub fn view(model: &Model, issue_id: IssueId) -> Node<Msg> {
let _issue = match find_issue(model, issue_id) {
Some(issue) => issue,
_ => return empty![],
};
let edit_issue_modal = match model.modals.get(0) {
Some(ModalType::EditIssue(_, modal)) => modal,
_ => return empty![],
};
let time_tracking_type = model
.project
.as_ref()
.map(|p| p.time_tracking)
.unwrap_or_else(|| TimeTracking::Untracked);
let modal_title = div![C!["modalTitle"], "Time tracking"];
let tracking = tracking_widget(model, edit_issue_modal);
let time_spent_field = time_tracking_field(
time_tracking_type,
FieldId::EditIssueModal(EditIssueModalSection::Issue(IssueFieldId::TimeSpent)),
"Time spent",
&edit_issue_modal.time_spent,
&edit_issue_modal.time_spent_select,
);
let time_remaining_field = time_tracking_field(
time_tracking_type,
FieldId::EditIssueModal(EditIssueModalSection::Issue(IssueFieldId::TimeRemaining)),
"Time remaining",
&edit_issue_modal.time_remaining,
&edit_issue_modal.time_remaining_select,
);
let inputs = div![
C!["inputs"],
div![C!["inputContainer"], time_spent_field],
div![C!["inputContainer"], time_remaining_field]
];
let close = StyledButton::build()
.text("Done")
.on_click(mouse_ev(Ev::Click, |_| Msg::ModalDropped))
.build()
.into_node();
StyledModal::build()
.add_class("timeTrackingModal")
.children(vec![
modal_title,
tracking,
inputs,
div![C!["actions"], close],
])
.width(400)
.build()
.into_node()
}
#[inline]
pub fn time_tracking_field(
time_tracking_type: TimeTracking,
field_id: FieldId,
label: &str,
input_state: &StyledInputState,
select_state: &StyledSelectState,
) -> Node<Msg> {
let fibonacci_values = fibonacci_values();
let input = match time_tracking_type {
TimeTracking::Untracked => empty![],
TimeTracking::Fibonacci => StyledSelect::build()
.selected(
select_state
.values
.iter()
.map(|n| (*n).to_child())
.collect(),
)
.state(select_state)
.options(fibonacci_values.iter().map(|v| v.to_child()).collect())
.build(field_id)
.into_node(),
TimeTracking::Hourly => StyledInput::build()
.state(input_state)
.valid(true)
.build(field_id)
.into_node(),
};
StyledField::build()
.input(input)
.label(label)
.build()
.into_node()
}

View File

@ -1,6 +1,4 @@
pub use model::*;
pub use update::*;
pub use view::*;
pub use {model::*, update::*, view::*};
mod model;
mod update;

View File

@ -1,16 +1,15 @@
use std::str::FromStr;
use seed::prelude::*;
use jirs_data::{fields::*, WsMsg};
use crate::{
use {
crate::{
authorize_or_redirect,
model::{Model, Page, PageContent},
pages::invite_page::InvitePage,
shared::write_auth_token,
ws::send_ws_msg,
FieldId, InvitationPageChange, Msg, PageChanged, WebSocketChanged,
},
jirs_data::{fields::*, WsMsg},
seed::prelude::*,
std::str::FromStr,
};
pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {

View File

@ -1,5 +1,4 @@
pub use update::*;
pub use view::*;
pub use {model::*, update::*, view::*};
pub mod model;
pub mod update;

View File

@ -1,11 +1,12 @@
use jirs_data::{ProjectId, User, UsersFieldId};
use crate::{
use {
crate::{
shared::{
styled_image_input::StyledImageInputState, styled_input::StyledInputState,
styled_select::StyledSelectState,
},
FieldId,
},
jirs_data::{ProjectId, User, UsersFieldId},
};
#[derive(Debug)]

View File

@ -1,5 +1,4 @@
pub use update::*;
pub use view::*;
pub use {model::*, update::*, view::*};
pub mod model;
pub mod update;

View File

@ -1,8 +1,4 @@
use std::collections::HashMap;
use jirs_data::*;
use crate::shared::drag::DragState;
use {crate::shared::drag::DragState, jirs_data::*, std::collections::HashMap};
#[derive(Default, Debug)]
pub struct StatusIssueIds {
@ -17,9 +13,6 @@ pub struct EpicIssuePerStatus {
pub per_status_issues: Vec<StatusIssueIds>,
}
// pub type VisibleIssueMap =
// HashMap<EpicName, HashMap<(IssueStatusId, IssueStatusName), Vec<IssueId>>>;
#[derive(Debug, Default)]
pub struct ProjectPage {
pub text_filter: String,
@ -33,9 +26,9 @@ pub struct ProjectPage {
impl ProjectPage {
pub fn rebuild_visible(
&mut self,
epics: &Vec<Epic>,
statuses: &Vec<IssueStatus>,
issues: &Vec<Issue>,
epics: &[Epic],
statuses: &[IssueStatus],
issues: &[Issue],
user: &Option<User>,
) {
let mut map = vec![];
@ -66,7 +59,7 @@ impl ProjectPage {
let mut per_epic_map = EpicIssuePerStatus::default();
per_epic_map.epic_name = epic.map(|(_, name)| name).unwrap_or_default().to_string();
for (current_status_id, issue_status_name) in statuses.clone() {
for (current_status_id, issue_status_name) in statuses.to_owned() {
let mut per_status_map = StatusIssueIds::default();
per_status_map.status_id = current_status_id;
per_status_map.status_name = issue_status_name.to_string();
@ -111,8 +104,3 @@ fn issue_filter_with_only_my(issue: &Issue, only_my: bool, user: &Option<User>)
let my_id = user.as_ref().map(|u| u.id).unwrap_or_default();
!only_my || issue.user_ids.contains(&my_id)
}
// #[inline]
// fn issue_filter_with_only_recent(issue: &Issue, ids: &[IssueId]) -> bool {
// ids.is_empty() || ids.contains(&issue.id)
// }

View File

@ -4,14 +4,13 @@ use {
pages::project_page::model::ProjectPage,
shared::styled_select::StyledSelectChanged,
ws::{board_load, send_ws_msg},
BoardPageChange, EditIssueModalSection, FieldId, Msg, PageChanged, WebSocketChanged,
BoardPageChange, EditIssueModalSection, FieldId, Msg, OperationKind, PageChanged,
ResourceKind,
},
jirs_data::*,
seed::prelude::Orders,
};
use crate::{OperationKind, ResourceKind};
pub fn update(msg: Msg, model: &mut crate::model::Model, orders: &mut impl Orders<Msg>) {
if model.user.is_none() {
return;
@ -32,8 +31,7 @@ pub fn update(msg: Msg, model: &mut crate::model::Model, orders: &mut impl Order
};
match msg {
Msg::WebSocketChange(WebSocketChanged::WsMsg(WsMsg::AuthorizeLoaded(..)))
| Msg::UserChanged(..)
Msg::UserChanged(..)
| Msg::ProjectChanged(Some(..))
| Msg::ChangePage(Page::Project)
| Msg::ChangePage(Page::AddIssue)

View File

@ -236,21 +236,6 @@ fn project_issue(model: &Model, issue: &Issue) -> Node<Msg> {
.into_node()
})
.collect();
// let avatars: Vec<Node<Msg>> = model
// .users
// .iter()
// .enumerate()
// .filter(|(_, user)| issue.user_ids.contains(&user.id))
// .map(|(idx, user)| {
// StyledAvatar::build()
// .size(24)
// .name(user.name.as_str())
// .avatar_url(user.avatar_url.as_deref().unwrap_or_default())
// .user_index(idx)
// .build()
// .into_node()
// })
// .collect();
let issue_type_icon = StyledIcon::build(issue.issue_type.clone().into())
.with_color(issue.issue_type.to_str())

View File

@ -1,6 +1,4 @@
pub use model::*;
pub use update::*;
pub use view::*;
pub use {model::*, update::*, view::*};
mod model;
mod update;

View File

@ -1,11 +1,12 @@
use jirs_data::{IssueStatusId, Project, ProjectFieldId, UpdateProjectPayload};
use crate::{
use {
crate::{
shared::{
drag::DragState, styled_checkbox::StyledCheckboxState, styled_input::StyledInputState,
styled_select::StyledSelectState,
},
FieldId,
},
jirs_data::{IssueStatusId, Project, ProjectFieldId, UpdateProjectPayload},
};
#[derive(Debug)]
@ -18,7 +19,6 @@ pub struct ProjectSettingsPage {
pub edit_column_id: Option<IssueStatusId>,
pub creating_issue_status: bool,
pub name: StyledInputState,
// pub description_rte: StyledRteState,
}
impl ProjectSettingsPage {
@ -58,9 +58,6 @@ impl ProjectSettingsPage {
FieldId::ProjectSettings(ProjectFieldId::IssueStatusName),
"",
),
// description_rte: StyledRteState::new(FieldId::ProjectSettings(
// ProjectFieldId::Description,
// )),
}
}

View File

@ -1,6 +1,7 @@
use {
crate::{
model::{Model, Page, PageContent},
pages::project_settings_page::ProjectSettingsPage,
shared::styled_select::StyledSelectChanged,
ws::{board_load, send_ws_msg},
FieldChange::TabChanged,
@ -11,8 +12,6 @@ use {
std::collections::HashSet,
};
use crate::pages::project_settings_page::ProjectSettingsPage;
pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
if model.page != Page::ProjectSettings {
return;

View File

@ -1,10 +1,5 @@
use std::collections::HashMap;
use seed::{prelude::*, *};
use jirs_data::{IssueStatus, ProjectCategory, TimeTracking, ToVec};
use crate::{
use {
crate::{
modals::issue_statuses_delete::Model as DeleteIssueStatusModal,
model::{self, ModalType, Model, PageContent},
pages::project_settings_page::ProjectSettingsPage,
@ -22,6 +17,10 @@ use crate::{
ToChild, ToNode,
},
FieldId, Msg, PageChanged, ProjectFieldId, ProjectPageChange,
},
jirs_data::{IssueStatus, ProjectCategory, TimeTracking, ToVec},
seed::{prelude::*, *},
std::collections::HashMap,
};
// use crate::shared::styled_rte::StyledRte;
@ -225,6 +224,7 @@ fn columns_section(model: &Model, page: &ProjectSettingsPage) -> Node<Msg> {
.into_node()
}
#[inline]
fn add_column(page: &ProjectSettingsPage, column_style: &str) -> Node<Msg> {
let on_click = mouse_ev(Ev::Click, move |_| {
Msg::PageChanged(PageChanged::ProjectSettings(
@ -268,6 +268,7 @@ fn add_column(page: &ProjectSettingsPage, column_style: &str) -> Node<Msg> {
}
}
#[inline]
fn column_preview(
is: &IssueStatus,
page: &ProjectSettingsPage,

View File

@ -1,5 +1,4 @@
pub use update::*;
pub use view::*;
pub use {model::*, update::*, view::*};
pub mod model;
pub mod update;

View File

@ -1,13 +1,13 @@
use seed::prelude::*;
use jirs_data::WsMsg;
use crate::pages::reports_page::model::ReportsPage;
use crate::{
use {
crate::{
changes::{PageChanged, ReportsPageChange},
model::{Model, Page, PageContent},
pages::reports_page::model::ReportsPage,
ws::board_load,
Msg, WebSocketChanged,
},
jirs_data::WsMsg,
seed::prelude::*,
};
pub fn update(msg: Msg, model: &mut crate::model::Model, orders: &mut impl Orders<Msg>) {

View File

@ -1,15 +1,14 @@
use std::collections::HashMap;
use chrono::Datelike;
use seed::{prelude::*, *};
use jirs_data::Issue;
use crate::pages::reports_page::model::ReportsPage;
use crate::{
use {
crate::{
model::{Model, PageContent},
pages::reports_page::model::ReportsPage,
shared::{inner_layout, styled_icon::StyledIcon, ToNode},
Msg, PageChanged, ReportsPageChange,
},
chrono::Datelike,
jirs_data::Issue,
seed::{prelude::*, *},
std::collections::HashMap,
};
const SVG_MARGIN_X: u32 = 10;

View File

@ -1,5 +1,4 @@
pub use update::*;
pub use view::*;
pub use {model::*, update::*, view::*};
pub mod model;
pub mod update;

View File

@ -1,16 +1,15 @@
use std::str::FromStr;
use seed::{prelude::*, *};
use uuid::Uuid;
use jirs_data::{SignInFieldId, WsMsg};
use crate::pages::sign_in_page::model::SignInPage;
use crate::{
use {
crate::{
model::{self, Model, Page, PageContent},
pages::sign_in_page::model::SignInPage,
shared::write_auth_token,
ws::send_ws_msg,
FieldId, Msg, WebSocketChanged,
},
jirs_data::{SignInFieldId, WsMsg},
seed::{prelude::*, *},
std::str::FromStr,
uuid::Uuid,
};
pub fn update(msg: Msg, model: &mut model::Model, orders: &mut impl Orders<Msg>) {

View File

@ -1,6 +1,5 @@
use seed::{prelude::*, *};
use crate::{
use {
crate::{
model::{self, PageContent},
shared::{
outer_layout,
@ -14,6 +13,8 @@ use crate::{
},
validations::{is_email, is_token},
FieldId, Msg, SignInFieldId,
},
seed::{prelude::*, *},
};
pub fn view(model: &model::Model) -> Node<Msg> {

View File

@ -1,5 +1,4 @@
pub use update::*;
pub use view::*;
pub use {model::*, update::*, view::*};
pub mod model;
pub mod update;

View File

@ -1,12 +1,12 @@
use seed::prelude::*;
use jirs_data::{SignUpFieldId, WsMsg};
use crate::pages::sign_up_page::model::SignUpPage;
use crate::{
use {
crate::{
model::{self, Model, Page, PageContent},
pages::sign_up_page::model::SignUpPage,
ws::send_ws_msg,
FieldId, Msg, WebSocketChanged,
},
jirs_data::{SignUpFieldId, WsMsg},
seed::prelude::*,
};
pub fn update(msg: Msg, model: &mut model::Model, orders: &mut impl Orders<Msg>) {

View File

@ -1,8 +1,5 @@
use seed::{prelude::*, *};
use jirs_data::SignUpFieldId;
use crate::{
use {
crate::{
model::{self, PageContent},
shared::{
outer_layout,
@ -16,6 +13,9 @@ use crate::{
},
validations::is_email,
FieldId, Msg,
},
jirs_data::SignUpFieldId,
seed::{prelude::*, *},
};
pub fn view(model: &model::Model) -> Node<Msg> {

View File

@ -1,5 +1,4 @@
pub use update::*;
pub use view::*;
pub use {model::*, update::*, view::*};
pub mod model;
pub mod update;

View File

@ -1,8 +1,7 @@
use jirs_data::{Invitation, User, UserRole, UsersFieldId};
use crate::model::InvitationFormState;
use crate::shared::styled_select::StyledSelectState;
use crate::FieldId;
use {
crate::{model::InvitationFormState, shared::styled_select::StyledSelectState, FieldId},
jirs_data::{Invitation, User, UserRole, UsersFieldId},
};
#[derive(Debug)]
pub struct UsersPage {

View File

@ -1,13 +1,13 @@
use seed::prelude::Orders;
use jirs_data::{InvitationState, UserRole, UsersFieldId, WsMsg};
use crate::pages::users_page::model::UsersPage;
use crate::{
use {
crate::{
model::{InvitationFormState, Model, Page, PageContent},
pages::users_page::model::UsersPage,
shared::styled_select::StyledSelectChanged,
ws::{invitation_load, send_ws_msg},
FieldId, Msg, PageChanged, UsersPageChange, WebSocketChanged,
},
jirs_data::{InvitationState, UserRole, UsersFieldId, WsMsg},
seed::prelude::Orders,
};
pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {

View File

@ -1,16 +1,16 @@
use seed::{prelude::*, *};
use jirs_data::{InvitationState, ToVec, UserRole, UsersFieldId};
use crate::{
use {
crate::{
model::{InvitationFormState, Model, PageContent},
shared::{
inner_layout, styled_button::StyledButton, styled_field::StyledField,
styled_form::StyledForm, styled_input::StyledInput, styled_select::StyledSelect, ToChild,
ToNode,
styled_form::StyledForm, styled_input::StyledInput, styled_select::StyledSelect,
ToChild, ToNode,
},
validations::is_email,
FieldId, Msg, PageChanged, UsersPageChange,
},
jirs_data::{InvitationState, ToVec, UserRole, UsersFieldId},
seed::{prelude::*, *},
};
pub fn view(model: &Model) -> Node<Msg> {

View File

@ -1,10 +1,10 @@
use seed::{prelude::*, *};
use jirs_data::*;
use crate::{
use {
crate::{
model::{Model, Page},
resolve_page, Msg,
},
jirs_data::*,
seed::{prelude::*, *},
};
pub mod aside;
@ -65,10 +65,12 @@ pub trait ToNode {
fn into_node(self) -> Node<Msg>;
}
#[inline]
pub fn divider() -> Node<Msg> {
div![C!["divider"], ""]
}
#[inline]
pub fn inner_layout(model: &Model, page_name: &str, children: Vec<Node<Msg>>) -> Node<Msg> {
let modal_node = crate::modal::view(model);
article![
@ -81,6 +83,7 @@ pub fn inner_layout(model: &Model, page_name: &str, children: Vec<Node<Msg>>) ->
]
}
#[inline]
pub fn outer_layout(model: &Model, page_name: &str, children: Vec<Node<Msg>>) -> Node<Msg> {
let modal = crate::modal::view(model);
article![

View File

@ -1,8 +1,5 @@
use seed::{prelude::*, *};
use jirs_data::{InvitationToken, Message, MessageType, WsMsg};
use crate::{
use {
crate::{
model::Model,
shared::{
divider,
@ -13,6 +10,9 @@ use crate::{
},
ws::send_ws_msg,
Msg, Page,
},
jirs_data::{InvitationToken, Message, MessageType, WsMsg},
seed::{prelude::*, *},
};
trait IntoNavItemIcon {
@ -45,7 +45,6 @@ pub fn render(model: &Model) -> Vec<Node<Msg>> {
let logo_svg = img![
attrs![At::Src => "/logo2.svg"; At::Style => "background: rgba(244,244,244,.8); border-radius: 24px;"]
];
// let logo_svg = Node::from_html(include_str!("../../static/logo.svg"));
let user_icon = match model.user.as_ref() {
Some(user) => i![

View File

@ -38,6 +38,7 @@ pub struct StyledEditor {
}
impl StyledEditor {
#[inline]
pub fn build(id: FieldId) -> StyledEditorBuilder {
StyledEditorBuilder {
id,
@ -61,6 +62,7 @@ pub struct StyledEditorBuilder {
}
impl StyledEditorBuilder {
#[inline]
pub fn text<S>(mut self, text: S) -> Self
where
S: Into<String>,
@ -69,6 +71,7 @@ impl StyledEditorBuilder {
self
}
#[inline]
pub fn initial_text<S>(mut self, text: S) -> Self
where
S: Into<String>,
@ -77,6 +80,7 @@ impl StyledEditorBuilder {
self
}
#[inline]
pub fn html<S>(mut self, text: S) -> Self
where
S: Into<String>,
@ -85,11 +89,13 @@ impl StyledEditorBuilder {
self
}
#[inline]
pub fn mode(mut self, mode: Mode) -> Self {
self.mode = mode;
self
}
#[inline]
pub fn build(self) -> StyledEditor {
StyledEditor {
id: self.id,
@ -101,6 +107,7 @@ impl StyledEditorBuilder {
}
}
#[inline]
pub fn update_on(mut self, ev: Ev) -> Self {
self.update_event = Some(ev);
self
@ -108,11 +115,13 @@ impl StyledEditorBuilder {
}
impl ToNode for StyledEditor {
#[inline]
fn into_node(self) -> Node<Msg> {
render(self)
}
}
#[inline]
pub fn render(values: StyledEditor) -> Node<Msg> {
let StyledEditor {
id,

View File

@ -1,7 +1,7 @@
use seed::{prelude::*, *};
use crate::shared::ToNode;
use crate::Msg;
use {
crate::{shared::ToNode, Msg},
seed::{prelude::*, *},
};
#[derive(Debug, Clone)]
pub struct StyledForm<'l> {
@ -11,12 +11,14 @@ pub struct StyledForm<'l> {
}
impl<'l> StyledForm<'l> {
#[inline]
pub fn build() -> StyledFormBuilder<'l> {
StyledFormBuilder::default()
}
}
impl<'l> ToNode for StyledForm<'l> {
#[inline]
fn into_node(self) -> Node<Msg> {
render(self)
}
@ -30,11 +32,13 @@ pub struct StyledFormBuilder<'l> {
}
impl<'l> StyledFormBuilder<'l> {
#[inline]
pub fn add_field(mut self, node: Node<Msg>) -> Self {
self.fields.push(node);
self
}
#[inline]
pub fn try_field(mut self, node: Option<Node<Msg>>) -> Self {
if let Some(n) = node {
self.fields.push(n);
@ -42,16 +46,19 @@ impl<'l> StyledFormBuilder<'l> {
self
}
#[inline]
pub fn heading(mut self, heading: &'l str) -> Self {
self.heading = heading;
self
}
#[inline]
pub fn on_submit(mut self, on_submit: EventHandler<Msg>) -> Self {
self.on_submit = Some(on_submit);
self
}
#[inline]
pub fn build(self) -> StyledForm<'l> {
StyledForm {
heading: self.heading,
@ -61,6 +68,7 @@ impl<'l> StyledFormBuilder<'l> {
}
}
#[inline]
pub fn render(values: StyledForm) -> Node<Msg> {
let StyledForm {
heading,
@ -73,7 +81,7 @@ pub fn render(values: StyledForm) -> Node<Msg> {
};
seed::form![
handlers,
attrs![At::Class => "styledForm"],
C!["styledForm"],
div![C!["formElement"], div![C!["formHeading"], heading], fields],
]
}

View File

@ -11,6 +11,7 @@ pub enum Variant {
}
impl Variant {
#[inline]
pub fn to_str<'l>(&self) -> &'l str {
match self {
Variant::Normal => "normal",
@ -20,6 +21,7 @@ impl Variant {
}
impl ToString for Variant {
#[inline]
fn to_string(&self) -> String {
self.to_str().to_string()
}
@ -33,6 +35,7 @@ pub struct StyledInputState {
}
impl StyledInputState {
#[inline]
pub fn new<S>(id: FieldId, value: S) -> Self
where
S: Into<String>,
@ -44,18 +47,22 @@ impl StyledInputState {
}
}
#[inline]
pub fn to_i32(&self) -> Option<i32> {
self.value.parse::<i32>().ok()
}
#[inline]
pub fn to_f64(&self) -> Option<f64> {
self.value.parse::<f64>().ok()
}
#[inline]
pub fn represent_f64_as_i32(&self) -> Option<i32> {
self.to_f64().map(|f| (f * 10.0f64) as i32)
}
#[inline]
pub fn update(&mut self, msg: &Msg) {
match msg {
Msg::StrInputChanged(field_id, s) if field_id == &self.id => {
@ -66,6 +73,7 @@ impl StyledInputState {
}
}
#[inline]
pub fn reset(&mut self) {
self.value.clear();
}
@ -86,6 +94,7 @@ pub struct StyledInput<'l> {
}
impl<'l> StyledInput<'l> {
#[inline]
pub fn build() -> StyledInputBuilder<'l> {
StyledInputBuilder {
icon: None,
@ -115,16 +124,19 @@ pub struct StyledInputBuilder<'l> {
}
impl<'l> StyledInputBuilder<'l> {
#[inline]
pub fn icon(mut self, icon: Icon) -> Self {
self.icon = Some(icon);
self
}
#[inline]
pub fn valid(mut self, valid: bool) -> Self {
self.valid = Some(valid);
self
}
#[inline]
pub fn value<S>(mut self, v: S) -> Self
where
S: Into<String>,
@ -133,36 +145,43 @@ impl<'l> StyledInputBuilder<'l> {
self
}
#[inline]
pub fn state(self, state: &StyledInputState) -> Self {
self.value(state.value.as_str())
.valid(!state.touched || !state.value.is_empty())
}
#[inline]
pub fn add_input_class(mut self, name: &'l str) -> Self {
self.input_class_list.push(name);
self
}
#[inline]
pub fn add_wrapper_class(mut self, name: &'l str) -> Self {
self.wrapper_class_list.push(name);
self
}
#[inline]
pub fn primary(mut self) -> Self {
self.variant = Variant::Primary;
self
}
#[inline]
pub fn auto_focus(mut self) -> Self {
self.auto_focus = true;
self
}
#[inline]
pub fn on_input_ev(mut self, handler: EventHandler<Msg>) -> Self {
self.input_handlers.push(handler);
self
}
#[inline]
pub fn build(self, id: FieldId) -> StyledInput<'l> {
StyledInput {
id,
@ -180,6 +199,7 @@ impl<'l> StyledInputBuilder<'l> {
}
impl<'l> ToNode for StyledInput<'l> {
#[inline]
fn into_node(self) -> Node<Msg> {
render(self)
}
@ -209,10 +229,10 @@ pub fn render(values: StyledInput) -> Node<Msg> {
input_class_list.push("withIcon");
}
let icon = match icon {
Some(icon) => StyledIcon::build(icon).build().into_node(),
_ => empty![],
};
let icon = icon
.map(|icon| StyledIcon::build(icon).build().into_node())
.unwrap_or(Node::Empty);
let on_input = {
let field_id = id.clone();
ev(Ev::Input, move |event| {

View File

@ -1,7 +1,6 @@
use {
crate::{
modal::time_tracking::value_for_time_tracking,
modals::issues_edit::Model as EditIssueModal,
modals::{issues_edit::Model as EditIssueModal, time_tracking::value_for_time_tracking},
model::{ModalType, Model},
shared::{
styled_icon::{Icon, StyledIcon},

View File

@ -1,6 +1,7 @@
use actix_web::HttpResponse;
use jirs_data::{msg::WsError, ErrorResponse};
use {
actix_web::HttpResponse,
jirs_data::{msg::WsError, ErrorResponse},
};
const TOKEN_NOT_FOUND: &str = "Token not found";
const DATABASE_CONNECTION_FAILED: &str = "Database connection failed";

View File

@ -1,5 +1,7 @@
use rusoto_signature::Region;
use serde::{Deserialize, Serialize};
use {
rusoto_signature::Region,
serde::{Deserialize, Serialize},
};
#[derive(Serialize, Deserialize, Debug)]
pub struct Configuration {

View File

@ -1,7 +1,7 @@
use std::fs::{read_to_string, write};
use serde::export::PhantomData;
use serde::{de::DeserializeOwned, Serialize};
use {
serde::{de::DeserializeOwned, export::PhantomData, Serialize},
std::fs::{read_to_string, write},
};
pub struct Reader<T: DeserializeOwned + Default + Serialize> {
__phantom: PhantomData<T>,

View File

@ -1,17 +1,16 @@
use std::cmp::Ordering;
use std::str::FromStr;
use chrono::NaiveDateTime;
#[cfg(feature = "backend")]
use diesel::*;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
pub use fields::*;
pub use msg::WsMsg;
pub use payloads::*;
#[cfg(feature = "backend")]
pub use sql::*;
use {
chrono::NaiveDateTime,
serde::{Deserialize, Serialize},
std::cmp::Ordering,
std::str::FromStr,
uuid::Uuid,
};
pub use {fields::*, msg::WsMsg, payloads::*};
pub mod fields;
pub mod msg;

View File

@ -1,8 +1,9 @@
use serde::{Deserialize, Serialize};
use crate::{
CommentId, EpicId, Issue, IssueId, IssuePriority, IssueStatusId, IssueType, ProjectCategory,
ProjectId, TimeTracking, UserId,
use {
crate::{
CommentId, EpicId, Issue, IssueId, IssuePriority, IssueStatusId, IssueType,
ProjectCategory, ProjectId, TimeTracking, UserId,
},
serde::{Deserialize, Serialize},
};
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]

View File

@ -1,9 +1,10 @@
use std::io::Write;
use diesel::{deserialize::*, pg::*, serialize::*, *};
use crate::{
InvitationState, IssuePriority, IssueType, MessageType, ProjectCategory, TimeTracking, UserRole,
use {
crate::{
InvitationState, IssuePriority, IssueType, MessageType, ProjectCategory, TimeTracking,
UserRole,
},
diesel::{deserialize::*, pg::*, serialize::*, *},
std::io::Write,
};
#[derive(SqlType)]