2020-04-05 15:15:09 +02:00
|
|
|
#[macro_use]
|
|
|
|
extern crate lazy_static;
|
|
|
|
|
2020-03-30 14:26:25 +02:00
|
|
|
use seed::fetch::FetchObject;
|
2020-03-30 08:16:26 +02:00
|
|
|
use seed::{prelude::*, *};
|
2020-03-27 12:17:27 +01:00
|
|
|
|
2020-03-31 22:05:18 +02:00
|
|
|
use jirs_data::IssueStatus;
|
|
|
|
|
2020-04-05 15:15:09 +02:00
|
|
|
use crate::api::ws;
|
|
|
|
use crate::model::{ModalType, Model, Page};
|
2020-04-02 08:45:43 +02:00
|
|
|
use crate::shared::styled_select::StyledSelectChange;
|
2020-03-30 23:19:00 +02:00
|
|
|
|
2020-03-30 14:26:25 +02:00
|
|
|
mod api;
|
2020-03-31 22:05:18 +02:00
|
|
|
mod api_handlers;
|
2020-03-30 14:26:25 +02:00
|
|
|
mod login;
|
2020-04-02 19:32:40 +02:00
|
|
|
mod modal;
|
2020-03-30 08:16:26 +02:00
|
|
|
mod model;
|
2020-03-30 14:26:25 +02:00
|
|
|
mod project;
|
|
|
|
mod project_settings;
|
|
|
|
mod register;
|
|
|
|
mod shared;
|
2020-03-30 08:16:26 +02:00
|
|
|
|
2020-03-31 11:11:06 +02:00
|
|
|
pub type UserId = i32;
|
2020-03-31 22:05:18 +02:00
|
|
|
pub type IssueId = i32;
|
2020-03-31 11:11:06 +02:00
|
|
|
pub type AvatarFilterActive = bool;
|
|
|
|
|
2020-04-02 08:45:43 +02:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub enum FieldId {
|
2020-04-05 15:15:09 +02:00
|
|
|
// edit issue
|
2020-04-02 08:45:43 +02:00
|
|
|
IssueTypeEditModalTop,
|
2020-04-05 15:15:09 +02:00
|
|
|
// project boards
|
|
|
|
TextFilterBoard,
|
|
|
|
//
|
2020-04-03 16:15:56 +02:00
|
|
|
CopyButtonLabel,
|
2020-04-05 15:15:09 +02:00
|
|
|
// add issue
|
2020-04-04 17:42:02 +02:00
|
|
|
IssueTypeAddIssueModal,
|
2020-04-05 15:15:09 +02:00
|
|
|
SummaryAddIssueModal,
|
|
|
|
DescriptionAddIssueModal,
|
2020-04-03 16:15:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub enum FieldChange {
|
|
|
|
LinkCopied(FieldId, bool),
|
2020-04-02 08:45:43 +02:00
|
|
|
}
|
|
|
|
|
2020-03-30 14:26:25 +02:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub enum Msg {
|
2020-03-31 22:05:18 +02:00
|
|
|
NoOp,
|
2020-04-02 08:45:43 +02:00
|
|
|
StyledSelectChanged(FieldId, StyledSelectChange),
|
|
|
|
|
2020-03-30 14:26:25 +02:00
|
|
|
ChangePage(model::Page),
|
|
|
|
CurrentProjectResult(FetchObject<String>),
|
|
|
|
CurrentUserResult(FetchObject<String>),
|
|
|
|
InternalFailure(String),
|
2020-03-30 23:19:00 +02:00
|
|
|
ToggleAboutTooltip,
|
2020-03-31 08:56:46 +02:00
|
|
|
|
|
|
|
// project
|
|
|
|
ProjectTextFilterChanged(String),
|
2020-03-31 11:11:06 +02:00
|
|
|
ProjectAvatarFilterChanged(UserId, AvatarFilterActive),
|
|
|
|
ProjectToggleOnlyMy,
|
2020-03-31 11:36:39 +02:00
|
|
|
ProjectToggleRecentlyUpdated,
|
2020-03-31 14:28:30 +02:00
|
|
|
ProjectClearFilters,
|
2020-03-31 22:05:18 +02:00
|
|
|
|
|
|
|
// dragging
|
|
|
|
IssueDragStarted(IssueId),
|
|
|
|
IssueDragStopped(IssueId),
|
|
|
|
IssueDropZone(IssueStatus),
|
|
|
|
|
2020-04-05 15:15:09 +02:00
|
|
|
// inputs
|
|
|
|
InputChanged(FieldId, String),
|
|
|
|
|
2020-03-31 22:05:18 +02:00
|
|
|
// issues
|
|
|
|
IssueUpdateResult(FetchObject<String>),
|
2020-04-04 17:42:02 +02:00
|
|
|
IssueDeleteResult(FetchObject<String>),
|
2020-04-03 23:43:29 +02:00
|
|
|
DeleteIssue(IssueId),
|
2020-04-01 18:30:01 +02:00
|
|
|
|
|
|
|
// modals
|
2020-04-03 16:15:56 +02:00
|
|
|
ModalOpened(ModalType),
|
|
|
|
ModalDropped,
|
|
|
|
ModalChanged(FieldChange),
|
2020-03-29 19:56:55 +02:00
|
|
|
}
|
|
|
|
|
2020-03-30 14:26:25 +02:00
|
|
|
fn update(msg: Msg, model: &mut model::Model, orders: &mut impl Orders<Msg>) {
|
|
|
|
if cfg!(debug_assertions) {
|
|
|
|
log!(msg);
|
|
|
|
}
|
2020-03-30 08:16:26 +02:00
|
|
|
match msg {
|
2020-03-30 14:26:25 +02:00
|
|
|
Msg::ChangePage(page) => {
|
|
|
|
model.page = page;
|
|
|
|
}
|
|
|
|
_ => (),
|
|
|
|
}
|
|
|
|
crate::shared::update(&msg, model, orders);
|
2020-04-02 19:32:40 +02:00
|
|
|
crate::modal::update(&msg, model, orders);
|
2020-03-30 14:26:25 +02:00
|
|
|
match model.page {
|
2020-04-04 17:42:02 +02:00
|
|
|
Page::Project | Page::AddIssue => project::update(msg, model, orders),
|
2020-04-01 10:36:05 +02:00
|
|
|
Page::EditIssue(_id) => project::update(msg, model, orders),
|
2020-03-30 14:26:25 +02:00
|
|
|
Page::ProjectSettings => project_settings::update(msg, model, orders),
|
|
|
|
Page::Login => login::update(msg, model, orders),
|
|
|
|
Page::Register => register::update(msg, model, orders),
|
|
|
|
}
|
|
|
|
if cfg!(debug_assertions) {
|
2020-03-31 22:05:18 +02:00
|
|
|
// debug!(model);
|
2020-03-29 19:56:55 +02:00
|
|
|
}
|
2020-03-30 08:16:26 +02:00
|
|
|
}
|
2020-03-29 19:56:55 +02:00
|
|
|
|
2020-03-30 14:26:25 +02:00
|
|
|
fn view(model: &model::Model) -> Node<Msg> {
|
|
|
|
match model.page {
|
2020-04-04 17:42:02 +02:00
|
|
|
Page::Project | Page::AddIssue => project::view(model),
|
2020-04-01 10:36:05 +02:00
|
|
|
Page::EditIssue(_id) => project::view(model),
|
2020-03-30 14:26:25 +02:00
|
|
|
Page::ProjectSettings => project_settings::view(model),
|
|
|
|
Page::Login => login::view(model),
|
|
|
|
Page::Register => register::view(model),
|
|
|
|
}
|
2020-03-30 08:16:26 +02:00
|
|
|
}
|
2020-03-29 19:56:55 +02:00
|
|
|
|
2020-03-30 08:16:26 +02:00
|
|
|
fn routes(url: Url) -> Option<Msg> {
|
|
|
|
if url.path.is_empty() {
|
2020-03-30 14:26:25 +02:00
|
|
|
return Some(Msg::ChangePage(model::Page::Project));
|
2020-03-30 08:16:26 +02:00
|
|
|
}
|
2020-03-29 19:56:55 +02:00
|
|
|
|
2020-03-30 08:16:26 +02:00
|
|
|
match url.path[0].as_ref() {
|
2020-03-30 14:26:25 +02:00
|
|
|
"board" => Some(Msg::ChangePage(model::Page::Project)),
|
2020-04-01 10:36:05 +02:00
|
|
|
"issues" => match url.path.get(1).as_ref().map(|s| s.parse::<i32>()) {
|
|
|
|
Some(Ok(id)) => Some(Msg::ChangePage(model::Page::EditIssue(id))),
|
|
|
|
_ => None,
|
|
|
|
},
|
2020-04-04 17:42:02 +02:00
|
|
|
"add-issue" => Some(Msg::ChangePage(Page::AddIssue)),
|
2020-03-30 14:26:25 +02:00
|
|
|
"project-settings" => Some(Msg::ChangePage(model::Page::ProjectSettings)),
|
|
|
|
"login" => Some(Msg::ChangePage(model::Page::Login)),
|
|
|
|
"register" => Some(Msg::ChangePage(model::Page::Register)),
|
|
|
|
_ => Some(Msg::ChangePage(model::Page::Project)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub static mut HOST_URL: String = String::new();
|
|
|
|
|
|
|
|
#[wasm_bindgen]
|
|
|
|
pub fn set_host_url(url: String) {
|
|
|
|
unsafe {
|
|
|
|
HOST_URL = url;
|
2020-03-29 19:56:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-05 15:15:09 +02:00
|
|
|
fn after_mount(_url: Url, _orders: &mut impl Orders<Msg>) -> AfterMount<Model> {
|
|
|
|
ws();
|
|
|
|
let model = Model::default();
|
|
|
|
AfterMount::new(model).url_handling(UrlHandling::None)
|
|
|
|
}
|
|
|
|
|
2020-03-30 14:26:25 +02:00
|
|
|
#[wasm_bindgen]
|
2020-03-30 08:16:26 +02:00
|
|
|
pub fn render() {
|
2020-04-05 15:15:09 +02:00
|
|
|
App::builder(update, view)
|
|
|
|
.routes(routes)
|
|
|
|
.after_mount(after_mount)
|
|
|
|
.build_and_start();
|
2020-03-29 19:56:55 +02:00
|
|
|
}
|