Better fmt, remove select builder
This commit is contained in:
parent
e6ef4d6b0e
commit
2b40f9fd91
@ -1,7 +1,5 @@
|
||||
use {
|
||||
actix,
|
||||
rusoto_s3::{PutObjectRequest, S3Client, S3},
|
||||
};
|
||||
use actix;
|
||||
use rusoto_s3::{PutObjectRequest, S3Client, S3};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AmazonError {
|
||||
|
@ -1,8 +1,8 @@
|
||||
use {
|
||||
crate::{db_find, tokens::FindAccessToken},
|
||||
diesel::prelude::*,
|
||||
jirs_data::User,
|
||||
};
|
||||
use diesel::prelude::*;
|
||||
use jirs_data::User;
|
||||
|
||||
use crate::db_find;
|
||||
use crate::tokens::FindAccessToken;
|
||||
|
||||
db_find! {
|
||||
AuthorizeUser,
|
||||
|
@ -1,8 +1,7 @@
|
||||
use {
|
||||
crate::{db_create, db_delete, db_load, db_update},
|
||||
diesel::prelude::*,
|
||||
jirs_data::{Comment, CommentId, IssueId, UserId},
|
||||
};
|
||||
use diesel::prelude::*;
|
||||
use jirs_data::{Comment, CommentId, IssueId, UserId};
|
||||
|
||||
use crate::{db_create, db_delete, db_load, db_update};
|
||||
|
||||
db_load! {
|
||||
LoadIssueComments,
|
||||
|
@ -1,9 +1,8 @@
|
||||
use {
|
||||
crate::{db_create, db_delete, db_load, db_update},
|
||||
derive_db_execute::Execute,
|
||||
diesel::prelude::*,
|
||||
jirs_data::{DescriptionString, Epic, EpicId, ProjectId},
|
||||
};
|
||||
use derive_db_execute::Execute;
|
||||
use diesel::prelude::*;
|
||||
use jirs_data::{DescriptionString, Epic, EpicId, ProjectId};
|
||||
|
||||
use crate::{db_create, db_delete, db_load, db_update};
|
||||
|
||||
#[derive(Execute)]
|
||||
#[db_exec(schema = "epics", result = "Epic", find = "epics.find(msg.epic_id)")]
|
||||
|
@ -1,16 +1,15 @@
|
||||
use {
|
||||
crate::{
|
||||
db_create, db_delete, db_find, db_load, db_pool, db_update,
|
||||
tokens::CreateBindToken,
|
||||
users::{LookupUser, Register},
|
||||
DbExecutor, DbPooledConn, InvitationError,
|
||||
},
|
||||
actix::{Handler, Message},
|
||||
diesel::prelude::*,
|
||||
jirs_data::{
|
||||
EmailString, Invitation, InvitationId, InvitationState, InvitationToken, ProjectId, Token,
|
||||
User, UserId, UserRole, UsernameString,
|
||||
},
|
||||
use actix::{Handler, Message};
|
||||
use diesel::prelude::*;
|
||||
use jirs_data::{
|
||||
EmailString, Invitation, InvitationId, InvitationState, InvitationToken, ProjectId, Token,
|
||||
User, UserId, UserRole, UsernameString,
|
||||
};
|
||||
|
||||
use crate::tokens::CreateBindToken;
|
||||
use crate::users::{LookupUser, Register};
|
||||
use crate::{
|
||||
db_create, db_delete, db_find, db_load, db_pool, db_update, DbExecutor, DbPooledConn,
|
||||
InvitationError,
|
||||
};
|
||||
|
||||
db_find! {
|
||||
|
@ -1,8 +1,8 @@
|
||||
use {
|
||||
crate::{db_create, db_delete, db_load, db_load_field},
|
||||
diesel::{expression::dsl::not, prelude::*},
|
||||
jirs_data::{IssueAssignee, IssueId, UserId},
|
||||
};
|
||||
use diesel::expression::dsl::not;
|
||||
use diesel::prelude::*;
|
||||
use jirs_data::{IssueAssignee, IssueId, UserId};
|
||||
|
||||
use crate::{db_create, db_delete, db_load, db_load_field};
|
||||
|
||||
db_create! {
|
||||
AsignMultiple,
|
||||
|
@ -1,8 +1,7 @@
|
||||
use {
|
||||
crate::{db_create, db_delete, db_load, db_update},
|
||||
diesel::prelude::*,
|
||||
jirs_data::{IssueStatus, IssueStatusId, Position, ProjectId, TitleString},
|
||||
};
|
||||
use diesel::prelude::*;
|
||||
use jirs_data::{IssueStatus, IssueStatusId, Position, ProjectId, TitleString};
|
||||
|
||||
use crate::{db_create, db_delete, db_load, db_update};
|
||||
|
||||
db_load! {
|
||||
LoadIssueStatuses,
|
||||
|
@ -1,9 +1,9 @@
|
||||
use {
|
||||
crate::models::Issue,
|
||||
derive_db_execute::Execute,
|
||||
diesel::{expression::sql_literal::sql, prelude::*},
|
||||
jirs_data::{IssueId, IssuePriority, IssueStatusId, IssueType, ProjectId, UserId},
|
||||
};
|
||||
use derive_db_execute::Execute;
|
||||
use diesel::expression::sql_literal::sql;
|
||||
use diesel::prelude::*;
|
||||
use jirs_data::{IssueId, IssuePriority, IssueStatusId, IssueType, ProjectId, UserId};
|
||||
|
||||
use crate::models::Issue;
|
||||
|
||||
#[derive(Default, Execute)]
|
||||
#[db_exec(
|
||||
@ -112,12 +112,11 @@ pub struct DeleteIssue {
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use {
|
||||
crate::models::Issue,
|
||||
derive_db_execute::Execute,
|
||||
diesel::prelude::*,
|
||||
jirs_data::{IssuePriority, IssueStatusId, IssueType},
|
||||
};
|
||||
use derive_db_execute::Execute;
|
||||
use diesel::prelude::*;
|
||||
use jirs_data::{IssuePriority, IssueStatusId, IssueType};
|
||||
|
||||
use crate::models::Issue;
|
||||
|
||||
#[derive(Default, Execute)]
|
||||
#[db_exec(
|
||||
|
@ -3,12 +3,10 @@
|
||||
#[macro_use]
|
||||
extern crate diesel;
|
||||
|
||||
use actix::{Actor, SyncContext};
|
||||
use diesel::pg::PgConnection;
|
||||
use diesel::r2d2::{self, ConnectionManager};
|
||||
pub use errors::*;
|
||||
use {
|
||||
actix::{Actor, SyncContext},
|
||||
diesel::pg::PgConnection,
|
||||
diesel::r2d2::{self, ConnectionManager},
|
||||
};
|
||||
|
||||
pub mod authorize_user;
|
||||
pub mod comments;
|
||||
@ -72,7 +70,8 @@ pub struct Guard<'l> {
|
||||
|
||||
impl<'l> Guard<'l> {
|
||||
pub fn new(conn: &'l DbPooledConn) -> Result<Self, crate::DatabaseError> {
|
||||
use diesel::{connection::TransactionManager, prelude::*};
|
||||
use diesel::connection::TransactionManager;
|
||||
use diesel::prelude::*;
|
||||
let tm = conn.transaction_manager();
|
||||
tm.begin_transaction(conn).map_err(|e| {
|
||||
log::error!("{:?}", e);
|
||||
|
@ -1,11 +1,8 @@
|
||||
use {
|
||||
crate::{
|
||||
db_create, db_delete, db_load,
|
||||
users::{FindUser, LookupUser},
|
||||
},
|
||||
diesel::prelude::*,
|
||||
jirs_data::{BindToken, Message, MessageId, MessageType, User, UserId},
|
||||
};
|
||||
use diesel::prelude::*;
|
||||
use jirs_data::{BindToken, Message, MessageId, MessageType, User, UserId};
|
||||
|
||||
use crate::users::{FindUser, LookupUser};
|
||||
use crate::{db_create, db_delete, db_load};
|
||||
|
||||
db_load! {
|
||||
LoadMessages,
|
||||
|
@ -1,13 +1,12 @@
|
||||
use {
|
||||
crate::schema::*,
|
||||
chrono::NaiveDateTime,
|
||||
jirs_data::{
|
||||
EpicId, InvitationState, IssuePriority, IssueStatusId, IssueType, ProjectCategory,
|
||||
ProjectId, TimeTracking, UserId,
|
||||
},
|
||||
serde::{Deserialize, Serialize},
|
||||
uuid::Uuid,
|
||||
use chrono::NaiveDateTime;
|
||||
use jirs_data::{
|
||||
EpicId, InvitationState, IssuePriority, IssueStatusId, IssueType, ProjectCategory, ProjectId,
|
||||
TimeTracking, UserId,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::schema::*;
|
||||
|
||||
#[derive(Serialize, Debug, Deserialize, Queryable)]
|
||||
pub struct Issue {
|
||||
|
@ -1,8 +1,7 @@
|
||||
use {
|
||||
crate::{db_create, db_find, db_load, db_update},
|
||||
diesel::prelude::*,
|
||||
jirs_data::{NameString, Project, ProjectCategory, ProjectId, TimeTracking, UserId},
|
||||
};
|
||||
use diesel::prelude::*;
|
||||
use jirs_data::{NameString, Project, ProjectCategory, ProjectId, TimeTracking, UserId};
|
||||
|
||||
use crate::{db_create, db_find, db_load, db_update};
|
||||
|
||||
db_find! {
|
||||
LoadCurrentProject,
|
||||
@ -12,11 +11,10 @@ db_find! {
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use {
|
||||
crate::db_create,
|
||||
diesel::prelude::*,
|
||||
jirs_data::{NameString, Project, ProjectCategory, TimeTracking},
|
||||
};
|
||||
use diesel::prelude::*;
|
||||
use jirs_data::{NameString, Project, ProjectCategory, TimeTracking};
|
||||
|
||||
use crate::db_create;
|
||||
|
||||
db_create! {
|
||||
CreateProject,
|
||||
|
@ -1,8 +1,7 @@
|
||||
use {
|
||||
crate::{db_create, db_find, db_update},
|
||||
diesel::prelude::*,
|
||||
jirs_data::{Token, UserId},
|
||||
};
|
||||
use diesel::prelude::*;
|
||||
use jirs_data::{Token, UserId};
|
||||
|
||||
use crate::{db_create, db_find, db_update};
|
||||
|
||||
db_find! {
|
||||
FindUserId,
|
||||
|
@ -1,8 +1,7 @@
|
||||
use {
|
||||
crate::{db_create, db_delete, db_find, db_load, db_update},
|
||||
diesel::prelude::*,
|
||||
jirs_data::{ProjectId, UserId, UserProject, UserProjectId, UserRole},
|
||||
};
|
||||
use diesel::prelude::*;
|
||||
use jirs_data::{ProjectId, UserId, UserProject, UserProjectId, UserRole};
|
||||
|
||||
use crate::{db_create, db_delete, db_find, db_load, db_update};
|
||||
|
||||
db_find! {
|
||||
CurrentUserProject,
|
||||
@ -27,11 +26,10 @@ db_load! {
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use {
|
||||
crate::db_update,
|
||||
diesel::prelude::*,
|
||||
jirs_data::{UserId, UserProject, UserProjectId},
|
||||
};
|
||||
use diesel::prelude::*;
|
||||
use jirs_data::{UserId, UserProject, UserProjectId};
|
||||
|
||||
use crate::db_update;
|
||||
|
||||
db_update! {
|
||||
ChangeProjectIsCurrent,
|
||||
|
@ -1,11 +1,9 @@
|
||||
use {
|
||||
crate::{
|
||||
db_create, db_find, db_load, db_update, projects::CreateProject, q,
|
||||
user_projects::CreateUserProject, DbPooledConn,
|
||||
},
|
||||
diesel::prelude::*,
|
||||
jirs_data::{EmailString, IssueId, ProjectId, User, UserId, UserRole, UsernameString},
|
||||
};
|
||||
use diesel::prelude::*;
|
||||
use jirs_data::{EmailString, IssueId, ProjectId, User, UserId, UserRole, UsernameString};
|
||||
|
||||
use crate::projects::CreateProject;
|
||||
use crate::user_projects::CreateUserProject;
|
||||
use crate::{db_create, db_find, db_load, db_update, q, DbPooledConn};
|
||||
|
||||
db_find! {
|
||||
FindUser,
|
||||
@ -156,12 +154,10 @@ db_update! {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use diesel::connection::TransactionManager;
|
||||
|
||||
use jirs_data::{Project, ProjectCategory};
|
||||
|
||||
use crate::build_pool;
|
||||
|
||||
use super::*;
|
||||
use crate::build_pool;
|
||||
|
||||
#[test]
|
||||
fn check_collision() {
|
||||
|
@ -1,9 +1,9 @@
|
||||
use {
|
||||
actix::SyncContext,
|
||||
actix_files::{self, Files},
|
||||
jirs_config::fs::Configuration,
|
||||
std::{io::Write, path::PathBuf},
|
||||
};
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use actix::SyncContext;
|
||||
use actix_files::{self, Files};
|
||||
use jirs_config::fs::Configuration;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum FsError {
|
||||
|
@ -1,14 +1,11 @@
|
||||
use {
|
||||
actix::{Actor, Handler, SyncContext},
|
||||
jirs_data::HighlightedCode,
|
||||
simsearch::SimSearch,
|
||||
std::sync::Arc,
|
||||
syntect::{
|
||||
easy::HighlightLines,
|
||||
highlighting::{Style, ThemeSet},
|
||||
parsing::SyntaxSet,
|
||||
},
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
use actix::{Actor, Handler, SyncContext};
|
||||
use jirs_data::HighlightedCode;
|
||||
use simsearch::SimSearch;
|
||||
use syntect::easy::HighlightLines;
|
||||
use syntect::highlighting::{Style, ThemeSet};
|
||||
use syntect::parsing::SyntaxSet;
|
||||
|
||||
mod load;
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
use {
|
||||
bincode::{deserialize_from, Result},
|
||||
flate2::bufread::ZlibDecoder,
|
||||
serde::de::DeserializeOwned,
|
||||
std::io::BufRead,
|
||||
};
|
||||
use std::io::BufRead;
|
||||
|
||||
use bincode::{deserialize_from, Result};
|
||||
use flate2::bufread::ZlibDecoder;
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
fn from_reader<T: DeserializeOwned, R: BufRead>(input: R) -> Result<T> {
|
||||
let mut decoder = ZlibDecoder::new(input);
|
||||
|
@ -1,8 +1,7 @@
|
||||
use {
|
||||
crate::MailExecutor,
|
||||
actix::{Handler, Message},
|
||||
uuid::Uuid,
|
||||
};
|
||||
use actix::{Handler, Message};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::MailExecutor;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Invite {
|
||||
|
@ -1,8 +1,7 @@
|
||||
use {
|
||||
crate::MailExecutor,
|
||||
actix::{Handler, Message},
|
||||
uuid::Uuid,
|
||||
};
|
||||
use actix::{Handler, Message};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::MailExecutor;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Welcome {
|
||||
|
@ -1,19 +1,21 @@
|
||||
use std::io::Write;
|
||||
|
||||
use actix::Addr;
|
||||
use actix_multipart::{Field, Multipart};
|
||||
use actix_web::http::header::ContentDisposition;
|
||||
use actix_web::web::Data;
|
||||
use actix_web::{post, web, Error, HttpResponse};
|
||||
use database_actor::authorize_user::AuthorizeUser;
|
||||
use database_actor::user_projects::CurrentUserProject;
|
||||
use database_actor::users::UpdateAvatarUrl;
|
||||
use database_actor::DbExecutor;
|
||||
#[cfg(feature = "local-storage")]
|
||||
use filesystem_actor;
|
||||
use {
|
||||
actix::Addr,
|
||||
actix_multipart::{Field, Multipart},
|
||||
actix_web::{http::header::ContentDisposition, post, web, web::Data, Error, HttpResponse},
|
||||
database_actor::{
|
||||
authorize_user::AuthorizeUser, user_projects::CurrentUserProject, users::UpdateAvatarUrl,
|
||||
DbExecutor,
|
||||
},
|
||||
futures::{executor::block_on, StreamExt, TryStreamExt},
|
||||
jirs_data::{User, UserId, WsMsg},
|
||||
websocket_actor::server::{InnerMsg::BroadcastToChannel, WsServer},
|
||||
};
|
||||
use futures::executor::block_on;
|
||||
use futures::{StreamExt, TryStreamExt};
|
||||
use jirs_data::{User, UserId, WsMsg};
|
||||
use websocket_actor::server::InnerMsg::BroadcastToChannel;
|
||||
use websocket_actor::server::WsServer;
|
||||
|
||||
#[post("/")]
|
||||
pub async fn upload(
|
||||
|
@ -1,6 +1,6 @@
|
||||
use actix_web::HttpResponse;
|
||||
|
||||
use jirs_data::{msg::WsError, ErrorResponse};
|
||||
use jirs_data::msg::WsError;
|
||||
use jirs_data::ErrorResponse;
|
||||
|
||||
const TOKEN_NOT_FOUND: &str = "Token not found";
|
||||
const DATABASE_CONNECTION_FAILED: &str = "Database connection failed";
|
||||
|
@ -1,11 +1,11 @@
|
||||
use {
|
||||
actix::Addr,
|
||||
actix_multipart::Field,
|
||||
actix_web::{http::header::ContentDisposition, web::Data, Error},
|
||||
futures::StreamExt,
|
||||
jirs_data::UserId,
|
||||
tokio::sync::broadcast::{Receiver, Sender},
|
||||
};
|
||||
use actix::Addr;
|
||||
use actix_multipart::Field;
|
||||
use actix_web::http::header::ContentDisposition;
|
||||
use actix_web::web::Data;
|
||||
use actix_web::Error;
|
||||
use futures::StreamExt;
|
||||
use jirs_data::UserId;
|
||||
use tokio::sync::broadcast::{Receiver, Sender};
|
||||
|
||||
#[cfg(all(feature = "local-storage", feature = "aws-s3"))]
|
||||
pub(crate) async fn handle_image(
|
||||
|
@ -1,14 +1,15 @@
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
use actix::Addr;
|
||||
use actix_web::web::Data;
|
||||
use actix_web::{HttpRequest, HttpResponse};
|
||||
use database_actor::authorize_user::AuthorizeUser;
|
||||
use database_actor::DbExecutor;
|
||||
pub use errors::*;
|
||||
use {
|
||||
crate::middleware::authorize::token_from_headers,
|
||||
actix::Addr,
|
||||
actix_web::{web::Data, HttpRequest, HttpResponse},
|
||||
database_actor::{authorize_user::AuthorizeUser, DbExecutor},
|
||||
jirs_data::User,
|
||||
};
|
||||
use jirs_data::User;
|
||||
|
||||
use crate::middleware::authorize::token_from_headers;
|
||||
|
||||
pub mod avatar;
|
||||
pub mod errors;
|
||||
|
@ -1,15 +1,12 @@
|
||||
use {
|
||||
actix_service::{Service, Transform},
|
||||
actix_web::{
|
||||
dev::{ServiceRequest, ServiceResponse},
|
||||
http::header::{self},
|
||||
http::HeaderMap,
|
||||
Error,
|
||||
},
|
||||
futures::future::{ok, FutureExt, LocalBoxFuture, Ready},
|
||||
jirs_data::User,
|
||||
std::task::{Context, Poll},
|
||||
};
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use actix_service::{Service, Transform};
|
||||
use actix_web::dev::{ServiceRequest, ServiceResponse};
|
||||
use actix_web::http::header::{self};
|
||||
use actix_web::http::HeaderMap;
|
||||
use actix_web::Error;
|
||||
use futures::future::{ok, FutureExt, LocalBoxFuture, Ready};
|
||||
use jirs_data::User;
|
||||
|
||||
type Db = actix_web::web::Data<database_actor::DbPool>;
|
||||
|
||||
|
@ -1,16 +1,13 @@
|
||||
use {
|
||||
crate::{
|
||||
db_or_debug_and_return, mail_or_debug_and_return, WebSocketActor, WsHandler, WsResult,
|
||||
},
|
||||
actix::AsyncContext,
|
||||
database_actor::{
|
||||
authorize_user::AuthorizeUser,
|
||||
tokens::{CreateBindToken, FindBindToken},
|
||||
users::LookupUser,
|
||||
},
|
||||
futures::executor::block_on,
|
||||
jirs_data::{Token, WsMsg},
|
||||
mail_actor::welcome::Welcome,
|
||||
use actix::AsyncContext;
|
||||
use database_actor::authorize_user::AuthorizeUser;
|
||||
use database_actor::tokens::{CreateBindToken, FindBindToken};
|
||||
use database_actor::users::LookupUser;
|
||||
use futures::executor::block_on;
|
||||
use jirs_data::{Token, WsMsg};
|
||||
use mail_actor::welcome::Welcome;
|
||||
|
||||
use crate::{
|
||||
db_or_debug_and_return, mail_or_debug_and_return, WebSocketActor, WsHandler, WsResult,
|
||||
};
|
||||
|
||||
pub struct Authenticate {
|
||||
|
@ -1,8 +1,7 @@
|
||||
use {
|
||||
crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult},
|
||||
futures::executor::block_on,
|
||||
jirs_data::{CommentId, CreateCommentPayload, IssueId, UpdateCommentPayload, WsMsg},
|
||||
};
|
||||
use futures::executor::block_on;
|
||||
use jirs_data::{CommentId, CreateCommentPayload, IssueId, UpdateCommentPayload, WsMsg};
|
||||
|
||||
use crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult};
|
||||
|
||||
pub struct LoadIssueComments {
|
||||
pub issue_id: IssueId,
|
||||
|
@ -1,9 +1,7 @@
|
||||
use jirs_data::IssueType;
|
||||
use {
|
||||
crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult},
|
||||
futures::executor::block_on,
|
||||
jirs_data::{DescriptionString, EpicId, NameString, UserProject, WsMsg},
|
||||
};
|
||||
use futures::executor::block_on;
|
||||
use jirs_data::{DescriptionString, EpicId, IssueType, NameString, UserProject, WsMsg};
|
||||
|
||||
use crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult};
|
||||
|
||||
pub struct LoadEpics;
|
||||
|
||||
@ -60,7 +58,7 @@ impl WsHandler<UpdateEpic> for WebSocketActor {
|
||||
self,
|
||||
database_actor::epics::UpdateEpic {
|
||||
project_id: *project_id,
|
||||
epic_id: epic_id,
|
||||
epic_id,
|
||||
name: name.clone(),
|
||||
}
|
||||
);
|
||||
@ -80,7 +78,7 @@ impl WsHandler<DeleteEpic> for WebSocketActor {
|
||||
self,
|
||||
database_actor::epics::DeleteEpic {
|
||||
user_id: *user_id,
|
||||
epic_id: epic_id,
|
||||
epic_id,
|
||||
}
|
||||
);
|
||||
Ok(Some(WsMsg::EpicDeleted(epic_id, n)))
|
||||
|
@ -1,8 +1,7 @@
|
||||
use {
|
||||
crate::{actor_or_debug_and_return, WebSocketActor, WsHandler, WsResult},
|
||||
futures::executor::block_on,
|
||||
jirs_data::{Code, Lang, WsMsg},
|
||||
};
|
||||
use futures::executor::block_on;
|
||||
use jirs_data::{Code, Lang, WsMsg};
|
||||
|
||||
use crate::{actor_or_debug_and_return, WebSocketActor, WsHandler, WsResult};
|
||||
|
||||
pub struct HighlightCode(pub Lang, pub Code);
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
use {
|
||||
crate::{
|
||||
db_or_debug_and_return, mail_or_debug_and_return, server::InnerMsg, WebSocketActor,
|
||||
WsHandler, WsMessageSender, WsResult,
|
||||
},
|
||||
database_actor::{invitations, messages::CreateMessageReceiver},
|
||||
futures::executor::block_on,
|
||||
jirs_data::{
|
||||
EmailString, InvitationId, InvitationToken, MessageType, UserRole, UsernameString, WsMsg,
|
||||
},
|
||||
use database_actor::invitations;
|
||||
use database_actor::messages::CreateMessageReceiver;
|
||||
use futures::executor::block_on;
|
||||
use jirs_data::{
|
||||
EmailString, InvitationId, InvitationToken, MessageType, UserRole, UsernameString, WsMsg,
|
||||
};
|
||||
|
||||
use crate::server::InnerMsg;
|
||||
use crate::{
|
||||
db_or_debug_and_return, mail_or_debug_and_return, WebSocketActor, WsHandler, WsMessageSender,
|
||||
WsResult,
|
||||
};
|
||||
|
||||
pub struct ListInvitation;
|
||||
|
@ -1,9 +1,8 @@
|
||||
use {
|
||||
crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult},
|
||||
database_actor::issue_statuses,
|
||||
futures::executor::block_on,
|
||||
jirs_data::{IssueStatusId, Position, TitleString, WsMsg},
|
||||
};
|
||||
use database_actor::issue_statuses;
|
||||
use futures::executor::block_on;
|
||||
use jirs_data::{IssueStatusId, Position, TitleString, WsMsg};
|
||||
|
||||
use crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult};
|
||||
|
||||
pub struct LoadIssueStatuses;
|
||||
|
||||
|
@ -1,17 +1,15 @@
|
||||
use {
|
||||
crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult},
|
||||
database_actor::{
|
||||
issue_assignees::LoadAssignees,
|
||||
issues::{LoadProjectIssues, UpdateIssue},
|
||||
},
|
||||
futures::executor::block_on,
|
||||
jirs_data::{
|
||||
CreateIssuePayload, IssueAssignee, IssueFieldId, IssueId, IssueStatusId, ListPosition,
|
||||
PayloadVariant, WsMsg,
|
||||
},
|
||||
std::collections::HashMap,
|
||||
use std::collections::HashMap;
|
||||
|
||||
use database_actor::issue_assignees::LoadAssignees;
|
||||
use database_actor::issues::{LoadProjectIssues, UpdateIssue};
|
||||
use futures::executor::block_on;
|
||||
use jirs_data::{
|
||||
CreateIssuePayload, IssueAssignee, IssueFieldId, IssueId, IssueStatusId, ListPosition,
|
||||
PayloadVariant, WsMsg,
|
||||
};
|
||||
|
||||
use crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult};
|
||||
|
||||
pub struct UpdateIssueHandler {
|
||||
pub id: i32,
|
||||
pub field_id: IssueFieldId,
|
||||
|
@ -1,9 +1,8 @@
|
||||
use {
|
||||
crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult},
|
||||
database_actor::messages,
|
||||
futures::executor::block_on,
|
||||
jirs_data::{MessageId, WsMsg},
|
||||
};
|
||||
use database_actor::messages;
|
||||
use futures::executor::block_on;
|
||||
use jirs_data::{MessageId, WsMsg};
|
||||
|
||||
use crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult};
|
||||
|
||||
pub struct LoadMessages;
|
||||
|
||||
|
@ -1,7 +1,14 @@
|
||||
pub use {
|
||||
auth::*, comments::*, epics::*, hi::*, invitations::*, issue_statuses::*, issues::*,
|
||||
messages::*, projects::*, user_projects::*, users::*,
|
||||
};
|
||||
pub use auth::*;
|
||||
pub use comments::*;
|
||||
pub use epics::*;
|
||||
pub use hi::*;
|
||||
pub use invitations::*;
|
||||
pub use issue_statuses::*;
|
||||
pub use issues::*;
|
||||
pub use messages::*;
|
||||
pub use projects::*;
|
||||
pub use user_projects::*;
|
||||
pub use users::*;
|
||||
|
||||
pub mod auth;
|
||||
pub mod comments;
|
||||
|
@ -1,9 +1,8 @@
|
||||
use {
|
||||
crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult},
|
||||
database_actor as db,
|
||||
futures::executor::block_on,
|
||||
jirs_data::{UpdateProjectPayload, UserProject, WsMsg},
|
||||
};
|
||||
use database_actor as db;
|
||||
use futures::executor::block_on;
|
||||
use jirs_data::{UpdateProjectPayload, UserProject, WsMsg};
|
||||
|
||||
use crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult};
|
||||
|
||||
impl WsHandler<UpdateProjectPayload> for WebSocketActor {
|
||||
fn handle_msg(&mut self, msg: UpdateProjectPayload, _ctx: &mut Self::Context) -> WsResult {
|
||||
|
@ -1,9 +1,8 @@
|
||||
use {
|
||||
crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult},
|
||||
database_actor as db,
|
||||
futures::executor::block_on,
|
||||
jirs_data::{UserProjectId, WsMsg},
|
||||
};
|
||||
use database_actor as db;
|
||||
use futures::executor::block_on;
|
||||
use jirs_data::{UserProjectId, WsMsg};
|
||||
|
||||
use crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult};
|
||||
|
||||
pub struct LoadUserProjects;
|
||||
|
||||
|
@ -1,11 +1,10 @@
|
||||
use {
|
||||
crate::{
|
||||
db_or_debug_and_return, handlers::auth::Authenticate, WebSocketActor, WsHandler, WsResult,
|
||||
},
|
||||
database_actor::{self, users::Register as DbRegister},
|
||||
futures::executor::block_on,
|
||||
jirs_data::{UserId, UserProject, UserRole, WsMsg},
|
||||
};
|
||||
use database_actor::users::Register as DbRegister;
|
||||
use database_actor::{self};
|
||||
use futures::executor::block_on;
|
||||
use jirs_data::{UserId, UserProject, UserRole, WsMsg};
|
||||
|
||||
use crate::handlers::auth::Authenticate;
|
||||
use crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult};
|
||||
|
||||
pub struct LoadProjectUsers;
|
||||
|
||||
|
@ -1,24 +1,20 @@
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
use {
|
||||
crate::{
|
||||
handlers::*,
|
||||
server::{InnerMsg, WsServer},
|
||||
},
|
||||
actix::{Actor, ActorContext, Addr, AsyncContext, Handler, Recipient, StreamHandler},
|
||||
actix_web::{
|
||||
get,
|
||||
web::{self, Data},
|
||||
Error, HttpRequest, HttpResponse,
|
||||
},
|
||||
actix_web_actors::ws,
|
||||
database_actor::{projects::LoadCurrentProject, user_projects::CurrentUserProject, DbExecutor},
|
||||
futures::executor::block_on,
|
||||
jirs_data::{Project, User, UserProject, WsMsg},
|
||||
log::*,
|
||||
mail_actor::MailExecutor,
|
||||
};
|
||||
use actix::{Actor, ActorContext, Addr, AsyncContext, Handler, Recipient, StreamHandler};
|
||||
use actix_web::web::{self, Data};
|
||||
use actix_web::{get, Error, HttpRequest, HttpResponse};
|
||||
use actix_web_actors::ws;
|
||||
use database_actor::projects::LoadCurrentProject;
|
||||
use database_actor::user_projects::CurrentUserProject;
|
||||
use database_actor::DbExecutor;
|
||||
use futures::executor::block_on;
|
||||
use jirs_data::{Project, User, UserProject, WsMsg};
|
||||
use log::*;
|
||||
use mail_actor::MailExecutor;
|
||||
|
||||
use crate::handlers::*;
|
||||
use crate::server::{InnerMsg, WsServer};
|
||||
|
||||
pub mod handlers;
|
||||
pub mod prelude;
|
||||
|
@ -1,8 +1,7 @@
|
||||
use {
|
||||
actix::{Actor, Context, Recipient},
|
||||
jirs_data::{ProjectId, UserId, WsMsg},
|
||||
std::collections::HashMap,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use actix::{Actor, Context, Recipient};
|
||||
use jirs_data::{ProjectId, UserId, WsMsg};
|
||||
|
||||
#[derive(actix::Message, Debug)]
|
||||
#[rtype(result = "()")]
|
||||
|
@ -3,11 +3,12 @@ mod utils;
|
||||
|
||||
extern crate proc_macro;
|
||||
|
||||
use {
|
||||
crate::parse_attr::Attributes,
|
||||
proc_macro::{token_stream::IntoIter, TokenStream, TokenTree},
|
||||
std::iter::Peekable,
|
||||
};
|
||||
use std::iter::Peekable;
|
||||
|
||||
use proc_macro::token_stream::IntoIter;
|
||||
use proc_macro::{TokenStream, TokenTree};
|
||||
|
||||
use crate::parse_attr::Attributes;
|
||||
|
||||
fn parse_meta(mut it: Peekable<IntoIter>) -> (Peekable<IntoIter>, Option<Attributes>) {
|
||||
let mut attrs: Option<Attributes> = None;
|
||||
@ -70,7 +71,6 @@ fn parse_meta(mut it: Peekable<IntoIter>) -> (Peekable<IntoIter>, Option<Attribu
|
||||
/// pub name: String
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
#[proc_macro_derive(Execute, attributes(db_exec))]
|
||||
pub fn derive_enum_iter(item: TokenStream) -> TokenStream {
|
||||
let mut it = item.into_iter().peekable();
|
||||
|
@ -1,6 +1,8 @@
|
||||
use proc_macro::{token_stream::IntoIter, TokenTree};
|
||||
use std::iter::Peekable;
|
||||
|
||||
use proc_macro::token_stream::IntoIter;
|
||||
use proc_macro::TokenTree;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct Attributes {
|
||||
pub result: Option<String>,
|
||||
|
@ -1,6 +1,8 @@
|
||||
use proc_macro::{token_stream::IntoIter, TokenTree};
|
||||
use std::iter::Peekable;
|
||||
|
||||
use proc_macro::token_stream::IntoIter;
|
||||
use proc_macro::TokenTree;
|
||||
|
||||
pub fn skip_pub(mut it: Peekable<IntoIter>) -> Peekable<IntoIter> {
|
||||
if let Some(TokenTree::Ident(ident)) = it.next() {
|
||||
if ident.to_string().as_str() != "pub" {
|
||||
|
@ -1,9 +1,9 @@
|
||||
extern crate proc_macro;
|
||||
|
||||
use {
|
||||
proc_macro::{token_stream::IntoIter, TokenStream, TokenTree},
|
||||
std::iter::Peekable,
|
||||
};
|
||||
use std::iter::Peekable;
|
||||
|
||||
use proc_macro::token_stream::IntoIter;
|
||||
use proc_macro::{TokenStream, TokenTree};
|
||||
|
||||
fn skip_meta(mut it: Peekable<IntoIter>) -> Peekable<IntoIter> {
|
||||
while let Some(token) = it.peek() {
|
||||
|
@ -1,22 +1,18 @@
|
||||
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,
|
||||
},
|
||||
};
|
||||
use std::error::Error;
|
||||
use std::io;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{mpsc, Arc};
|
||||
use std::time::Duration;
|
||||
|
||||
use termion::event::Key;
|
||||
use termion::input::MouseTerminal;
|
||||
use termion::raw::IntoRawMode;
|
||||
use termion::screen::AlternateScreen;
|
||||
use tui::backend::TermionBackend;
|
||||
use tui::layout::{Constraint, Direction, Layout};
|
||||
use tui::style::{Color, Style};
|
||||
use tui::widgets::{Block, Borders, Tabs};
|
||||
use tui::Terminal;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Config {
|
||||
@ -68,8 +64,8 @@ impl Events {
|
||||
// eprintln!("{}", err);
|
||||
// return;
|
||||
// }
|
||||
// if !ignore_exit_key.load(Ordering::Relaxed) && key == config.exit_key {
|
||||
// return;
|
||||
// if !ignore_exit_key.load(Ordering::Relaxed) && key ==
|
||||
// config.exit_key { return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@ -84,8 +80,8 @@ impl Events {
|
||||
Events {
|
||||
rx,
|
||||
ignore_exit_key,
|
||||
// input_handle,
|
||||
// tick_handle,
|
||||
/* input_handle,
|
||||
* tick_handle, */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
use {
|
||||
crate::{components::styled_editor::Mode as TabMode, FieldId},
|
||||
jirs_data::{EpicId, IssueStatusId, WsMsg},
|
||||
seed::prelude::WebSocketMessage,
|
||||
};
|
||||
use jirs_data::{EpicId, IssueStatusId, WsMsg};
|
||||
use seed::prelude::WebSocketMessage;
|
||||
|
||||
use crate::components::styled_editor::Mode as TabMode;
|
||||
use crate::FieldId;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum FieldChange {
|
||||
|
@ -1,7 +1,8 @@
|
||||
use {
|
||||
crate::{shared::ToNode, Msg},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::shared::ToNode;
|
||||
use crate::Msg;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StyledAvatar<'l> {
|
||||
|
@ -1,7 +1,8 @@
|
||||
use {
|
||||
crate::{shared::ToNode, ButtonId, Msg},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::shared::ToNode;
|
||||
use crate::{ButtonId, Msg};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub enum ButtonVariant {
|
||||
|
@ -1,11 +1,8 @@
|
||||
use {
|
||||
crate::{
|
||||
shared::{IntoChild, ToNode},
|
||||
FieldId, Msg,
|
||||
},
|
||||
jirs_data::TimeTracking,
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::shared::ToNode;
|
||||
use crate::{FieldId, Msg};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StyledCheckboxState {
|
||||
@ -30,12 +27,12 @@ impl StyledCheckboxState {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ChildBuilder<'l> {
|
||||
field_id: Option<FieldId>,
|
||||
name: &'l str,
|
||||
label: &'l str,
|
||||
value: u32,
|
||||
selected: bool,
|
||||
class_list: Vec<String>,
|
||||
pub field_id: Option<FieldId>,
|
||||
pub name: &'l str,
|
||||
pub label: &'l str,
|
||||
pub value: u32,
|
||||
pub selected: bool,
|
||||
pub class_list: &'l str,
|
||||
}
|
||||
|
||||
impl<'l> Default for ChildBuilder<'l> {
|
||||
@ -46,7 +43,7 @@ impl<'l> Default for ChildBuilder<'l> {
|
||||
label: "",
|
||||
value: 0,
|
||||
selected: false,
|
||||
class_list: vec![],
|
||||
class_list: "",
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -77,11 +74,8 @@ impl<'l> ChildBuilder<'l> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_class<S>(mut self, name: S) -> Self
|
||||
where
|
||||
S: Into<String>,
|
||||
{
|
||||
self.class_list.push(name.into());
|
||||
pub fn class_list(mut self, name: &'l str) -> Self {
|
||||
self.class_list = name;
|
||||
self
|
||||
}
|
||||
}
|
||||
@ -94,7 +88,7 @@ impl<'l> ToNode for ChildBuilder<'l> {
|
||||
label,
|
||||
value,
|
||||
selected,
|
||||
mut class_list,
|
||||
class_list,
|
||||
} = self;
|
||||
|
||||
let id = field_id.as_ref().map(|f| f.to_string()).unwrap_or_default();
|
||||
@ -103,9 +97,6 @@ impl<'l> ToNode for ChildBuilder<'l> {
|
||||
field_id_clone.map(|field_id| Msg::U32InputChanged(field_id, value))
|
||||
});
|
||||
|
||||
class_list.push("styledCheckboxChild".to_string());
|
||||
class_list.push(if selected { "selected" } else { "" }.to_string());
|
||||
|
||||
let input_attrs = if selected {
|
||||
attrs![At::Type => "radio", At::Name => name, At::Checked => selected, At::Id => format!("{}-{}", id, name)]
|
||||
} else {
|
||||
@ -113,7 +104,11 @@ impl<'l> ToNode for ChildBuilder<'l> {
|
||||
};
|
||||
|
||||
div![
|
||||
attrs![At::Class => class_list.join(" ")],
|
||||
C![
|
||||
"styledCheckboxChild",
|
||||
class_list,
|
||||
IF![selected => "selected"]
|
||||
],
|
||||
handler,
|
||||
label![attrs![At::For => format!("{}-{}", id, name)], label],
|
||||
input![input_attrs],
|
||||
@ -216,27 +211,3 @@ where
|
||||
opt,
|
||||
]
|
||||
}
|
||||
|
||||
impl<'l> IntoChild<'l> for TimeTracking {
|
||||
type Builder = ChildBuilder<'l>;
|
||||
|
||||
fn into_child(self) -> Self::Builder {
|
||||
Self::Builder::default()
|
||||
.label(match self {
|
||||
TimeTracking::Untracked => "No tracking",
|
||||
TimeTracking::Fibonacci => "Fibonacci (Bad mode)",
|
||||
TimeTracking::Hourly => "Evil Mode (Hourly)",
|
||||
})
|
||||
.name(match self {
|
||||
TimeTracking::Untracked => "untracked",
|
||||
TimeTracking::Fibonacci => "fibonacci",
|
||||
TimeTracking::Hourly => "hourly",
|
||||
})
|
||||
.add_class(match self {
|
||||
TimeTracking::Untracked => "untracked",
|
||||
TimeTracking::Fibonacci => "fibonacci",
|
||||
TimeTracking::Hourly => "hourly",
|
||||
})
|
||||
.value((self).into())
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,10 @@
|
||||
use {
|
||||
crate::{
|
||||
components::{styled_button::StyledButton, styled_modal::StyledModal},
|
||||
shared::ToNode,
|
||||
Msg,
|
||||
},
|
||||
seed::{prelude::*, EventHandler, *},
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::{EventHandler, *};
|
||||
|
||||
use crate::components::styled_button::ButtonVariant;
|
||||
use crate::components::styled_button::{ButtonVariant, StyledButton};
|
||||
use crate::components::styled_modal::StyledModal;
|
||||
use crate::shared::ToNode;
|
||||
use crate::Msg;
|
||||
|
||||
const TITLE: &str = "Warning";
|
||||
const MESSAGE: &str = "Are you sure you want to continue with this action?";
|
||||
|
@ -1,19 +1,15 @@
|
||||
use {
|
||||
crate::{
|
||||
components::{
|
||||
styled_button::StyledButton, styled_icon::Icon, styled_tooltip::StyledTooltip,
|
||||
},
|
||||
shared::ToNode,
|
||||
FieldId, Msg,
|
||||
},
|
||||
chrono::prelude::*,
|
||||
chrono::Duration,
|
||||
seed::{prelude::*, *},
|
||||
std::ops::RangeInclusive,
|
||||
};
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
use crate::components::styled_button::ButtonVariant;
|
||||
use crate::components::styled_tooltip::TooltipVariant;
|
||||
use chrono::prelude::*;
|
||||
use chrono::Duration;
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::components::styled_button::{ButtonVariant, StyledButton};
|
||||
use crate::components::styled_icon::Icon;
|
||||
use crate::components::styled_tooltip::{StyledTooltip, TooltipVariant};
|
||||
use crate::shared::ToNode;
|
||||
use crate::{FieldId, Msg};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum StyledDateTimeChanged {
|
||||
|
@ -1,9 +1,9 @@
|
||||
use {
|
||||
crate::{
|
||||
components::styled_textarea::StyledTextarea, shared::ToNode, FieldChange, FieldId, Msg,
|
||||
},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::components::styled_textarea::StyledTextarea;
|
||||
use crate::shared::ToNode;
|
||||
use crate::{FieldChange, FieldId, Msg};
|
||||
|
||||
#[derive(Debug, Clone, PartialOrd, PartialEq, Hash)]
|
||||
pub enum Mode {
|
||||
|
@ -1,7 +1,8 @@
|
||||
use {
|
||||
crate::{shared::ToNode, Msg},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::shared::ToNode;
|
||||
use crate::Msg;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StyledField<'l> {
|
||||
@ -22,57 +23,12 @@ impl<'l> Default for StyledField<'l> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> StyledField<'l> {
|
||||
pub fn build() -> StyledFieldBuilder<'l> {
|
||||
StyledFieldBuilder::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> ToNode for StyledField<'l> {
|
||||
fn into_node(self) -> Node<Msg> {
|
||||
render(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct StyledFieldBuilder<'l> {
|
||||
label: Option<&'l str>,
|
||||
tip: Option<&'l str>,
|
||||
input: Option<Node<Msg>>,
|
||||
class_list: &'l str,
|
||||
}
|
||||
|
||||
impl<'l> StyledFieldBuilder<'l> {
|
||||
pub fn label(mut self, label: &'l str) -> Self {
|
||||
self.label = Some(label);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn tip(mut self, tip: &'l str) -> Self {
|
||||
self.tip = Some(tip);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn input(mut self, input: Node<Msg>) -> Self {
|
||||
self.input = Some(input);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn class_list(mut self, name: &'l str) -> Self {
|
||||
self.class_list = name;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> StyledField<'l> {
|
||||
StyledField {
|
||||
label: self.label.unwrap_or_default(),
|
||||
tip: self.tip,
|
||||
input: self.input.unwrap_or(empty![]),
|
||||
class_list: self.class_list,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(values: StyledField) -> Node<Msg> {
|
||||
let StyledField {
|
||||
label,
|
||||
|
@ -1,7 +1,8 @@
|
||||
use {
|
||||
crate::{shared::ToNode, Msg},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::shared::ToNode;
|
||||
use crate::Msg;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct StyledForm<'l> {
|
||||
|
@ -1,9 +1,11 @@
|
||||
use {
|
||||
crate::{shared::ToNode, Msg},
|
||||
jirs_data::{IssuePriority, IssueType},
|
||||
seed::{prelude::*, *},
|
||||
std::borrow::Cow,
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use jirs_data::{IssuePriority, IssueType};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::shared::ToNode;
|
||||
use crate::Msg;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -245,37 +247,6 @@ impl ToNode for Icon {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StyledIconBuilder<'l> {
|
||||
pub icon: Icon,
|
||||
pub size: Option<i32>,
|
||||
pub class_list: &'l str,
|
||||
pub style_list: Vec<Cow<'l, str>>,
|
||||
pub color: Option<Cow<'l, str>>,
|
||||
pub on_click: Option<EventHandler<Msg>>,
|
||||
}
|
||||
|
||||
impl<'l> StyledIconBuilder<'l> {
|
||||
pub fn size(mut self, size: i32) -> Self {
|
||||
self.size = Some(size);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn class_list(mut self, name: &'l str) -> Self {
|
||||
self.class_list = name;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_color(mut self, color: &'l str) -> Self {
|
||||
self.color = Some(Cow::Borrowed(color));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_click(mut self, on_click: EventHandler<Msg>) -> Self {
|
||||
self.on_click = Some(on_click);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StyledIcon<'l> {
|
||||
pub icon: Icon,
|
||||
pub size: Option<i32>,
|
||||
|
@ -1,8 +1,9 @@
|
||||
use {
|
||||
crate::{shared::ToNode, FieldId, Msg},
|
||||
seed::{prelude::*, *},
|
||||
web_sys::File,
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
use web_sys::File;
|
||||
|
||||
use crate::shared::ToNode;
|
||||
use crate::{FieldId, Msg};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct StyledImageInputState {
|
||||
|
@ -1,11 +1,9 @@
|
||||
use {
|
||||
crate::{
|
||||
components::styled_icon::{Icon, StyledIcon},
|
||||
shared::ToNode,
|
||||
FieldId, Msg,
|
||||
},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::components::styled_icon::{Icon, StyledIcon};
|
||||
use crate::shared::ToNode;
|
||||
use crate::{FieldId, Msg};
|
||||
|
||||
#[derive(Clone, Debug, PartialOrd, PartialEq)]
|
||||
pub enum InputVariant {
|
||||
|
@ -1,8 +1,10 @@
|
||||
use {
|
||||
crate::{shared::ToNode, Msg},
|
||||
seed::{prelude::*, *},
|
||||
std::str::FromStr,
|
||||
};
|
||||
use std::str::FromStr;
|
||||
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::shared::ToNode;
|
||||
use crate::Msg;
|
||||
|
||||
pub struct StyledLink<'l> {
|
||||
pub children: Vec<Node<Msg>>,
|
||||
@ -10,48 +12,6 @@ pub struct StyledLink<'l> {
|
||||
pub href: &'l str,
|
||||
}
|
||||
|
||||
impl<'l> StyledLink<'l> {
|
||||
// pub fn build() -> StyledLinkBuilder<'l> {
|
||||
// StyledLinkBuilder::default()
|
||||
// }
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct StyledLinkBuilder<'l> {
|
||||
children: Vec<Node<Msg>>,
|
||||
class_list: &'l str,
|
||||
href: &'l str,
|
||||
}
|
||||
|
||||
impl<'l> StyledLinkBuilder<'l> {
|
||||
pub fn add_child(mut self, child: Node<Msg>) -> Self {
|
||||
self.children.push(child);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn class_list(mut self, name: &'l str) -> Self {
|
||||
self.class_list = name;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn href(mut self, href: &'l str) -> Self {
|
||||
self.href = href;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn text(self, s: &'l str) -> Self {
|
||||
self.add_child(span![s])
|
||||
}
|
||||
|
||||
pub fn build(self) -> StyledLink<'l> {
|
||||
StyledLink {
|
||||
children: self.children,
|
||||
class_list: self.class_list,
|
||||
href: self.href,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> ToNode for StyledLink<'l> {
|
||||
fn into_node(self) -> Node<Msg> {
|
||||
render(self)
|
||||
|
@ -1,11 +1,9 @@
|
||||
use {
|
||||
crate::{
|
||||
components::styled_icon::{Icon, StyledIcon},
|
||||
shared::ToNode,
|
||||
Msg,
|
||||
},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::components::styled_icon::{Icon, StyledIcon};
|
||||
use crate::shared::ToNode;
|
||||
use crate::Msg;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
|
||||
|
@ -1,14 +1,12 @@
|
||||
use {
|
||||
crate::{
|
||||
components::{
|
||||
styled_icon::{Icon, StyledIcon},
|
||||
styled_select_child::*,
|
||||
},
|
||||
shared::ToNode,
|
||||
FieldId, Msg,
|
||||
},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::components::styled_icon::{Icon, StyledIcon};
|
||||
use crate::components::styled_select_child::*;
|
||||
use crate::shared::ToNode;
|
||||
use crate::{FieldId, Msg};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum StyledSelectChanged {
|
||||
@ -71,7 +69,7 @@ impl StyledSelectState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, msg: &Msg, _orders: &mut impl Orders<Msg>) {
|
||||
pub fn update(&mut self, msg: &Msg, orders: &mut impl Orders<Msg>) {
|
||||
let field_id = match msg {
|
||||
Msg::StyledSelectChanged(field_id, ..) => field_id,
|
||||
_ => return,
|
||||
@ -87,6 +85,7 @@ impl StyledSelectState {
|
||||
}
|
||||
}
|
||||
Msg::StyledSelectChanged(_, StyledSelectChanged::Text(text)) => {
|
||||
orders.skip();
|
||||
self.text_filter = text.clone();
|
||||
}
|
||||
Msg::StyledSelectChanged(_, StyledSelectChanged::Changed(Some(v))) => {
|
||||
@ -112,7 +111,7 @@ impl StyledSelectState {
|
||||
|
||||
pub struct StyledSelect<'l, Options>
|
||||
where
|
||||
Options: Iterator<Item = StyledSelectChildBuilder<'l>>,
|
||||
Options: Iterator<Item = StyledSelectChild<'l>>,
|
||||
{
|
||||
pub id: FieldId,
|
||||
pub variant: SelectVariant,
|
||||
@ -121,7 +120,7 @@ where
|
||||
pub valid: bool,
|
||||
pub is_multi: bool,
|
||||
pub options: Option<Options>,
|
||||
pub selected: Vec<StyledSelectChildBuilder<'l>>,
|
||||
pub selected: Vec<StyledSelectChild<'l>>,
|
||||
pub text_filter: &'l str,
|
||||
pub opened: bool,
|
||||
pub clearable: bool,
|
||||
@ -129,7 +128,7 @@ where
|
||||
|
||||
impl<'l, Options> Default for StyledSelect<'l, Options>
|
||||
where
|
||||
Options: Iterator<Item = StyledSelectChildBuilder<'l>>,
|
||||
Options: Iterator<Item = StyledSelectChild<'l>>,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
@ -150,7 +149,7 @@ where
|
||||
|
||||
impl<'l, Options> ToNode for StyledSelect<'l, Options>
|
||||
where
|
||||
Options: Iterator<Item = StyledSelectChildBuilder<'l>>,
|
||||
Options: Iterator<Item = StyledSelectChild<'l>>,
|
||||
{
|
||||
fn into_node(self) -> Node<Msg> {
|
||||
render(self)
|
||||
@ -159,7 +158,7 @@ where
|
||||
|
||||
pub fn render<'l, Options>(values: StyledSelect<'l, Options>) -> Node<Msg>
|
||||
where
|
||||
Options: Iterator<Item = StyledSelectChildBuilder<'l>>,
|
||||
Options: Iterator<Item = StyledSelectChild<'l>>,
|
||||
{
|
||||
let StyledSelect {
|
||||
id,
|
||||
@ -221,13 +220,16 @@ where
|
||||
empty![]
|
||||
};
|
||||
|
||||
let skip = selected.iter().fold(HashMap::new(), |mut h, o| {
|
||||
h.insert(o.value, true);
|
||||
h
|
||||
});
|
||||
let children: Vec<Node<Msg>> = if let Some(options) = options {
|
||||
options
|
||||
.filter(|o| !selected.contains(&o) && o.match_text(text_filter))
|
||||
.filter(|o| !skip.contains_key(&o.value) && o.match_text(text_filter))
|
||||
.map(|child| {
|
||||
let child = child.build(DisplayType::SelectOption);
|
||||
let value = child.value();
|
||||
let node = child.into_node();
|
||||
let node = child.render_option();
|
||||
|
||||
let on_change = {
|
||||
let field_id = id.clone();
|
||||
@ -245,21 +247,6 @@ where
|
||||
vec![]
|
||||
};
|
||||
|
||||
let text_input = if opened {
|
||||
seed::input![
|
||||
C!["dropDownInput"],
|
||||
attrs![
|
||||
At::Name => name,
|
||||
At::Type => "text"
|
||||
At::Placeholder => "Search"
|
||||
At::AutoFocus => "true",
|
||||
],
|
||||
on_text,
|
||||
]
|
||||
} else {
|
||||
empty![]
|
||||
};
|
||||
|
||||
let option_list = match (opened, children.is_empty()) {
|
||||
(false, _) => empty![],
|
||||
(_, true) => seed::div![C!["noOptions"], "No results"],
|
||||
@ -281,10 +268,7 @@ where
|
||||
|
||||
vec![div![C!["valueMulti"], children]]
|
||||
} else {
|
||||
selected
|
||||
.into_iter()
|
||||
.map(|m| render_value(m.build(DisplayType::SelectValue).into_node()))
|
||||
.collect()
|
||||
selected.into_iter().map(|m| m.render_value()).collect()
|
||||
};
|
||||
|
||||
seed::div![
|
||||
@ -303,29 +287,25 @@ where
|
||||
div![
|
||||
C!["dropDown"],
|
||||
attrs![At::Style => dropdown_style.as_str()],
|
||||
text_input,
|
||||
IF![opened => seed::input![
|
||||
C!["dropDownInput"],
|
||||
attrs![
|
||||
At::Name => name,
|
||||
At::Type => "text"
|
||||
At::Placeholder => "Search"
|
||||
At::AutoFocus => "true",
|
||||
],
|
||||
on_text,
|
||||
]],
|
||||
option_list
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
fn render_value(mut content: Node<Msg>) -> Node<Msg> {
|
||||
content.add_class("value");
|
||||
content
|
||||
}
|
||||
|
||||
fn into_multi_value(opt: StyledSelectChildBuilder, id: FieldId) -> Node<Msg> {
|
||||
let close_icon = StyledIcon {
|
||||
icon: Icon::Close,
|
||||
size: Some(14),
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
let child = opt.build(DisplayType::SelectValue);
|
||||
fn into_multi_value(child: StyledSelectChild, id: FieldId) -> Node<Msg> {
|
||||
let value = child.value();
|
||||
|
||||
let mut opt = child.into_node();
|
||||
opt.add_class("value").add_child(close_icon);
|
||||
let opt = child.render_multi_value();
|
||||
|
||||
let handler = {
|
||||
let field_id = id;
|
||||
|
@ -1,25 +1,23 @@
|
||||
use {
|
||||
crate::{
|
||||
components::styled_select::SelectVariant,
|
||||
shared::{IntoChild, ToChild, ToNode},
|
||||
Msg,
|
||||
},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::components::styled_avatar::StyledAvatar;
|
||||
use crate::components::styled_icon::StyledIcon;
|
||||
use crate::components::styled_icon::{Icon, StyledIcon};
|
||||
use crate::components::styled_select::SelectVariant;
|
||||
use crate::shared::ToNode;
|
||||
use crate::Msg;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub enum DisplayType {
|
||||
SelectOption,
|
||||
SelectValue,
|
||||
SelectMultiValue,
|
||||
}
|
||||
|
||||
pub struct StyledSelectChild<'l> {
|
||||
pub name: Option<&'l str>,
|
||||
pub icon: Option<Node<Msg>>,
|
||||
pub text: Option<&'l str>,
|
||||
pub display_type: DisplayType,
|
||||
pub value: u32,
|
||||
pub class_list: &'l str,
|
||||
pub variant: SelectVariant,
|
||||
@ -31,7 +29,6 @@ impl<'l> Default for StyledSelectChild<'l> {
|
||||
name: None,
|
||||
icon: None,
|
||||
text: None,
|
||||
display_type: DisplayType::SelectOption,
|
||||
value: 0,
|
||||
class_list: "",
|
||||
variant: Default::default(),
|
||||
@ -44,95 +41,37 @@ impl<'l> StyledSelectChild<'l> {
|
||||
pub fn value(&self) -> u32 {
|
||||
self.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> ToNode for StyledSelectChild<'l> {
|
||||
fn into_node(self) -> Node<Msg> {
|
||||
render(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StyledSelectChildBuilder<'l> {
|
||||
pub icon: Option<Node<Msg>>,
|
||||
pub text: Option<&'l str>,
|
||||
pub name: Option<&'l str>,
|
||||
pub value: u32,
|
||||
pub class_list: &'l str,
|
||||
pub variant: SelectVariant,
|
||||
}
|
||||
|
||||
impl<'l> Default for StyledSelectChildBuilder<'l> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
icon: None,
|
||||
text: None,
|
||||
name: None,
|
||||
value: 0,
|
||||
class_list: "",
|
||||
variant: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> PartialEq for StyledSelectChildBuilder<'l> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.value == other.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> StyledSelectChildBuilder<'l> {
|
||||
pub fn icon(mut self, icon: Node<Msg>) -> Self {
|
||||
self.icon = Some(icon);
|
||||
self
|
||||
#[inline(always)]
|
||||
pub fn render_value(self) -> Node<Msg> {
|
||||
render(DisplayType::SelectValue, self)
|
||||
}
|
||||
|
||||
pub fn text<'m: 'l>(mut self, text: &'m str) -> Self {
|
||||
self.text = Some(text);
|
||||
self
|
||||
#[inline(always)]
|
||||
pub fn render_multi_value(self) -> Node<Msg> {
|
||||
render(DisplayType::SelectMultiValue, self)
|
||||
}
|
||||
|
||||
pub fn name(mut self, name: &'l str) -> Self {
|
||||
self.name = Some(name);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn value(mut self, value: u32) -> Self {
|
||||
self.value = value;
|
||||
self
|
||||
#[inline(always)]
|
||||
pub fn render_option(self) -> Node<Msg> {
|
||||
render(DisplayType::SelectOption, self)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn match_text(&self, text: &str) -> bool {
|
||||
self.text
|
||||
.as_ref()
|
||||
.map(|t| t.to_lowercase().contains(text.to_lowercase().as_str()))
|
||||
.unwrap_or(true)
|
||||
}
|
||||
|
||||
pub fn class_list<'m: 'l>(mut self, name: &'m str) -> Self {
|
||||
self.class_list = name;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self, display_type: DisplayType) -> StyledSelectChild<'l> {
|
||||
StyledSelectChild {
|
||||
name: self.name,
|
||||
icon: self.icon,
|
||||
text: self.text,
|
||||
display_type,
|
||||
value: self.value,
|
||||
class_list: self.class_list,
|
||||
variant: self.variant,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(values: StyledSelectChild) -> Node<Msg> {
|
||||
#[inline(always)]
|
||||
pub fn render(display_type: DisplayType, values: StyledSelectChild) -> Node<Msg> {
|
||||
let StyledSelectChild {
|
||||
name,
|
||||
icon,
|
||||
text,
|
||||
display_type,
|
||||
value: _,
|
||||
class_list,
|
||||
variant,
|
||||
@ -152,7 +91,7 @@ pub fn render(values: StyledSelectChild) -> Node<Msg> {
|
||||
.unwrap_or_default(),
|
||||
match display_type {
|
||||
DisplayType::SelectOption => "optionLabel",
|
||||
DisplayType::SelectValue => "selectItemLabel",
|
||||
DisplayType::SelectValue | DisplayType::SelectMultiValue => "selectItemLabel",
|
||||
},
|
||||
class_list
|
||||
],
|
||||
@ -167,168 +106,22 @@ pub fn render(values: StyledSelectChild) -> Node<Msg> {
|
||||
name.as_deref().unwrap_or_default(),
|
||||
match display_type {
|
||||
DisplayType::SelectOption => "optionItem",
|
||||
DisplayType::SelectValue => "selectItem",
|
||||
DisplayType::SelectValue | DisplayType::SelectMultiValue => "selectItem value",
|
||||
},
|
||||
class_list
|
||||
],
|
||||
icon_node,
|
||||
label_node
|
||||
label_node,
|
||||
IF![display_type == DisplayType::SelectMultiValue => close_icon()]
|
||||
]
|
||||
}
|
||||
|
||||
impl<'l> ToChild<'l> for jirs_data::User {
|
||||
type Builder = StyledSelectChildBuilder<'l>;
|
||||
|
||||
fn to_child<'m: 'l>(&'m self) -> Self::Builder {
|
||||
let avatar = StyledAvatar {
|
||||
size: 20,
|
||||
name: &self.name,
|
||||
avatar_url: self.avatar_url.as_deref(),
|
||||
..StyledAvatar::default()
|
||||
}
|
||||
.into_node();
|
||||
StyledSelectChildBuilder {
|
||||
value: self.id as u32,
|
||||
icon: Some(avatar),
|
||||
text: Some(self.name.as_str()),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> IntoChild<'l> for jirs_data::IssuePriority {
|
||||
type Builder = StyledSelectChildBuilder<'l>;
|
||||
|
||||
fn into_child(self) -> Self::Builder {
|
||||
let icon = StyledIcon {
|
||||
icon: self.clone().into(),
|
||||
class_list: self.to_str(),
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
|
||||
StyledSelectChildBuilder {
|
||||
icon: Some(icon),
|
||||
text: Some(self.to_str()),
|
||||
class_list: self.to_str(),
|
||||
value: self.into(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> ToChild<'l> for jirs_data::IssueStatus {
|
||||
type Builder = StyledSelectChildBuilder<'l>;
|
||||
|
||||
fn to_child<'m: 'l>(&'m self) -> Self::Builder {
|
||||
StyledSelectChildBuilder {
|
||||
value: self.id as u32,
|
||||
class_list: self.name.as_str(),
|
||||
text: Some(self.name.as_str()),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> IntoChild<'l> for jirs_data::IssueType {
|
||||
type Builder = StyledSelectChildBuilder<'l>;
|
||||
|
||||
fn into_child(self) -> Self::Builder {
|
||||
let name = self.to_label();
|
||||
|
||||
let type_icon = StyledIcon {
|
||||
icon: self.clone().into(),
|
||||
class_list: name,
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
|
||||
StyledSelectChildBuilder {
|
||||
class_list: name,
|
||||
text: Some(name),
|
||||
icon: Some(type_icon),
|
||||
value: self.into(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> IntoChild<'l> for jirs_data::ProjectCategory {
|
||||
type Builder = StyledSelectChildBuilder<'l>;
|
||||
|
||||
fn into_child(self) -> Self::Builder {
|
||||
StyledSelectChildBuilder {
|
||||
class_list: self.to_str(),
|
||||
text: Some(self.to_str()),
|
||||
value: self.into(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> IntoChild<'l> for jirs_data::UserRole {
|
||||
type Builder = StyledSelectChildBuilder<'l>;
|
||||
|
||||
fn into_child(self) -> Self::Builder {
|
||||
let name = self.to_str();
|
||||
|
||||
StyledSelectChildBuilder {
|
||||
text: Some(name),
|
||||
value: self.into(),
|
||||
class_list: name,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! id_name_builder {
|
||||
() => {
|
||||
fn to_child<'m: 'l>(&'m self) -> Self::Builder {
|
||||
StyledSelectChildBuilder {
|
||||
text: Some(self.name.as_str()),
|
||||
value: self.id as u32,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<'l> ToChild<'l> for jirs_data::Project {
|
||||
type Builder = StyledSelectChildBuilder<'l>;
|
||||
id_name_builder!();
|
||||
}
|
||||
|
||||
impl<'l> ToChild<'l> for jirs_data::Epic {
|
||||
type Builder = StyledSelectChildBuilder<'l>;
|
||||
id_name_builder!();
|
||||
}
|
||||
|
||||
impl<'l> ToChild<'l> for u32 {
|
||||
type Builder = StyledSelectChildBuilder<'l>;
|
||||
|
||||
fn to_child<'m: 'l>(&'m self) -> Self::Builder {
|
||||
let name = stringify!(self);
|
||||
|
||||
StyledSelectChildBuilder {
|
||||
class_list: name,
|
||||
text: Some(name),
|
||||
value: *self,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type Label = String;
|
||||
pub type Value = u32;
|
||||
|
||||
impl<'l> ToChild<'l> for (Label, Value) {
|
||||
type Builder = StyledSelectChildBuilder<'l>;
|
||||
|
||||
fn to_child<'m: 'l>(&'m self) -> Self::Builder {
|
||||
StyledSelectChildBuilder {
|
||||
text: Some(self.0.as_str()),
|
||||
value: self.1,
|
||||
..Default::default()
|
||||
}
|
||||
#[inline(always)]
|
||||
fn close_icon() -> Node<Msg> {
|
||||
StyledIcon {
|
||||
icon: Icon::Close,
|
||||
size: Some(14),
|
||||
..Default::default()
|
||||
}
|
||||
.into_node()
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
use {
|
||||
crate::{shared::ToNode, FieldId, Msg},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::shared::ToNode;
|
||||
use crate::{FieldId, Msg};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StyledTextarea<'l> {
|
||||
@ -43,8 +44,8 @@ const PADDING_TOP_BOTTOM: f64 = 17f64;
|
||||
const BORDER_TOP_BOTTOM: f64 = 2f64;
|
||||
const ADDITIONAL_HEIGHT: f64 = PADDING_TOP_BOTTOM + BORDER_TOP_BOTTOM;
|
||||
|
||||
// height = `calc( (${$0.value.split("\n").length}px * ( 15 * 1.4285 )) + 17px + 2px)`
|
||||
// where:
|
||||
// height = `calc( (${$0.value.split("\n").length}px * ( 15 * 1.4285 )) + 17px +
|
||||
// 2px)` where:
|
||||
// * 15 is font-size
|
||||
// * 1.4285 is line-height
|
||||
// * 17 is padding top + bottom
|
||||
|
@ -1,7 +1,8 @@
|
||||
use {
|
||||
crate::{shared::ToNode, Msg},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::shared::ToNode;
|
||||
use crate::Msg;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum TooltipVariant {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use {
|
||||
crate::Msg,
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::Msg;
|
||||
|
||||
#[inline(always)]
|
||||
pub fn render() -> Node<Msg> {
|
||||
|
@ -1,22 +1,21 @@
|
||||
#![feature(type_ascription, trait_alias, drain_filter)]
|
||||
|
||||
use {
|
||||
crate::{
|
||||
components::{
|
||||
styled_date_time_input::StyledDateTimeChanged,
|
||||
styled_select::StyledSelectChanged,
|
||||
styled_tooltip,
|
||||
styled_tooltip::{TooltipVariant as StyledTooltip, TooltipVariant},
|
||||
},
|
||||
model::{ModalType, Model, Page},
|
||||
shared::{go_to_board, go_to_login},
|
||||
ws::{flush_queue, open_socket, read_incoming, send_ws_msg},
|
||||
},
|
||||
jirs_data::*,
|
||||
seed::{prelude::*, *},
|
||||
web_sys::File,
|
||||
};
|
||||
pub use {changes::*, components::*, fields::*, images::*};
|
||||
pub use changes::*;
|
||||
pub use components::*;
|
||||
pub use fields::*;
|
||||
pub use images::*;
|
||||
use jirs_data::*;
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
use web_sys::File;
|
||||
|
||||
use crate::components::styled_date_time_input::StyledDateTimeChanged;
|
||||
use crate::components::styled_select::StyledSelectChanged;
|
||||
use crate::components::styled_tooltip;
|
||||
use crate::components::styled_tooltip::{TooltipVariant as StyledTooltip, TooltipVariant};
|
||||
use crate::model::{ModalType, Model, Page};
|
||||
use crate::shared::{go_to_board, go_to_login};
|
||||
use crate::ws::{flush_queue, open_socket, read_incoming, send_ws_msg};
|
||||
|
||||
// use crate::shared::styled_rte::RteMsg;
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
pub use {model::*, view::*};
|
||||
pub use model::*;
|
||||
pub use view::*;
|
||||
|
||||
mod model;
|
||||
mod view;
|
||||
|
@ -1,8 +1,9 @@
|
||||
use {
|
||||
crate::{model, shared::ToNode, styled_confirm_modal::StyledConfirmModal, Msg},
|
||||
jirs_data::CommentId,
|
||||
seed::prelude::*,
|
||||
};
|
||||
use jirs_data::CommentId;
|
||||
use seed::prelude::*;
|
||||
|
||||
use crate::shared::ToNode;
|
||||
use crate::styled_confirm_modal::StyledConfirmModal;
|
||||
use crate::{model, Msg};
|
||||
|
||||
pub fn view(_model: &model::Model, modal: &super::Model) -> Node<Msg> {
|
||||
let comment_id: CommentId = modal.comment_id;
|
||||
|
@ -1,4 +1,6 @@
|
||||
pub use {model::*, update::*, view::*};
|
||||
pub use model::*;
|
||||
pub use update::*;
|
||||
pub use view::*;
|
||||
|
||||
mod model;
|
||||
mod update;
|
||||
|
@ -1,7 +1,10 @@
|
||||
use {
|
||||
crate::{components::styled_modal::StyledModal, model::Model, shared::ToNode, Msg},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::components::styled_modal::StyledModal;
|
||||
use crate::model::Model;
|
||||
use crate::shared::ToNode;
|
||||
use crate::Msg;
|
||||
|
||||
pub fn view(model: &Model) -> Node<Msg> {
|
||||
let text = format!("{:#?}", model);
|
||||
|
@ -1,15 +1,12 @@
|
||||
use {
|
||||
crate::{
|
||||
components::{styled_field::StyledField, styled_select::StyledSelect},
|
||||
model::{IssueModal, Model},
|
||||
shared::{ToChild, ToNode},
|
||||
FieldId, Msg,
|
||||
},
|
||||
jirs_data::EpicId,
|
||||
seed::prelude::Node,
|
||||
};
|
||||
use jirs_data::{Epic, EpicId};
|
||||
use seed::prelude::Node;
|
||||
|
||||
use crate::components::styled_select::SelectVariant;
|
||||
use crate::components::styled_field::StyledField;
|
||||
use crate::components::styled_select::{SelectVariant, StyledSelect};
|
||||
use crate::components::styled_select_child::StyledSelectChild;
|
||||
use crate::model::{IssueModal, Model};
|
||||
use crate::shared::ToNode;
|
||||
use crate::{FieldId, Msg};
|
||||
|
||||
pub fn epic_field<Modal>(model: &Model, modal: &Modal, field_id: FieldId) -> Option<Node<Msg>>
|
||||
where
|
||||
@ -18,16 +15,15 @@ where
|
||||
if model.epics.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let selected = modal
|
||||
.epic_id_value()
|
||||
.and_then(|id| model.epics.iter().find(|epic| epic.id == id as EpicId))
|
||||
.map(|epic| vec![epic.to_child()])
|
||||
.unwrap_or_default();
|
||||
let input = StyledSelect {
|
||||
id: field_id,
|
||||
name: "epic",
|
||||
selected,
|
||||
options: Some(model.epics.iter().map(|epic| epic.to_child())),
|
||||
selected: vec![modal
|
||||
.epic_id_value()
|
||||
.and_then(|id| model.epics.iter().find(|epic| epic.id == id as EpicId))
|
||||
.map(epic_select_option)
|
||||
.unwrap_or_default()],
|
||||
options: Some(model.epics.iter().map(epic_select_option)),
|
||||
variant: SelectVariant::Normal,
|
||||
clearable: true,
|
||||
text_filter: modal.epic_state().text_filter.as_str(),
|
||||
@ -46,3 +42,11 @@ where
|
||||
.into_node(),
|
||||
)
|
||||
}
|
||||
|
||||
fn epic_select_option<'l>(epic: &'l Epic) -> StyledSelectChild<'l> {
|
||||
StyledSelectChild {
|
||||
value: epic.id as u32,
|
||||
text: Some(epic.name.as_str()),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
pub use {model::*, update::*, view::*};
|
||||
pub use model::*;
|
||||
pub use update::*;
|
||||
pub use view::*;
|
||||
|
||||
mod model;
|
||||
mod update;
|
||||
|
@ -1,7 +1,6 @@
|
||||
use {
|
||||
crate::model,
|
||||
jirs_data::{EpicId, IssueId},
|
||||
};
|
||||
use jirs_data::{EpicId, IssueId};
|
||||
|
||||
use crate::model;
|
||||
|
||||
#[derive(Clone, Debug, PartialOrd, PartialEq)]
|
||||
pub struct Model {
|
||||
|
@ -1,8 +1,8 @@
|
||||
use {
|
||||
crate::{ws::send_ws_msg, Msg, OperationKind, ResourceKind},
|
||||
jirs_data::WsMsg,
|
||||
seed::prelude::*,
|
||||
};
|
||||
use jirs_data::WsMsg;
|
||||
use seed::prelude::*;
|
||||
|
||||
use crate::ws::send_ws_msg;
|
||||
use crate::{Msg, OperationKind, ResourceKind};
|
||||
|
||||
pub fn update(msg: &Msg, model: &mut crate::model::Model, orders: &mut impl Orders<Msg>) {
|
||||
let modal = match &mut model.modals_mut().delete_epic {
|
||||
|
@ -1,13 +1,13 @@
|
||||
use {
|
||||
crate::{
|
||||
components::{styled_button::*, styled_confirm_modal::*, styled_icon::*, styled_modal::*},
|
||||
modals::epics_delete::Model,
|
||||
model,
|
||||
shared::ToNode,
|
||||
Msg,
|
||||
},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::components::styled_button::*;
|
||||
use crate::components::styled_confirm_modal::*;
|
||||
use crate::components::styled_icon::*;
|
||||
use crate::components::styled_modal::*;
|
||||
use crate::modals::epics_delete::Model;
|
||||
use crate::shared::ToNode;
|
||||
use crate::{model, Msg};
|
||||
|
||||
pub fn view(model: &model::Model, modal: &Model) -> Node<Msg> {
|
||||
if modal.related_issues.is_empty() {
|
||||
|
@ -1,4 +1,6 @@
|
||||
pub use {model::*, update::*, view::*};
|
||||
pub use model::*;
|
||||
pub use update::*;
|
||||
pub use view::*;
|
||||
|
||||
mod model;
|
||||
mod update;
|
||||
|
@ -1,11 +1,9 @@
|
||||
use {
|
||||
crate::{
|
||||
components::{styled_checkbox::StyledCheckboxState, styled_input::*},
|
||||
model, FieldId, Msg,
|
||||
},
|
||||
jirs_data::*,
|
||||
seed::prelude::Orders,
|
||||
};
|
||||
use jirs_data::*;
|
||||
use seed::prelude::Orders;
|
||||
|
||||
use crate::components::styled_checkbox::StyledCheckboxState;
|
||||
use crate::components::styled_input::*;
|
||||
use crate::{model, FieldId, Msg};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Model {
|
||||
|
@ -1,8 +1,7 @@
|
||||
use {
|
||||
crate::{send_ws_msg, FieldId, Msg, OperationKind, ResourceKind},
|
||||
jirs_data::{EpicFieldId, IssueType, WsMsg},
|
||||
seed::prelude::*,
|
||||
};
|
||||
use jirs_data::{EpicFieldId, IssueType, WsMsg};
|
||||
use seed::prelude::*;
|
||||
|
||||
use crate::{send_ws_msg, FieldId, Msg, OperationKind, ResourceKind};
|
||||
|
||||
pub fn update(msg: &Msg, model: &mut crate::model::Model, orders: &mut impl Orders<Msg>) {
|
||||
let modal = match &mut model.modals.edit_epic {
|
||||
|
@ -1,17 +1,15 @@
|
||||
use {
|
||||
crate::{
|
||||
components::{
|
||||
styled_button::*, styled_checkbox::*, styled_icon::Icon, styled_input::*,
|
||||
styled_modal::*,
|
||||
},
|
||||
modals::epics_edit::Model,
|
||||
model,
|
||||
shared::{IntoChild, ToNode},
|
||||
FieldId, Msg,
|
||||
},
|
||||
jirs_data::{EpicFieldId, IssueType},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use jirs_data::{EpicFieldId, IssueType};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::components::styled_button::*;
|
||||
use crate::components::styled_checkbox::*;
|
||||
use crate::components::styled_icon::Icon;
|
||||
use crate::components::styled_input::*;
|
||||
use crate::components::styled_modal::*;
|
||||
use crate::modals::epics_edit::Model;
|
||||
use crate::shared::{IntoChild, ToNode};
|
||||
use crate::{model, FieldId, Msg};
|
||||
|
||||
pub struct IssueTypeWrapper(IssueType);
|
||||
|
||||
@ -23,7 +21,7 @@ impl<'l> IntoChild<'l> for IssueTypeWrapper {
|
||||
.label(self.0.to_label())
|
||||
.name(self.0.to_str())
|
||||
.value(self.0.into())
|
||||
.add_class(self.0.to_str())
|
||||
.class_list(self.0.to_str())
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,7 +66,7 @@ fn transform_into_available(modal: &super::Model) -> Node<Msg> {
|
||||
.options(
|
||||
IssueType::default()
|
||||
.into_iter()
|
||||
.map(|ty| IssueTypeWrapper(ty).into_child()),
|
||||
.map(issue_type_select_option),
|
||||
)
|
||||
.state(&modal.transform_into)
|
||||
.build(FieldId::EditEpic(EpicFieldId::TransformInto))
|
||||
@ -86,6 +84,17 @@ fn transform_into_available(modal: &super::Model) -> Node<Msg> {
|
||||
div![C!["transform available"], div![types], div![execute]]
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn issue_type_select_option<'l>(ty: IssueType) -> ChildBuilder<'l> {
|
||||
ChildBuilder {
|
||||
name: ty.to_str(),
|
||||
label: ty.to_label(),
|
||||
value: ty.into(),
|
||||
class_list: ty.to_str(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn transform_into_unavailable(modal: &super::Model) -> Node<Msg> {
|
||||
let (n, s) = match modal.related_issues.len() {
|
||||
1 => (1.to_string(), "issue"),
|
||||
|
@ -1,4 +1,6 @@
|
||||
pub use {model::*, update::*, view::*};
|
||||
pub use model::*;
|
||||
pub use update::*;
|
||||
pub use view::*;
|
||||
|
||||
mod model;
|
||||
mod update;
|
||||
|
@ -1,8 +1,8 @@
|
||||
use {
|
||||
crate::{model::Model, Msg, OperationKind, ResourceKind},
|
||||
jirs_data::WsMsg,
|
||||
seed::prelude::*,
|
||||
};
|
||||
use jirs_data::WsMsg;
|
||||
use seed::prelude::*;
|
||||
|
||||
use crate::model::Model;
|
||||
use crate::{Msg, OperationKind, ResourceKind};
|
||||
|
||||
pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||
let _modal = match &mut model.modals_mut().delete_issue_status_modal {
|
||||
|
@ -1,8 +1,9 @@
|
||||
use {
|
||||
crate::{components::styled_confirm_modal::StyledConfirmModal, model, shared::ToNode, Msg},
|
||||
jirs_data::IssueStatusId,
|
||||
seed::prelude::*,
|
||||
};
|
||||
use jirs_data::IssueStatusId;
|
||||
use seed::prelude::*;
|
||||
|
||||
use crate::components::styled_confirm_modal::StyledConfirmModal;
|
||||
use crate::shared::ToNode;
|
||||
use crate::{model, Msg};
|
||||
|
||||
pub fn view(_model: &model::Model, issue_status_id: IssueStatusId) -> Node<Msg> {
|
||||
StyledConfirmModal {
|
||||
|
@ -1,4 +1,6 @@
|
||||
pub use {model::*, update::*, view::*};
|
||||
pub use model::*;
|
||||
pub use update::*;
|
||||
pub use view::*;
|
||||
|
||||
mod model;
|
||||
mod update;
|
||||
|
@ -1,17 +1,13 @@
|
||||
use {
|
||||
crate::{
|
||||
components::{
|
||||
styled_date_time_input::*, styled_input::*, styled_select::*, styled_select_child::*,
|
||||
},
|
||||
model::IssueModal,
|
||||
shared::{IntoChild, ToNode},
|
||||
FieldId, Msg,
|
||||
},
|
||||
derive_enum_iter::EnumIter,
|
||||
derive_enum_primitive::EnumPrimitive,
|
||||
jirs_data::{IssueFieldId, IssuePriority},
|
||||
seed::prelude::*,
|
||||
};
|
||||
use derive_enum_iter::EnumIter;
|
||||
use derive_enum_primitive::EnumPrimitive;
|
||||
use jirs_data::{IssueFieldId, IssuePriority};
|
||||
use seed::prelude::*;
|
||||
|
||||
use crate::components::styled_date_time_input::*;
|
||||
use crate::components::styled_input::*;
|
||||
use crate::components::styled_select::*;
|
||||
use crate::model::IssueModal;
|
||||
use crate::{FieldId, Msg};
|
||||
|
||||
#[derive(Copy, Clone, EnumPrimitive, EnumIter)]
|
||||
pub enum Type {
|
||||
@ -53,43 +49,6 @@ impl Type {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> IntoChild<'l> for Type {
|
||||
type Builder = StyledSelectChildBuilder<'l>;
|
||||
|
||||
fn into_child(self) -> Self::Builder {
|
||||
let name = match self {
|
||||
Type::Task => "Task",
|
||||
Type::Bug => "Bug",
|
||||
Type::Story => "Story",
|
||||
Type::Epic => "Epic",
|
||||
};
|
||||
let value: u32 = self.into();
|
||||
|
||||
let type_icon = {
|
||||
use crate::components::styled_icon::*;
|
||||
StyledIcon {
|
||||
icon: match self {
|
||||
Type::Task => Icon::Task,
|
||||
Type::Bug => Icon::Bug,
|
||||
Type::Story => Icon::Story,
|
||||
Type::Epic => Icon::Epic,
|
||||
},
|
||||
class_list: name,
|
||||
..Default::default()
|
||||
}
|
||||
.into_node()
|
||||
};
|
||||
|
||||
StyledSelectChildBuilder {
|
||||
class_list: name,
|
||||
text: Some(name),
|
||||
icon: Some(type_icon),
|
||||
value,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialOrd, PartialEq)]
|
||||
pub struct Model {
|
||||
pub priority: IssuePriority,
|
||||
|
@ -1,11 +1,10 @@
|
||||
use {
|
||||
crate::{
|
||||
components::styled_select::StyledSelectChanged, model::IssueModal, ws::send_ws_msg,
|
||||
FieldId, Msg, OperationKind, ResourceKind,
|
||||
},
|
||||
jirs_data::{IssueFieldId, UserId, WsMsg},
|
||||
seed::prelude::*,
|
||||
};
|
||||
use jirs_data::{IssueFieldId, UserId, WsMsg};
|
||||
use seed::prelude::*;
|
||||
|
||||
use crate::components::styled_select::StyledSelectChanged;
|
||||
use crate::model::IssueModal;
|
||||
use crate::ws::send_ws_msg;
|
||||
use crate::{FieldId, Msg, OperationKind, ResourceKind};
|
||||
|
||||
pub fn update(msg: &Msg, model: &mut crate::model::Model, orders: &mut impl Orders<Msg>) {
|
||||
let user_id = model.user_id().unwrap_or_default();
|
||||
|
@ -1,25 +1,23 @@
|
||||
use {
|
||||
crate::{
|
||||
components::{
|
||||
styled_button::StyledButton, styled_date_time_input::StyledDateTimeInput,
|
||||
styled_field::StyledField, styled_form::StyledForm, styled_input::StyledInput,
|
||||
styled_modal::StyledModal, styled_select::StyledSelect,
|
||||
styled_textarea::StyledTextarea,
|
||||
},
|
||||
modals::{
|
||||
epic_field,
|
||||
issues_create::{Model as AddIssueModal, Type},
|
||||
},
|
||||
model::Model,
|
||||
shared::{IntoChild, ToChild, ToNode},
|
||||
FieldId, Msg,
|
||||
},
|
||||
jirs_data::{IssueFieldId, IssuePriority},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use jirs_data::{IssueFieldId, IssuePriority, User};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::components::styled_button::ButtonVariant;
|
||||
use crate::components::styled_select::SelectVariant;
|
||||
use crate::components::styled_avatar::StyledAvatar;
|
||||
use crate::components::styled_button::{ButtonVariant, StyledButton};
|
||||
use crate::components::styled_date_time_input::StyledDateTimeInput;
|
||||
use crate::components::styled_field::StyledField;
|
||||
use crate::components::styled_form::StyledForm;
|
||||
use crate::components::styled_icon::{Icon, StyledIcon};
|
||||
use crate::components::styled_input::StyledInput;
|
||||
use crate::components::styled_modal::StyledModal;
|
||||
use crate::components::styled_select::{SelectVariant, StyledSelect};
|
||||
use crate::components::styled_select_child::StyledSelectChild;
|
||||
use crate::components::styled_textarea::StyledTextarea;
|
||||
use crate::modals::epic_field;
|
||||
use crate::modals::issues_create::{Model as AddIssueModal, Type};
|
||||
use crate::model::Model;
|
||||
use crate::shared::ToNode;
|
||||
use crate::{FieldId, Msg};
|
||||
|
||||
pub fn view(model: &Model, modal: &AddIssueModal) -> Node<Msg> {
|
||||
let issue_type = modal
|
||||
@ -40,27 +38,25 @@ pub fn view(model: &Model, modal: &AddIssueModal) -> Node<Msg> {
|
||||
Type::Epic => {
|
||||
let name_field = name_field(modal);
|
||||
|
||||
let starts = StyledField::build()
|
||||
.input(
|
||||
StyledDateTimeInput::build()
|
||||
.state(&modal.epic_starts_at_state)
|
||||
.build(FieldId::AddIssueModal(IssueFieldId::EpicStartsAt))
|
||||
.into_node(),
|
||||
)
|
||||
.label("Starts at")
|
||||
.build()
|
||||
.into_node();
|
||||
let starts = StyledField {
|
||||
input: StyledDateTimeInput::build()
|
||||
.state(&modal.epic_starts_at_state)
|
||||
.build(FieldId::AddIssueModal(IssueFieldId::EpicStartsAt))
|
||||
.into_node(),
|
||||
label: "Starts at",
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
|
||||
let end = StyledField::build()
|
||||
.input(
|
||||
StyledDateTimeInput::build()
|
||||
.state(&modal.epic_ends_at_state)
|
||||
.build(FieldId::AddIssueModal(IssueFieldId::EpicEndsAt))
|
||||
.into_node(),
|
||||
)
|
||||
.label("Ends at")
|
||||
.build()
|
||||
.into_node();
|
||||
let end = StyledField {
|
||||
input: StyledDateTimeInput::build()
|
||||
.state(&modal.epic_ends_at_state)
|
||||
.build(FieldId::AddIssueModal(IssueFieldId::EpicEndsAt))
|
||||
.into_node(),
|
||||
label: "Ends at",
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
|
||||
form.add_field(name_field).add_field(starts).add_field(end)
|
||||
}
|
||||
@ -129,19 +125,16 @@ fn issue_type_field(modal: &AddIssueModal) -> Node<Msg> {
|
||||
text_filter: modal.type_state.text_filter.as_str(),
|
||||
opened: modal.type_state.opened,
|
||||
valid: true,
|
||||
options: Some(Type::Task.into_iter().map(|t| t.into_child().name("type"))),
|
||||
selected: vec![{
|
||||
let v: Type = modal
|
||||
options: Some(Type::Task.into_iter().map(type_select_option)),
|
||||
selected: vec![type_select_option(
|
||||
modal
|
||||
.type_state
|
||||
.values
|
||||
.get(0)
|
||||
.cloned()
|
||||
.unwrap_or_default()
|
||||
.into();
|
||||
v
|
||||
}
|
||||
.into_child()
|
||||
.name("type")],
|
||||
.into(),
|
||||
)],
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
@ -154,6 +147,37 @@ fn issue_type_field(modal: &AddIssueModal) -> Node<Msg> {
|
||||
.into_node()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn type_select_option<'l>(t: Type) -> StyledSelectChild<'l> {
|
||||
let name = match t {
|
||||
Type::Task => "Task",
|
||||
Type::Bug => "Bug",
|
||||
Type::Story => "Story",
|
||||
Type::Epic => "Epic",
|
||||
};
|
||||
|
||||
StyledSelectChild {
|
||||
class_list: name,
|
||||
text: Some(name),
|
||||
icon: Some(
|
||||
StyledIcon {
|
||||
icon: match t {
|
||||
Type::Task => Icon::Task,
|
||||
Type::Bug => Icon::Bug,
|
||||
Type::Story => Icon::Story,
|
||||
Type::Epic => Icon::Epic,
|
||||
},
|
||||
class_list: name,
|
||||
..Default::default()
|
||||
}
|
||||
.into_node(),
|
||||
),
|
||||
name: Some("type"),
|
||||
value: t.into(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn short_summary_field(modal: &AddIssueModal) -> Node<Msg> {
|
||||
let short_summary = StyledInput {
|
||||
@ -199,13 +223,13 @@ fn reporter_field(model: &Model, modal: &AddIssueModal) -> Node<Msg> {
|
||||
variant: SelectVariant::Normal,
|
||||
text_filter: modal.reporter_state.text_filter.as_str(),
|
||||
opened: modal.reporter_state.opened,
|
||||
options: Some(model.users.iter().map(|u| u.to_child().name("reporter"))),
|
||||
options: Some(model.users.iter().map(reporter_select_option)),
|
||||
selected: model
|
||||
.users
|
||||
.iter()
|
||||
.filter_map(|user| {
|
||||
if user.id == reporter_id {
|
||||
Some(user.to_child().name("reporter"))
|
||||
Some(reporter_select_option(user))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -224,6 +248,25 @@ fn reporter_field(model: &Model, modal: &AddIssueModal) -> Node<Msg> {
|
||||
.into_node()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn reporter_select_option(user: &User) -> StyledSelectChild {
|
||||
StyledSelectChild {
|
||||
value: user.id as u32,
|
||||
icon: Some(
|
||||
StyledAvatar {
|
||||
size: 20,
|
||||
name: &user.name,
|
||||
avatar_url: user.avatar_url.as_deref(),
|
||||
..StyledAvatar::default()
|
||||
}
|
||||
.into_node(),
|
||||
),
|
||||
text: Some(user.name.as_str()),
|
||||
name: Some("reporter"),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn assignees_field(model: &Model, modal: &AddIssueModal) -> Node<Msg> {
|
||||
let assignees = StyledSelect {
|
||||
id: FieldId::AddIssueModal(IssueFieldId::Assignees),
|
||||
@ -231,13 +274,13 @@ fn assignees_field(model: &Model, modal: &AddIssueModal) -> Node<Msg> {
|
||||
is_multi: true,
|
||||
text_filter: modal.assignees_state.text_filter.as_str(),
|
||||
opened: modal.assignees_state.opened,
|
||||
options: Some(model.users.iter().map(|u| u.to_child().name("assignees"))),
|
||||
options: Some(model.users.iter().map(assignee_select_option)),
|
||||
selected: model
|
||||
.users
|
||||
.iter()
|
||||
.filter_map(|user| {
|
||||
if modal.user_ids.contains(&user.id) {
|
||||
Some(user.to_child().name("assignees"))
|
||||
Some(assignee_select_option(user))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -248,12 +291,32 @@ fn assignees_field(model: &Model, modal: &AddIssueModal) -> Node<Msg> {
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
StyledField::build()
|
||||
.input(assignees)
|
||||
.label("Assignees")
|
||||
.tip("")
|
||||
.build()
|
||||
.into_node()
|
||||
StyledField {
|
||||
input: assignees,
|
||||
label: "Assignees",
|
||||
tip: Some(""),
|
||||
..Default::default()
|
||||
}
|
||||
.into_node()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn assignee_select_option(user: &User) -> StyledSelectChild {
|
||||
StyledSelectChild {
|
||||
value: user.id as u32,
|
||||
icon: Some(
|
||||
StyledAvatar {
|
||||
size: 20,
|
||||
name: &user.name,
|
||||
avatar_url: user.avatar_url.as_deref(),
|
||||
..StyledAvatar::default()
|
||||
}
|
||||
.into_node(),
|
||||
),
|
||||
text: Some(user.name.as_str()),
|
||||
name: Some("assignees"),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn issue_priority_field(modal: &AddIssueModal) -> Node<Msg> {
|
||||
@ -265,8 +328,8 @@ fn issue_priority_field(modal: &AddIssueModal) -> Node<Msg> {
|
||||
text_filter: modal.priority_state.text_filter.as_str(),
|
||||
opened: modal.priority_state.opened,
|
||||
valid: true,
|
||||
options: Some(priorities.map(|p| p.into_child().name("priority"))),
|
||||
selected: vec![modal.priority.into_child().name("priority")],
|
||||
options: Some(priorities.map(priority_select_option)),
|
||||
selected: vec![priority_select_option(modal.priority)],
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
@ -279,6 +342,24 @@ fn issue_priority_field(modal: &AddIssueModal) -> Node<Msg> {
|
||||
.into_node()
|
||||
}
|
||||
|
||||
fn priority_select_option<'l>(priority: IssuePriority) -> StyledSelectChild<'l> {
|
||||
StyledSelectChild {
|
||||
icon: Some(
|
||||
StyledIcon {
|
||||
icon: priority.clone().into(),
|
||||
class_list: priority.to_str(),
|
||||
..Default::default()
|
||||
}
|
||||
.into_node(),
|
||||
),
|
||||
text: Some(priority.to_str()),
|
||||
class_list: priority.to_str(),
|
||||
value: priority.into(),
|
||||
name: Some("priority"),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn name_field(modal: &AddIssueModal) -> Node<Msg> {
|
||||
let name = StyledInput {
|
||||
value: modal.title_state.value.as_str(),
|
||||
|
@ -1,4 +1,6 @@
|
||||
pub use {model::*, update::*, view::*};
|
||||
pub use model::*;
|
||||
pub use update::*;
|
||||
pub use view::*;
|
||||
|
||||
mod model;
|
||||
mod update;
|
||||
|
@ -1,7 +1,8 @@
|
||||
use {
|
||||
crate::{components::styled_confirm_modal::StyledConfirmModal, model, shared::ToNode, Msg},
|
||||
seed::prelude::*,
|
||||
};
|
||||
use seed::prelude::*;
|
||||
|
||||
use crate::components::styled_confirm_modal::StyledConfirmModal;
|
||||
use crate::shared::ToNode;
|
||||
use crate::{model, Msg};
|
||||
|
||||
pub fn view(model: &model::Model) -> Node<Msg> {
|
||||
let issue_id = match &model.modals().delete_issue_confirm {
|
||||
|
@ -1,4 +1,6 @@
|
||||
pub use {model::*, update::*, view::*};
|
||||
pub use model::*;
|
||||
pub use update::*;
|
||||
pub use view::*;
|
||||
|
||||
mod model;
|
||||
mod update;
|
||||
|
@ -1,17 +1,13 @@
|
||||
use {
|
||||
crate::{
|
||||
components::{
|
||||
styled_date_time_input::StyledDateTimeInputState, styled_editor::Mode,
|
||||
styled_editor::StyledEditorState, styled_input::StyledInputState,
|
||||
styled_select::StyledSelectState,
|
||||
},
|
||||
modals::time_tracking::value_for_time_tracking,
|
||||
model::{CommentForm, IssueModal},
|
||||
EditIssueModalSection, FieldId, Msg,
|
||||
},
|
||||
jirs_data::{Issue, IssueFieldId, IssueId, TimeTracking, UpdateIssuePayload},
|
||||
seed::prelude::*,
|
||||
};
|
||||
use jirs_data::{Issue, IssueFieldId, IssueId, TimeTracking, UpdateIssuePayload};
|
||||
use seed::prelude::*;
|
||||
|
||||
use crate::components::styled_date_time_input::StyledDateTimeInputState;
|
||||
use crate::components::styled_editor::{Mode, StyledEditorState};
|
||||
use crate::components::styled_input::StyledInputState;
|
||||
use crate::components::styled_select::StyledSelectState;
|
||||
use crate::modals::time_tracking::value_for_time_tracking;
|
||||
use crate::model::{CommentForm, IssueModal};
|
||||
use crate::{EditIssueModalSection, FieldId, Msg};
|
||||
|
||||
#[derive(Clone, Debug, PartialOrd, PartialEq)]
|
||||
pub struct Model {
|
||||
|
@ -1,13 +1,10 @@
|
||||
use {
|
||||
crate::{
|
||||
components::styled_select::StyledSelectChanged,
|
||||
model::{IssueModal, Model},
|
||||
ws::send_ws_msg,
|
||||
EditIssueModalSection, FieldChange, FieldId, Msg, OperationKind, ResourceKind,
|
||||
},
|
||||
jirs_data::*,
|
||||
seed::prelude::*,
|
||||
};
|
||||
use jirs_data::*;
|
||||
use seed::prelude::*;
|
||||
|
||||
use crate::components::styled_select::StyledSelectChanged;
|
||||
use crate::model::{IssueModal, Model};
|
||||
use crate::ws::send_ws_msg;
|
||||
use crate::{EditIssueModalSection, FieldChange, FieldId, Msg, OperationKind, ResourceKind};
|
||||
|
||||
pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||
let modal = match &mut model.modals.edit_issue {
|
||||
@ -303,7 +300,6 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||
}
|
||||
//
|
||||
// comments
|
||||
//
|
||||
Msg::StrInputChanged(
|
||||
FieldId::EditIssueModal(EditIssueModalSection::Comment(CommentFieldId::Body)),
|
||||
text,
|
||||
|
@ -1,26 +1,27 @@
|
||||
use {
|
||||
crate::{
|
||||
components::{
|
||||
styled_avatar::StyledAvatar, styled_button::StyledButton, styled_editor::StyledEditor,
|
||||
styled_field::StyledField, styled_icon::Icon, styled_input::StyledInput,
|
||||
styled_modal::*, styled_select::StyledSelect,
|
||||
},
|
||||
modals::{
|
||||
epic_field, issues_edit::Model as EditIssueModal, time_tracking::time_tracking_field,
|
||||
},
|
||||
model::{ModalType, Model},
|
||||
shared::{tracking_widget::tracking_link, IntoChild, ToChild, ToNode},
|
||||
EditIssueModalSection, FieldChange, FieldId, Msg,
|
||||
},
|
||||
comments::*,
|
||||
jirs_data::{CommentFieldId, IssueFieldId, IssuePriority, IssueType, TimeTracking},
|
||||
seed::{prelude::*, *},
|
||||
use comments::*;
|
||||
use jirs_data::{
|
||||
CommentFieldId, IssueFieldId, IssuePriority, IssueStatus, IssueType, TimeTracking,
|
||||
UpdateIssuePayload, User,
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::components::styled_button::ButtonVariant;
|
||||
use crate::components::styled_icon::StyledIcon;
|
||||
use crate::components::styled_select::SelectVariant;
|
||||
use crate::components::styled_select_child::StyledSelectChildBuilder;
|
||||
use crate::components::styled_avatar::StyledAvatar;
|
||||
use crate::components::styled_button::{ButtonVariant, StyledButton};
|
||||
use crate::components::styled_editor::StyledEditor;
|
||||
use crate::components::styled_field::StyledField;
|
||||
use crate::components::styled_icon::{Icon, StyledIcon};
|
||||
use crate::components::styled_input::StyledInput;
|
||||
use crate::components::styled_modal::*;
|
||||
use crate::components::styled_select::{SelectVariant, StyledSelect, StyledSelectState};
|
||||
use crate::components::styled_select_child::StyledSelectChild;
|
||||
use crate::modals::epic_field;
|
||||
use crate::modals::issues_edit::Model as EditIssueModal;
|
||||
use crate::modals::time_tracking::time_tracking_field;
|
||||
use crate::model::{ModalType, Model};
|
||||
use crate::shared::tracking_widget::tracking_link;
|
||||
use crate::shared::ToNode;
|
||||
use crate::{EditIssueModalSection, FieldChange, FieldId, Msg};
|
||||
|
||||
mod comments;
|
||||
|
||||
@ -149,27 +150,9 @@ fn modal_header(_model: &Model, modal: &EditIssueModal) -> Node<Msg> {
|
||||
options: Some(
|
||||
IssueType::default()
|
||||
.into_iter()
|
||||
.map(|t| t.into_child().name("type")),
|
||||
.map(|t| type_select_option(t, &text)),
|
||||
),
|
||||
selected: vec![{
|
||||
let name = payload.issue_type.to_label();
|
||||
|
||||
let type_icon = StyledIcon {
|
||||
icon: payload.issue_type.clone().into(),
|
||||
class_list: name,
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
|
||||
StyledSelectChildBuilder {
|
||||
class_list: name,
|
||||
text: Some(&text),
|
||||
icon: Some(type_icon),
|
||||
value: payload.issue_type.into(),
|
||||
name: Some("type"),
|
||||
..Default::default()
|
||||
}
|
||||
}],
|
||||
selected: vec![type_select_option(payload.issue_type, &text)],
|
||||
..Default::default()
|
||||
}
|
||||
.into_node()
|
||||
@ -187,6 +170,26 @@ fn modal_header(_model: &Model, modal: &EditIssueModal) -> Node<Msg> {
|
||||
]
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn type_select_option<'l>(t: IssueType, text: &'l str) -> StyledSelectChild<'l> {
|
||||
let name = t.to_label();
|
||||
StyledSelectChild {
|
||||
class_list: name,
|
||||
text: Some(text),
|
||||
icon: Some(
|
||||
StyledIcon {
|
||||
icon: t.clone().into(),
|
||||
class_list: name,
|
||||
..Default::default()
|
||||
}
|
||||
.into_node(),
|
||||
),
|
||||
value: t.into(),
|
||||
name: Some("type"),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn left_modal_column(model: &Model, modal: &EditIssueModal) -> Node<Msg> {
|
||||
let EditIssueModal {
|
||||
payload,
|
||||
@ -220,7 +223,11 @@ fn left_modal_column(model: &Model, modal: &EditIssueModal) -> Node<Msg> {
|
||||
}
|
||||
.into_node()
|
||||
};
|
||||
let description_field = StyledField::build().input(description).build().into_node();
|
||||
let description_field = StyledField {
|
||||
input: description,
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
|
||||
let user_avatar = StyledAvatar {
|
||||
avatar_url: model.user.as_ref().and_then(|u| u.avatar_url.as_deref()),
|
||||
@ -283,110 +290,13 @@ fn right_modal_column(model: &Model, modal: &EditIssueModal) -> Node<Msg> {
|
||||
..
|
||||
} = modal;
|
||||
|
||||
let status = StyledSelect {
|
||||
id: FieldId::EditIssueModal(EditIssueModalSection::Issue(IssueFieldId::IssueStatusId)),
|
||||
name: "status",
|
||||
opened: status_state.opened,
|
||||
variant: SelectVariant::Normal,
|
||||
text_filter: status_state.text_filter.as_str(),
|
||||
options: Some(
|
||||
model
|
||||
.issue_statuses
|
||||
.iter()
|
||||
.map(|opt| opt.to_child().name("status")),
|
||||
),
|
||||
selected: model
|
||||
.issue_statuses
|
||||
.iter()
|
||||
.filter(|is| is.id == payload.issue_status_id)
|
||||
.map(|is| is.to_child().name("status"))
|
||||
.collect(),
|
||||
let status_field = status_select(model, payload, status_state);
|
||||
|
||||
valid: true,
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
let status_field = StyledField::build()
|
||||
.input(status)
|
||||
.label("Status")
|
||||
.build()
|
||||
.into_node();
|
||||
let assignees_field = assignees_select(model, payload, assignees_state);
|
||||
|
||||
let assignees = StyledSelect {
|
||||
id: FieldId::EditIssueModal(EditIssueModalSection::Issue(IssueFieldId::Assignees)),
|
||||
name: "assignees",
|
||||
variant: SelectVariant::Empty,
|
||||
is_multi: true,
|
||||
opened: assignees_state.opened,
|
||||
text_filter: assignees_state.text_filter.as_str(),
|
||||
options: Some(
|
||||
model
|
||||
.users
|
||||
.iter()
|
||||
.map(|user| user.to_child().name("assignees")),
|
||||
),
|
||||
selected: model
|
||||
.users
|
||||
.iter()
|
||||
.filter(|user| payload.user_ids.contains(&user.id))
|
||||
.map(|user| user.to_child().name("assignees"))
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
let assignees_field = StyledField::build()
|
||||
.input(assignees)
|
||||
.label("Assignees")
|
||||
.build()
|
||||
.into_node();
|
||||
let reporter_field = reporters_select(model, payload, reporter_state);
|
||||
|
||||
let reporter = StyledSelect {
|
||||
id: FieldId::EditIssueModal(EditIssueModalSection::Issue(IssueFieldId::Reporter)),
|
||||
name: "reporter",
|
||||
opened: reporter_state.opened,
|
||||
variant: SelectVariant::Empty,
|
||||
text_filter: reporter_state.text_filter.as_str(),
|
||||
options: Some(
|
||||
model
|
||||
.users
|
||||
.iter()
|
||||
.map(|user| user.to_child().name("reporter")),
|
||||
),
|
||||
selected: model
|
||||
.users
|
||||
.iter()
|
||||
.filter(|user| payload.reporter_id == user.id)
|
||||
.map(|user| user.to_child().name("reporter"))
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
let reporter_field = StyledField::build()
|
||||
.input(reporter)
|
||||
.label("Reporter")
|
||||
.build()
|
||||
.into_node();
|
||||
|
||||
let priority = StyledSelect {
|
||||
id: FieldId::EditIssueModal(EditIssueModalSection::Issue(IssueFieldId::Priority)),
|
||||
name: "priority",
|
||||
variant: SelectVariant::Empty,
|
||||
opened: priority_state.opened,
|
||||
text_filter: priority_state.text_filter.as_str(),
|
||||
options: Some(
|
||||
IssuePriority::default()
|
||||
.into_iter()
|
||||
.map(|p| p.into_child().name("priority")),
|
||||
),
|
||||
selected: vec![payload.priority.into_child().name("priority")],
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
let priority_field = StyledField::build()
|
||||
.input(priority)
|
||||
.label("Priority")
|
||||
.build()
|
||||
.into_node();
|
||||
let priority_field = priorities_select(payload, priority_state);
|
||||
|
||||
let time_tracking_type = model
|
||||
.project
|
||||
@ -404,12 +314,13 @@ fn right_modal_column(model: &Model, modal: &EditIssueModal) -> Node<Msg> {
|
||||
);
|
||||
|
||||
let tracking = tracking_link(model, modal);
|
||||
let tracking_field = StyledField::build()
|
||||
.label("TIME TRACKING")
|
||||
.tip("")
|
||||
.input(tracking)
|
||||
.build()
|
||||
.into_node();
|
||||
let tracking_field = StyledField {
|
||||
label: "TIME TRACKING",
|
||||
tip: Some(""),
|
||||
input: tracking,
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
(estimate_field, tracking_field)
|
||||
} else {
|
||||
(Node::Empty, Node::Empty)
|
||||
@ -433,3 +344,192 @@ fn right_modal_column(model: &Model, modal: &EditIssueModal) -> Node<Msg> {
|
||||
epic_field,
|
||||
]
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn priorities_select(
|
||||
payload: &UpdateIssuePayload,
|
||||
priority_state: &StyledSelectState,
|
||||
) -> Node<Msg> {
|
||||
let priority = StyledSelect {
|
||||
id: FieldId::EditIssueModal(EditIssueModalSection::Issue(IssueFieldId::Priority)),
|
||||
name: "priority",
|
||||
variant: SelectVariant::Empty,
|
||||
opened: priority_state.opened,
|
||||
text_filter: priority_state.text_filter.as_str(),
|
||||
options: Some(
|
||||
IssuePriority::default()
|
||||
.into_iter()
|
||||
.map(priority_select_option),
|
||||
),
|
||||
selected: vec![priority_select_option(payload.priority)],
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
StyledField {
|
||||
label: "Priority",
|
||||
input: priority,
|
||||
..Default::default()
|
||||
}
|
||||
.into_node()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn priority_select_option<'l>(ip: IssuePriority) -> StyledSelectChild<'l> {
|
||||
StyledSelectChild {
|
||||
icon: Some(
|
||||
StyledIcon {
|
||||
icon: ip.clone().into(),
|
||||
class_list: ip.to_str(),
|
||||
..Default::default()
|
||||
}
|
||||
.into_node(),
|
||||
),
|
||||
text: Some(ip.to_str()),
|
||||
class_list: ip.to_str(),
|
||||
value: ip.into(),
|
||||
name: Some("priority"),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn status_select(
|
||||
model: &Model,
|
||||
payload: &UpdateIssuePayload,
|
||||
status_state: &StyledSelectState,
|
||||
) -> Node<Msg> {
|
||||
let status = StyledSelect {
|
||||
id: FieldId::EditIssueModal(EditIssueModalSection::Issue(IssueFieldId::IssueStatusId)),
|
||||
name: "status",
|
||||
opened: status_state.opened,
|
||||
variant: SelectVariant::Normal,
|
||||
text_filter: status_state.text_filter.as_str(),
|
||||
options: Some(model.issue_statuses.iter().map(issue_status_select_option)),
|
||||
selected: model
|
||||
.issue_statuses
|
||||
.iter()
|
||||
.filter(|is| is.id == payload.issue_status_id)
|
||||
.map(issue_status_select_option)
|
||||
.collect(),
|
||||
|
||||
valid: true,
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
StyledField {
|
||||
label: "Status",
|
||||
input: status,
|
||||
..Default::default()
|
||||
}
|
||||
.into_node()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn issue_status_select_option<'l>(is: &'l IssueStatus) -> StyledSelectChild<'l> {
|
||||
StyledSelectChild {
|
||||
value: is.id as u32,
|
||||
class_list: is.name.as_str(),
|
||||
text: Some(is.name.as_str()),
|
||||
name: Some("status"),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn reporters_select(
|
||||
model: &Model,
|
||||
payload: &UpdateIssuePayload,
|
||||
reporter_state: &StyledSelectState,
|
||||
) -> Node<Msg> {
|
||||
let reporter = StyledSelect {
|
||||
id: FieldId::EditIssueModal(EditIssueModalSection::Issue(IssueFieldId::Reporter)),
|
||||
name: "reporter",
|
||||
opened: reporter_state.opened,
|
||||
variant: SelectVariant::Empty,
|
||||
text_filter: reporter_state.text_filter.as_str(),
|
||||
options: Some(model.users.iter().map(reporter_select_option)),
|
||||
selected: model
|
||||
.users
|
||||
.iter()
|
||||
.filter(|user| payload.reporter_id == user.id)
|
||||
.map(reporter_select_option)
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
StyledField {
|
||||
label: "Reporter",
|
||||
input: reporter,
|
||||
..Default::default()
|
||||
}
|
||||
.into_node()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn reporter_select_option<'l>(user: &'l User) -> StyledSelectChild<'l> {
|
||||
StyledSelectChild {
|
||||
value: user.id as u32,
|
||||
icon: Some(
|
||||
StyledAvatar {
|
||||
size: 20,
|
||||
name: &user.name,
|
||||
avatar_url: user.avatar_url.as_deref(),
|
||||
..StyledAvatar::default()
|
||||
}
|
||||
.into_node(),
|
||||
),
|
||||
text: Some(user.name.as_str()),
|
||||
name: Some("reporter"),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn assignees_select(
|
||||
model: &Model,
|
||||
payload: &UpdateIssuePayload,
|
||||
assignees_state: &StyledSelectState,
|
||||
) -> Node<Msg> {
|
||||
let assignees = StyledSelect {
|
||||
id: FieldId::EditIssueModal(EditIssueModalSection::Issue(IssueFieldId::Assignees)),
|
||||
name: "assignees",
|
||||
variant: SelectVariant::Empty,
|
||||
is_multi: true,
|
||||
opened: assignees_state.opened,
|
||||
text_filter: assignees_state.text_filter.as_str(),
|
||||
options: Some(model.users.iter().map(assignee_select_option)),
|
||||
selected: model
|
||||
.users
|
||||
.iter()
|
||||
.filter(|user| payload.user_ids.contains(&user.id))
|
||||
.map(assignee_select_option)
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
StyledField {
|
||||
input: assignees,
|
||||
label: "Assignees",
|
||||
..Default::default()
|
||||
}
|
||||
.into_node()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn assignee_select_option<'l>(user: &'l User) -> StyledSelectChild<'l> {
|
||||
StyledSelectChild {
|
||||
value: user.id as u32,
|
||||
icon: Some(
|
||||
StyledAvatar {
|
||||
size: 20,
|
||||
name: &user.name,
|
||||
avatar_url: user.avatar_url.as_deref(),
|
||||
..StyledAvatar::default()
|
||||
}
|
||||
.into_node(),
|
||||
),
|
||||
text: Some(user.name.as_str()),
|
||||
name: Some("assignees"),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,14 @@
|
||||
use {
|
||||
crate::{
|
||||
components::{
|
||||
styled_avatar::StyledAvatar, styled_button::StyledButton,
|
||||
styled_textarea::StyledTextarea,
|
||||
},
|
||||
modals::issues_edit::Model as EditIssueModal,
|
||||
model::{CommentForm, ModalType, Model},
|
||||
shared::ToNode,
|
||||
EditIssueModalSection, FieldChange, FieldId, Msg,
|
||||
},
|
||||
jirs_data::{Comment, CommentFieldId},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use jirs_data::{Comment, CommentFieldId};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::components::styled_button::ButtonVariant;
|
||||
use crate::components::styled_avatar::StyledAvatar;
|
||||
use crate::components::styled_button::{ButtonVariant, StyledButton};
|
||||
use crate::components::styled_textarea::StyledTextarea;
|
||||
use crate::modals::issues_edit::Model as EditIssueModal;
|
||||
use crate::model::{CommentForm, ModalType, Model};
|
||||
use crate::shared::ToNode;
|
||||
use crate::{EditIssueModalSection, FieldChange, FieldId, Msg};
|
||||
|
||||
pub fn build_comment_form(form: &CommentForm) -> Vec<Node<Msg>> {
|
||||
let submit_comment_form = mouse_ev(Ev::Click, move |ev| {
|
||||
|
@ -1,4 +1,6 @@
|
||||
pub use {epic_field::*, update::*, view::*};
|
||||
pub use epic_field::*;
|
||||
pub use update::*;
|
||||
pub use view::*;
|
||||
|
||||
pub mod comments_delete;
|
||||
#[cfg(debug_assertions)]
|
||||
|
@ -1,4 +1,6 @@
|
||||
pub use {model::*, update::*, view::*};
|
||||
pub use model::*;
|
||||
pub use update::*;
|
||||
pub use view::*;
|
||||
|
||||
mod model;
|
||||
mod update;
|
||||
|
@ -1,22 +1,17 @@
|
||||
use {
|
||||
crate::{
|
||||
components::{
|
||||
styled_button::StyledButton,
|
||||
styled_field::StyledField,
|
||||
styled_input::{StyledInput, StyledInputState},
|
||||
styled_modal::StyledModal,
|
||||
styled_select::{StyledSelect, StyledSelectState},
|
||||
},
|
||||
model::Model,
|
||||
shared::{
|
||||
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 seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::components::styled_button::StyledButton;
|
||||
use crate::components::styled_field::StyledField;
|
||||
use crate::components::styled_input::{StyledInput, StyledInputState};
|
||||
use crate::components::styled_modal::StyledModal;
|
||||
use crate::components::styled_select::{StyledSelect, StyledSelectState};
|
||||
use crate::components::styled_select_child::StyledSelectChild;
|
||||
use crate::model::Model;
|
||||
use crate::shared::tracking_widget::{fibonacci_value_name, fibonacci_values, tracking_widget};
|
||||
use crate::shared::ToNode;
|
||||
use crate::{EditIssueModalSection, FieldId, Msg};
|
||||
|
||||
pub fn value_for_time_tracking(v: &Option<i32>, time_tracking_type: &TimeTracking) -> String {
|
||||
match (time_tracking_type, v.as_ref()) {
|
||||
@ -85,7 +80,7 @@ pub fn view(model: &Model, modal: &super::Model) -> Node<Msg> {
|
||||
.into_node()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[inline(always)]
|
||||
pub fn time_tracking_field(
|
||||
time_tracking_type: TimeTracking,
|
||||
field_id: FieldId,
|
||||
@ -101,12 +96,18 @@ pub fn time_tracking_field(
|
||||
selected: select_state
|
||||
.values
|
||||
.iter()
|
||||
.map(|n| (*n).to_child())
|
||||
.copied()
|
||||
.map(fibonacci_value_select_option)
|
||||
.collect(),
|
||||
|
||||
text_filter: select_state.text_filter.as_str(),
|
||||
opened: select_state.opened,
|
||||
options: Some(fibonacci_values.iter().map(|v| v.to_child())),
|
||||
options: Some(
|
||||
fibonacci_values
|
||||
.iter()
|
||||
.copied()
|
||||
.map(fibonacci_value_select_option),
|
||||
),
|
||||
..Default::default()
|
||||
}
|
||||
.into_node(),
|
||||
@ -125,3 +126,14 @@ pub fn time_tracking_field(
|
||||
}
|
||||
.into_node()
|
||||
}
|
||||
|
||||
fn fibonacci_value_select_option<'l>(value: u32) -> StyledSelectChild<'l> {
|
||||
let name = fibonacci_value_name(value);
|
||||
|
||||
StyledSelectChild {
|
||||
class_list: name,
|
||||
text: Some(name),
|
||||
value,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,11 @@
|
||||
use jirs_data::{CommentId, IssueStatusId};
|
||||
use {
|
||||
crate::{
|
||||
model::{ModalType, Model, Page},
|
||||
shared::go_to_board,
|
||||
ws::send_ws_msg,
|
||||
FieldChange, FieldId, Msg, OperationKind, ResourceKind,
|
||||
},
|
||||
jirs_data::{EpicId, IssueId, TimeTracking, WsMsg},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use jirs_data::{CommentId, EpicId, IssueId, IssueStatusId, TimeTracking, WsMsg};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::model::{ModalType, Model, Page};
|
||||
use crate::shared::go_to_board;
|
||||
use crate::ws::send_ws_msg;
|
||||
use crate::{FieldChange, FieldId, Msg, OperationKind, ResourceKind};
|
||||
|
||||
pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||
match msg {
|
||||
|
@ -1,7 +1,8 @@
|
||||
use {
|
||||
crate::{model::*, Msg},
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::model::*;
|
||||
use crate::Msg;
|
||||
|
||||
pub fn view(model: &Model) -> Node<Msg> {
|
||||
let nodes = model
|
||||
|
@ -1,20 +1,21 @@
|
||||
use {
|
||||
crate::{
|
||||
components::styled_select::StyledSelectState,
|
||||
pages::{
|
||||
invite_page::InvitePage, profile_page::model::ProfilePage,
|
||||
project_page::model::ProjectPage, project_settings_page::ProjectSettingsPage,
|
||||
reports_page::model::ReportsPage, sign_in_page::model::SignInPage,
|
||||
sign_up_page::model::SignUpPage, users_page::model::UsersPage,
|
||||
},
|
||||
Msg,
|
||||
},
|
||||
jirs_data::*,
|
||||
seed::{app::Orders, browser::web_socket::WebSocket},
|
||||
serde::{Deserialize, Serialize},
|
||||
std::collections::hash_map::HashMap,
|
||||
uuid::Uuid,
|
||||
};
|
||||
use std::collections::hash_map::HashMap;
|
||||
|
||||
use jirs_data::*;
|
||||
use seed::app::Orders;
|
||||
use seed::browser::web_socket::WebSocket;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::components::styled_select::StyledSelectState;
|
||||
use crate::pages::invite_page::InvitePage;
|
||||
use crate::pages::profile_page::model::ProfilePage;
|
||||
use crate::pages::project_page::model::ProjectPage;
|
||||
use crate::pages::project_settings_page::ProjectSettingsPage;
|
||||
use crate::pages::reports_page::model::ReportsPage;
|
||||
use crate::pages::sign_in_page::model::SignInPage;
|
||||
use crate::pages::sign_up_page::model::SignUpPage;
|
||||
use crate::pages::users_page::model::UsersPage;
|
||||
use crate::Msg;
|
||||
|
||||
pub trait IssueModal {
|
||||
fn epic_id_value(&self) -> Option<u32>;
|
||||
|
@ -1,4 +1,6 @@
|
||||
pub use {model::*, update::*, view::*};
|
||||
pub use model::*;
|
||||
pub use update::*;
|
||||
pub use view::*;
|
||||
|
||||
mod model;
|
||||
mod update;
|
||||
|
@ -1,15 +1,15 @@
|
||||
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,
|
||||
use std::str::FromStr;
|
||||
|
||||
use jirs_data::fields::*;
|
||||
use jirs_data::WsMsg;
|
||||
use seed::prelude::*;
|
||||
|
||||
use crate::model::{Model, Page, PageContent};
|
||||
use crate::pages::invite_page::InvitePage;
|
||||
use crate::shared::write_auth_token;
|
||||
use crate::ws::send_ws_msg;
|
||||
use crate::{
|
||||
authorize_or_redirect, FieldId, InvitationPageChange, Msg, PageChanged, WebSocketChanged,
|
||||
};
|
||||
|
||||
pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||
|
@ -1,21 +1,16 @@
|
||||
use {
|
||||
crate::{
|
||||
components::{
|
||||
styled_button::StyledButton, styled_field::StyledField, styled_form::StyledForm,
|
||||
styled_input::StyledInput,
|
||||
},
|
||||
match_page,
|
||||
model::{Model, PageContent},
|
||||
pages::invite_page::InvitePage,
|
||||
shared::{outer_layout, ToNode},
|
||||
validations::is_token,
|
||||
FieldId, InvitationPageChange, Msg, PageChanged,
|
||||
},
|
||||
jirs_data::fields::*,
|
||||
seed::{prelude::*, *},
|
||||
};
|
||||
use jirs_data::fields::*;
|
||||
use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::components::styled_button::ButtonVariant;
|
||||
use crate::components::styled_button::{ButtonVariant, StyledButton};
|
||||
use crate::components::styled_field::StyledField;
|
||||
use crate::components::styled_form::StyledForm;
|
||||
use crate::components::styled_input::StyledInput;
|
||||
use crate::model::{Model, PageContent};
|
||||
use crate::pages::invite_page::InvitePage;
|
||||
use crate::shared::{outer_layout, ToNode};
|
||||
use crate::validations::is_token;
|
||||
use crate::{match_page, FieldId, InvitationPageChange, Msg, PageChanged};
|
||||
|
||||
pub fn view(model: &Model) -> Node<Msg> {
|
||||
let page = match_page!(model, Invite; Empty);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user