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