Fix drop create modal, add deploy info
This commit is contained in:
parent
fce3bb727f
commit
f0c275120a
@ -180,8 +180,7 @@ cargo run --bin jirs_server
|
|||||||
```bash
|
```bash
|
||||||
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||||
cd jirs_client
|
cd jirs_client
|
||||||
yarn
|
./web/scripts/prod.sh
|
||||||
./scripts/prod.sh
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -193,7 +193,11 @@ impl CreateIssue {
|
|||||||
crate::issue_statuses::LoadIssueStatuses {
|
crate::issue_statuses::LoadIssueStatuses {
|
||||||
project_id: msg.project_id,
|
project_id: msg.project_id,
|
||||||
}
|
}
|
||||||
.execute(conn)?
|
.execute(conn)
|
||||||
|
.map_err(|e| {
|
||||||
|
common::log::error!("Failed to find issue status. {:?}", e);
|
||||||
|
e
|
||||||
|
})?
|
||||||
.first()
|
.first()
|
||||||
.ok_or(crate::DatabaseError::Issue(
|
.ok_or(crate::DatabaseError::Issue(
|
||||||
crate::IssueError::NoIssueStatuses,
|
crate::IssueError::NoIssueStatuses,
|
||||||
@ -223,12 +227,22 @@ impl CreateIssue {
|
|||||||
reporter_id: msg.reporter_id,
|
reporter_id: msg.reporter_id,
|
||||||
epic_id: msg.epic_id,
|
epic_id: msg.epic_id,
|
||||||
}
|
}
|
||||||
.execute(conn)?;
|
.execute(conn)
|
||||||
|
.map_err(|e| {
|
||||||
|
common::log::error!("Failed to insert issue. {:?}", e);
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
if !assign_users.is_empty() {
|
||||||
crate::issue_assignees::AsignMultiple {
|
crate::issue_assignees::AsignMultiple {
|
||||||
issue_id: issue.id,
|
issue_id: issue.id,
|
||||||
user_ids: assign_users,
|
user_ids: assign_users,
|
||||||
}
|
}
|
||||||
.execute(conn)?;
|
.execute(conn)
|
||||||
|
.map_err(|e| {
|
||||||
|
common::log::error!("Failed to apply multiple assignee to issue. {:?}", e);
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
}
|
||||||
issues.find(issue.id).get_result(conn).map_err(|e| {
|
issues.find(issue.id).get_result(conn).map_err(|e| {
|
||||||
common::log::error!("{:?}", e);
|
common::log::error!("{:?}", e);
|
||||||
crate::DatabaseError::GenericFailure(
|
crate::DatabaseError::GenericFailure(
|
||||||
|
127
docs/Deploy.md
Normal file
127
docs/Deploy.md
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
# Deploy with Nginx
|
||||||
|
|
||||||
|
You can deploy easily JIRS to any PC including Raspberry PI. To do this you will need compile it from source code.
|
||||||
|
|
||||||
|
We will use following setup, but you can modify it.
|
||||||
|
|
||||||
|
* `issues.example.com` - domain
|
||||||
|
* `postgres://postgres@192.168.1.144:5432/jirs` - database on other machine and within inner network
|
||||||
|
|
||||||
|
* `/var/jirs` - main directory
|
||||||
|
* `/var/jirs/clone` - cloned source code
|
||||||
|
* `/var/jirs/web` - All static assets including wasm library
|
||||||
|
* `/var/jirs/config` - config files
|
||||||
|
* `/var/jirs/uploads` - uploaded files
|
||||||
|
|
||||||
|
### JIRS Config files
|
||||||
|
|
||||||
|
* `config/db.toml` (REQUIRED)
|
||||||
|
|
||||||
|
```toml
|
||||||
|
concurrency = 2
|
||||||
|
database_url = "postgres://postgres@192.168.1.144:5432/jirs"
|
||||||
|
```
|
||||||
|
|
||||||
|
* `config/web.toml` (public_path is required)
|
||||||
|
|
||||||
|
```toml
|
||||||
|
concurrency = 2
|
||||||
|
port = "5000"
|
||||||
|
bind = "0.0.0.0"
|
||||||
|
ssl = false
|
||||||
|
tmp_dir = "/tmp"
|
||||||
|
public_path = "issues.example.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
* `config/fs.toml` (must match nginx config)
|
||||||
|
|
||||||
|
```toml
|
||||||
|
store_path = "./uploads"
|
||||||
|
client_path = "/uploads"
|
||||||
|
tmp_path = "/tmp"
|
||||||
|
concurrency = 2
|
||||||
|
```
|
||||||
|
|
||||||
|
* `config/mail.toml` (REQUIRED)
|
||||||
|
|
||||||
|
```toml
|
||||||
|
concurrency = 2
|
||||||
|
user = "apikey"
|
||||||
|
pass = "SG.ARJL0wAxQk-LLJca9FJ5Lg.ahs7dyashd8a7shd7ahsd978h"
|
||||||
|
host = "smtp.sendgrid.net"
|
||||||
|
from = "admin@issues.example.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
### NGINX config file
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name issues.example.com;
|
||||||
|
|
||||||
|
root /var/jirs/web;
|
||||||
|
try_files $uri $uri/index.html index.html;
|
||||||
|
|
||||||
|
location ~ /uploads/ {
|
||||||
|
root /var/jirs;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ .js {
|
||||||
|
add_header 'Content-Type' 'application/javascript';
|
||||||
|
add_header 'Access-Control-Allow-Origin' '*';
|
||||||
|
}
|
||||||
|
location ~ .css {
|
||||||
|
add_header 'Content-Type' 'text/css';
|
||||||
|
}
|
||||||
|
location ~ .wasm {
|
||||||
|
add_header 'Content-Type' 'application/wasm';
|
||||||
|
add_header 'Access-Control-Allow-Origin' '*';
|
||||||
|
}
|
||||||
|
|
||||||
|
location /ws/ {
|
||||||
|
proxy_pass http://localhost:5000;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "Upgrade";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
}
|
||||||
|
location /avatar {
|
||||||
|
proxy_pass http://localhost:5000;
|
||||||
|
}
|
||||||
|
location ~ / {
|
||||||
|
add_header 'Content-Type' 'text/html';
|
||||||
|
add_header 'Access-Control-Allow-Origin' '*';
|
||||||
|
root /var/jirs/web;
|
||||||
|
try_files $uri $uri/index.html /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compile application
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo install --force wasm-pack
|
||||||
|
cargo install --force rsass
|
||||||
|
```
|
||||||
|
|
||||||
|
Ensure `$HOME/.cargo/bin` is in `$PATH`
|
||||||
|
|
||||||
|
* Compile server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo build --bin jirs_server --release --no-default-features --features local-storage
|
||||||
|
cp ./target/release/jirs_server /usr/bin/jirs_server
|
||||||
|
```
|
||||||
|
|
||||||
|
* Compile web client
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./web/scripts/prod.sh
|
||||||
|
|
||||||
|
cp -r /tmp/wasm/* /var/jirs/web
|
||||||
|
```
|
||||||
|
|
||||||
|
If it fails (there is no wasm-opt for Raspberry PI) you must disable wasm-opt or compile it on any other PC and just
|
||||||
|
copy everything to `/var/jirs/web`
|
||||||
|
|
||||||
|
|
@ -156,10 +156,10 @@ fn update(msg: Msg, model: &mut model::Model, orders: &mut impl Orders<Msg>) {
|
|||||||
if model.ws.is_none() {
|
if model.ws.is_none() {
|
||||||
open_socket(model, orders);
|
open_socket(model, orders);
|
||||||
}
|
}
|
||||||
|
let mut msg = msg;
|
||||||
|
|
||||||
let msg = match msg {
|
let msg = match msg {
|
||||||
Msg::WebSocketChange(change) => {
|
Msg::WebSocketChange(change) => match change {
|
||||||
match change {
|
|
||||||
WebSocketChanged::WebSocketOpened => {
|
WebSocketChanged::WebSocketOpened => {
|
||||||
flush_queue(model, orders);
|
flush_queue(model, orders);
|
||||||
send_ws_msg(WsMsg::Ping, model.ws.as_ref(), orders);
|
send_ws_msg(WsMsg::Ping, model.ws.as_ref(), orders);
|
||||||
@ -177,10 +177,10 @@ fn update(msg: Msg, model: &mut model::Model, orders: &mut impl Orders<Msg>) {
|
|||||||
orders.skip();
|
orders.skip();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
WebSocketChanged::WsMsg(ws_msg) => {
|
WebSocketChanged::WsMsg(mut ws_msg) => {
|
||||||
ws::update(ws_msg, model, orders);
|
ws::update(&mut ws_msg, model, orders);
|
||||||
orders.skip();
|
orders.skip();
|
||||||
return;
|
Msg::WebSocketChange(WebSocketChanged::WsMsg(ws_msg))
|
||||||
}
|
}
|
||||||
WebSocketChanged::WebSocketMessageLoaded(v) => {
|
WebSocketChanged::WebSocketMessageLoaded(v) => {
|
||||||
match bincode::deserialize(v.as_slice()) {
|
match bincode::deserialize(v.as_slice()) {
|
||||||
@ -208,8 +208,7 @@ fn update(msg: Msg, model: &mut model::Model, orders: &mut impl Orders<Msg>) {
|
|||||||
open_socket(model, orders);
|
open_socket(model, orders);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
}
|
|
||||||
_ => msg,
|
_ => msg,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,14 +1,41 @@
|
|||||||
|
static mut HOST: String = String::new();
|
||||||
|
static mut WS: String = String::new();
|
||||||
|
|
||||||
|
fn ensure_host() {
|
||||||
|
unsafe {
|
||||||
|
if HOST.is_empty() {
|
||||||
|
HOST = format!(
|
||||||
|
"{}//{}",
|
||||||
|
seed::window().location().protocol().unwrap(),
|
||||||
|
seed::window().location().host().unwrap()
|
||||||
|
);
|
||||||
|
let host: String = seed::window().location().host().unwrap();
|
||||||
|
let is_local = host.ends_with("lvh.me")
|
||||||
|
|| host.contains("localhost")
|
||||||
|
|| host.starts_with("127.")
|
||||||
|
|| host.contains("0.0.0.0");
|
||||||
|
WS = format!(
|
||||||
|
"{}//{}/ws/",
|
||||||
|
match seed::window().location().protocol().unwrap().as_str() {
|
||||||
|
"http:" => "ws:",
|
||||||
|
_ => "wss:",
|
||||||
|
},
|
||||||
|
if is_local {
|
||||||
|
"localhost:5000"
|
||||||
|
} else {
|
||||||
|
host.as_str()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn host_url() -> &'static str {
|
pub fn host_url() -> &'static str {
|
||||||
if cfg!(debug_assertions) {
|
ensure_host();
|
||||||
"http://localhost:5000"
|
unsafe { HOST.as_str() }
|
||||||
} else {
|
|
||||||
"https://localhost:5000"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ws_url() -> &'static str {
|
pub fn ws_url() -> &'static str {
|
||||||
if cfg!(debug_assertions) {
|
ensure_host();
|
||||||
"ws://localhost:5000/ws/"
|
unsafe { WS.as_str() }
|
||||||
} else {
|
|
||||||
"wss://localhost:5000/ws/"
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -113,7 +113,10 @@ fn push_modal(modal_type: &ModalType, model: &mut Model, orders: &mut impl Order
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn drop_modal(model: &mut Model, orders: &mut impl Orders<Msg>) {
|
fn drop_modal(model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||||
let modal = model.modal_stack_mut().pop().unwrap();
|
let modal = match model.modal_stack_mut().pop() {
|
||||||
|
Some(modal) => modal,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
let modals = model.modals_mut();
|
let modals = model.modals_mut();
|
||||||
match modal {
|
match modal {
|
||||||
ModalType::AddIssue(_) => {
|
ModalType::AddIssue(_) => {
|
||||||
|
@ -45,9 +45,10 @@ pub fn send_ws_msg(msg: WsMsg, ws: Option<&WebSocket>, orders: &mut impl Orders<
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let binary = bincode::serialize(&msg).unwrap();
|
let binary = bincode::serialize(&msg).unwrap_or_default();
|
||||||
ws.send_bytes(binary.as_slice())
|
if let Err(e) = ws.send_bytes(binary.as_slice()) {
|
||||||
.expect("Failed to send ws msg");
|
log::error!("Failed to send ws msg. {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_socket(model: &mut Model, orders: &mut impl Orders<Msg>) {
|
pub fn open_socket(model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||||
@ -92,12 +93,12 @@ pub async fn read_incoming(msg: WebSocketMessage) -> Msg {
|
|||||||
Msg::WebSocketChange(WebSocketChanged::WebSocketMessageLoaded(bytes))
|
Msg::WebSocketChange(WebSocketChanged::WebSocketMessageLoaded(bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
pub fn update(msg: &mut WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||||
match msg {
|
match msg {
|
||||||
// auth
|
// auth
|
||||||
WsMsg::Session(WsMsgSession::AuthorizeLoaded(Ok((user, setting)))) => {
|
WsMsg::Session(WsMsgSession::AuthorizeLoaded(Ok((user, setting)))) => {
|
||||||
model.user = Some(user);
|
model.user = Some(user.clone());
|
||||||
model.user_settings = Some(setting);
|
model.user_settings = Some(setting.clone());
|
||||||
|
|
||||||
if is_non_logged_area() {
|
if is_non_logged_area() {
|
||||||
go_to_board(orders);
|
go_to_board(orders);
|
||||||
@ -134,7 +135,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
}
|
}
|
||||||
// project
|
// project
|
||||||
WsMsg::Project(WsMsgProject::ProjectsLoaded(v)) => {
|
WsMsg::Project(WsMsgProject::ProjectsLoaded(v)) => {
|
||||||
model.projects = v;
|
model.projects = std::mem::take(v);
|
||||||
init_current_project(model, orders);
|
init_current_project(model, orders);
|
||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
ResourceKind::Project,
|
ResourceKind::Project,
|
||||||
@ -145,7 +146,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
// user projects
|
// user projects
|
||||||
WsMsg::UserProjectsLoaded(v) => {
|
WsMsg::UserProjectsLoaded(v) => {
|
||||||
model.current_user_project = v.iter().find(|up| up.is_current).cloned();
|
model.current_user_project = v.iter().find(|up| up.is_current).cloned();
|
||||||
model.user_projects = v;
|
model.user_projects = std::mem::take(v);
|
||||||
init_current_project(model, orders);
|
init_current_project(model, orders);
|
||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
ResourceKind::UserProject,
|
ResourceKind::UserProject,
|
||||||
@ -160,7 +161,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
up.is_current = up.id == user_project.id;
|
up.is_current = up.id == user_project.id;
|
||||||
model.user_projects.push(up);
|
model.user_projects.push(up);
|
||||||
}
|
}
|
||||||
model.current_user_project = Some(user_project);
|
model.current_user_project = Some(user_project.clone());
|
||||||
init_current_project(model, orders);
|
init_current_project(model, orders);
|
||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
ResourceKind::UserProject,
|
ResourceKind::UserProject,
|
||||||
@ -170,23 +171,23 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
}
|
}
|
||||||
// user settings
|
// user settings
|
||||||
WsMsg::User(WsMsgUser::AvatarUrlChanged(id, url)) => {
|
WsMsg::User(WsMsgUser::AvatarUrlChanged(id, url)) => {
|
||||||
if let Some(user) = model.user.as_mut().filter(|u| u.id == id) {
|
if let Some(user) = model.user.as_mut().filter(|u| u.id == *id) {
|
||||||
user.avatar_url = Some(url.clone());
|
user.avatar_url = Some(url.clone());
|
||||||
}
|
}
|
||||||
if let Some(user) = model.users_by_id.get_mut(&id) {
|
if let Some(user) = model.users_by_id.get_mut(&id) {
|
||||||
user.avatar_url = Some(url.clone());
|
user.avatar_url = Some(url.clone());
|
||||||
}
|
}
|
||||||
if let Some(user) = model.users.iter_mut().find(|u| u.id == id) {
|
if let Some(user) = model.users.iter_mut().find(|u| u.id == *id) {
|
||||||
user.avatar_url = Some(url);
|
user.avatar_url = Some(url.clone());
|
||||||
}
|
}
|
||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
ResourceKind::User,
|
ResourceKind::User,
|
||||||
OperationKind::SingleModified,
|
OperationKind::SingleModified,
|
||||||
Some(id),
|
Some(*id),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
WsMsg::User(WsMsgUser::UserSettingUpdated(setting)) => {
|
WsMsg::User(WsMsgUser::UserSettingUpdated(setting)) => {
|
||||||
model.user_settings = Some(setting);
|
model.user_settings = Some(setting.clone());
|
||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
ResourceKind::UserSetting,
|
ResourceKind::UserSetting,
|
||||||
OperationKind::SingleModified,
|
OperationKind::SingleModified,
|
||||||
@ -196,7 +197,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
|
|
||||||
// issue statuses
|
// issue statuses
|
||||||
WsMsg::IssueStatus(WsMsgIssueStatus::IssueStatusesLoaded(v)) => {
|
WsMsg::IssueStatus(WsMsgIssueStatus::IssueStatusesLoaded(v)) => {
|
||||||
model.issue_statuses = v;
|
model.issue_statuses = std::mem::take(v);
|
||||||
model
|
model
|
||||||
.issue_statuses
|
.issue_statuses
|
||||||
.sort_by(|a, b| a.position.cmp(&b.position));
|
.sort_by(|a, b| a.position.cmp(&b.position));
|
||||||
@ -208,7 +209,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
}
|
}
|
||||||
WsMsg::IssueStatus(WsMsgIssueStatus::IssueStatusCreated(is)) => {
|
WsMsg::IssueStatus(WsMsgIssueStatus::IssueStatusCreated(is)) => {
|
||||||
let id = is.id;
|
let id = is.id;
|
||||||
model.issue_statuses.push(is);
|
model.issue_statuses.push(is.clone());
|
||||||
model
|
model
|
||||||
.issue_statuses
|
.issue_statuses
|
||||||
.sort_by(|a, b| a.position.cmp(&b.position));
|
.sort_by(|a, b| a.position.cmp(&b.position));
|
||||||
@ -218,10 +219,10 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
Some(id),
|
Some(id),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
WsMsg::IssueStatus(WsMsgIssueStatus::IssueStatusUpdated(mut changed)) => {
|
WsMsg::IssueStatus(WsMsgIssueStatus::IssueStatusUpdated(changed)) => {
|
||||||
let id = changed.id;
|
let id = changed.id;
|
||||||
if let Some(idx) = model.issue_statuses.iter().position(|c| c.id == changed.id) {
|
if let Some(idx) = model.issue_statuses.iter().position(|c| c.id == changed.id) {
|
||||||
std::mem::swap(&mut model.issue_statuses[idx], &mut changed);
|
std::mem::swap(&mut model.issue_statuses[idx], changed);
|
||||||
}
|
}
|
||||||
model
|
model
|
||||||
.issue_statuses
|
.issue_statuses
|
||||||
@ -236,7 +237,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
let mut old = vec![];
|
let mut old = vec![];
|
||||||
std::mem::swap(&mut model.issue_statuses, &mut old);
|
std::mem::swap(&mut model.issue_statuses, &mut old);
|
||||||
for is in old {
|
for is in old {
|
||||||
if is.id != dropped_id {
|
if is.id != *dropped_id {
|
||||||
model.issue_statuses.push(is);
|
model.issue_statuses.push(is);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -246,11 +247,11 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
ResourceKind::IssueStatus,
|
ResourceKind::IssueStatus,
|
||||||
OperationKind::SingleRemoved,
|
OperationKind::SingleRemoved,
|
||||||
Some(dropped_id),
|
Some(*dropped_id),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// issues
|
// issues
|
||||||
WsMsg::Project(WsMsgProject::ProjectIssuesLoaded(mut v)) => {
|
WsMsg::Project(WsMsgProject::ProjectIssuesLoaded(v)) => {
|
||||||
v.sort_by(|a, b| (a.list_position as i64).cmp(&(b.list_position as i64)));
|
v.sort_by(|a, b| (a.list_position as i64).cmp(&(b.list_position as i64)));
|
||||||
{
|
{
|
||||||
let _ = std::mem::replace(model.issues_mut(), v.clone());
|
let _ = std::mem::replace(model.issues_mut(), v.clone());
|
||||||
@ -266,12 +267,24 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
WsMsg::Issue(WsMsgIssue::IssueCreated(issue)) => {
|
||||||
|
let id = issue.id;
|
||||||
|
model.issues_by_id.insert(id, issue.clone());
|
||||||
|
if let Some(idx) = model.issues().iter().position(|i| i.id == issue.id) {
|
||||||
|
let _ = std::mem::replace(&mut model.issues_mut()[idx], issue.clone());
|
||||||
|
}
|
||||||
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
|
ResourceKind::Issue,
|
||||||
|
OperationKind::SingleCreated,
|
||||||
|
Some(id),
|
||||||
|
));
|
||||||
|
}
|
||||||
WsMsg::Issue(WsMsgIssue::IssueUpdated(issue)) => {
|
WsMsg::Issue(WsMsgIssue::IssueUpdated(issue)) => {
|
||||||
let id = issue.id;
|
let id = issue.id;
|
||||||
model.issues_by_id.remove(&id);
|
model.issues_by_id.remove(&id);
|
||||||
model.issues_by_id.insert(id, issue.clone());
|
model.issues_by_id.insert(id, issue.clone());
|
||||||
if let Some(idx) = model.issues().iter().position(|i| i.id == issue.id) {
|
if let Some(idx) = model.issues().iter().position(|i| i.id == issue.id) {
|
||||||
let _ = std::mem::replace(&mut model.issues_mut()[idx], issue);
|
let _ = std::mem::replace(&mut model.issues_mut()[idx], issue.clone());
|
||||||
}
|
}
|
||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
ResourceKind::Issue,
|
ResourceKind::Issue,
|
||||||
@ -280,10 +293,9 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
WsMsg::Issue(WsMsgIssue::IssueDeleted(id, _count)) => {
|
WsMsg::Issue(WsMsgIssue::IssueDeleted(id, _count)) => {
|
||||||
let mut old = vec![];
|
let old = std::mem::take(model.issues_mut());
|
||||||
std::mem::swap(model.issues_mut(), &mut old);
|
|
||||||
for is in old {
|
for is in old {
|
||||||
if is.id == id {
|
if is.id == *id {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
model.issues_mut().push(is);
|
model.issues_mut().push(is);
|
||||||
@ -291,7 +303,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
ResourceKind::Issue,
|
ResourceKind::Issue,
|
||||||
OperationKind::SingleRemoved,
|
OperationKind::SingleRemoved,
|
||||||
Some(id),
|
Some(*id),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// users
|
// users
|
||||||
@ -308,7 +320,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
// comments
|
// comments
|
||||||
WsMsg::Comment(WsMsgComment::IssueCommentsLoaded(mut comments)) => {
|
WsMsg::Comment(WsMsgComment::IssueCommentsLoaded(comments)) => {
|
||||||
let issue_id = match &model.modals().edit_issue {
|
let issue_id = match &model.modals().edit_issue {
|
||||||
Some(modal) => modal.id,
|
Some(modal) => modal.id,
|
||||||
_ => return,
|
_ => return,
|
||||||
@ -318,7 +330,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
}
|
}
|
||||||
comments.sort_by(|a, b| a.updated_at.cmp(&b.updated_at));
|
comments.sort_by(|a, b| a.updated_at.cmp(&b.updated_at));
|
||||||
model.comments = comments.clone();
|
model.comments = comments.clone();
|
||||||
for comment in comments {
|
for comment in std::mem::take(comments) {
|
||||||
model.comments_by_id.insert(comment.id, comment);
|
model.comments_by_id.insert(comment.id, comment);
|
||||||
}
|
}
|
||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
@ -331,7 +343,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
let comment_id = comment.id;
|
let comment_id = comment.id;
|
||||||
if let Some(idx) = model.comments.iter().position(|c| c.id == comment.id) {
|
if let Some(idx) = model.comments.iter().position(|c| c.id == comment.id) {
|
||||||
let _ = std::mem::replace(&mut model.comments[idx], comment.clone());
|
let _ = std::mem::replace(&mut model.comments[idx], comment.clone());
|
||||||
model.comments_by_id.insert(comment.id, comment);
|
model.comments_by_id.insert(comment.id, comment.clone());
|
||||||
}
|
}
|
||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
ResourceKind::Comment,
|
ResourceKind::Comment,
|
||||||
@ -340,20 +352,20 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
WsMsg::Comment(WsMsgComment::CommentDeleted(comment_id, _count)) => {
|
WsMsg::Comment(WsMsgComment::CommentDeleted(comment_id, _count)) => {
|
||||||
if let Some(idx) = model.comments.iter().position(|c| c.id == comment_id) {
|
if let Some(idx) = model.comments.iter().position(|c| c.id == *comment_id) {
|
||||||
model.comments.remove(idx);
|
model.comments.remove(idx);
|
||||||
}
|
}
|
||||||
model.comments_by_id.remove(&comment_id);
|
model.comments_by_id.remove(&comment_id);
|
||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
ResourceKind::Comment,
|
ResourceKind::Comment,
|
||||||
OperationKind::SingleRemoved,
|
OperationKind::SingleRemoved,
|
||||||
Some(comment_id),
|
Some(*comment_id),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// messages
|
// messages
|
||||||
WsMsg::Message(WsMsgMessage::MessageUpdated(mut received)) => {
|
WsMsg::Message(WsMsgMessage::MessageUpdated(received)) => {
|
||||||
if let Some(idx) = model.messages.iter().position(|m| m.id == received.id) {
|
if let Some(idx) = model.messages.iter().position(|m| m.id == received.id) {
|
||||||
std::mem::swap(&mut model.messages[idx], &mut received);
|
std::mem::swap(&mut model.messages[idx], received);
|
||||||
}
|
}
|
||||||
model.messages.sort_by(|a, b| a.id.cmp(&b.id));
|
model.messages.sort_by(|a, b| a.id.cmp(&b.id));
|
||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
@ -363,7 +375,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
WsMsg::Message(WsMsgMessage::MessagesLoaded(v)) => {
|
WsMsg::Message(WsMsgMessage::MessagesLoaded(v)) => {
|
||||||
model.messages = v;
|
model.messages = std::mem::take(v);
|
||||||
model.messages.sort_by(|a, b| a.id.cmp(&b.id));
|
model.messages.sort_by(|a, b| a.id.cmp(&b.id));
|
||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
ResourceKind::Message,
|
ResourceKind::Message,
|
||||||
@ -372,14 +384,14 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
WsMsg::Message(WsMsgMessage::MessageMarkedSeen(id, _count)) => {
|
WsMsg::Message(WsMsgMessage::MessageMarkedSeen(id, _count)) => {
|
||||||
if let Some(idx) = model.messages.iter().position(|m| m.id == id) {
|
if let Some(idx) = model.messages.iter().position(|m| m.id == *id) {
|
||||||
model.messages.remove(idx);
|
model.messages.remove(idx);
|
||||||
}
|
}
|
||||||
model.messages.sort_by(|a, b| a.id.cmp(&b.id));
|
model.messages.sort_by(|a, b| a.id.cmp(&b.id));
|
||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
ResourceKind::Message,
|
ResourceKind::Message,
|
||||||
OperationKind::SingleRemoved,
|
OperationKind::SingleRemoved,
|
||||||
Some(id),
|
Some(*id),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,7 +399,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
WsMsg::Epic(WsMsgEpic::EpicsLoaded(epics)) => {
|
WsMsg::Epic(WsMsgEpic::EpicsLoaded(epics)) => {
|
||||||
model.epics = epics.clone();
|
model.epics = epics.clone();
|
||||||
for epic in epics {
|
for epic in epics {
|
||||||
model.epics_by_id.insert(epic.id, epic);
|
model.epics_by_id.insert(epic.id, epic.clone());
|
||||||
}
|
}
|
||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
ResourceKind::Epic,
|
ResourceKind::Epic,
|
||||||
@ -399,7 +411,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
let id = epic.id;
|
let id = epic.id;
|
||||||
model.epics.push(epic.clone());
|
model.epics.push(epic.clone());
|
||||||
model.epics.sort_by(|a, b| a.id.cmp(&b.id));
|
model.epics.sort_by(|a, b| a.id.cmp(&b.id));
|
||||||
model.epics_by_id.insert(epic.id, epic);
|
model.epics_by_id.insert(epic.id, epic.clone());
|
||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
ResourceKind::Epic,
|
ResourceKind::Epic,
|
||||||
OperationKind::SingleCreated,
|
OperationKind::SingleCreated,
|
||||||
@ -411,7 +423,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
if let Some(idx) = model.epics.iter().position(|e| e.id == epic.id) {
|
if let Some(idx) = model.epics.iter().position(|e| e.id == epic.id) {
|
||||||
let _ = std::mem::replace(&mut model.epics[idx], epic.clone());
|
let _ = std::mem::replace(&mut model.epics[idx], epic.clone());
|
||||||
}
|
}
|
||||||
model.epics_by_id.insert(epic.id, epic);
|
model.epics_by_id.insert(epic.id, epic.clone());
|
||||||
model.epics.sort_by(|a, b| a.id.cmp(&b.id));
|
model.epics.sort_by(|a, b| a.id.cmp(&b.id));
|
||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
ResourceKind::Epic,
|
ResourceKind::Epic,
|
||||||
@ -420,7 +432,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
WsMsg::Epic(WsMsgEpic::EpicDeleted(id, _count)) => {
|
WsMsg::Epic(WsMsgEpic::EpicDeleted(id, _count)) => {
|
||||||
if let Some(idx) = model.epics.iter().position(|e| e.id == id) {
|
if let Some(idx) = model.epics.iter().position(|e| e.id == *id) {
|
||||||
model.epics.remove(idx);
|
model.epics.remove(idx);
|
||||||
}
|
}
|
||||||
model.epics_by_id.remove(&id);
|
model.epics_by_id.remove(&id);
|
||||||
@ -428,7 +440,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
orders.send_msg(Msg::ResourceChanged(
|
orders.send_msg(Msg::ResourceChanged(
|
||||||
ResourceKind::Epic,
|
ResourceKind::Epic,
|
||||||
OperationKind::SingleRemoved,
|
OperationKind::SingleRemoved,
|
||||||
Some(id),
|
Some(*id),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
WsMsg::Session(WsMsgSession::AuthenticateSuccess) => {
|
WsMsg::Session(WsMsgSession::AuthenticateSuccess) => {
|
||||||
@ -436,7 +448,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
page.login_success = true;
|
page.login_success = true;
|
||||||
}
|
}
|
||||||
WsMsg::Session(WsMsgSession::BindTokenOk(access_token)) => {
|
WsMsg::Session(WsMsgSession::BindTokenOk(access_token)) => {
|
||||||
match write_auth_token(Some(access_token)) {
|
match write_auth_token(Some(*access_token)) {
|
||||||
Ok(msg) => {
|
Ok(msg) => {
|
||||||
orders.skip().send_msg(msg);
|
orders.skip().send_msg(msg);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user