From 40c8cf105a4203178b7358c3c6e84bff540c383c Mon Sep 17 00:00:00 2001 From: Aran Varun Date: Sun, 5 May 2024 15:40:27 +0300 Subject: [PATCH 01/19] user optional details --- src/main.rs | 22 ++++++---------------- src/models/user_model.rs | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/main.rs b/src/main.rs index ab453c9..c182f6d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,23 +8,14 @@ extern crate rocket; #[cfg(test)] mod tests; -use api::permission_api::get_all_permissions; -use api::role_api::get_all_roles; -use api::user_api::{get_all_users, get_user}; -use repository::localdb_repo::LocalRepo; -use repository::mongodb_repo::MongoRepo; -use rocket::fairing::AdHoc; -use rocket::serde::Deserialize; +use api::{ + permission_api::get_all_permissions, + role_api::get_all_roles, + user_api::{get_all_users, get_user}, +}; +use repository::{localdb_repo::LocalRepo, mongodb_repo::MongoRepo}; use rocket::{get, http::Status, serde::json::Json}; -#[derive(Debug, Deserialize)] -#[serde(crate = "rocket::serde")] -#[allow(dead_code)] -struct AppConfig { - key: String, - port: u16, -} - #[get("/")] fn hello() -> Result, Status> { Ok(Json(String::from("Hello world"))) @@ -41,7 +32,6 @@ fn rocket() -> _ { .mount("/", routes![get_all_roles]) .mount("/", routes![get_all_permissions]) .mount("/", routes![hello]) - .attach(AdHoc::config::()) } /* diff --git a/src/models/user_model.rs b/src/models/user_model.rs index be83182..d4968bc 100644 --- a/src/models/user_model.rs +++ b/src/models/user_model.rs @@ -1,12 +1,28 @@ // use mongodb::bson::oid::ObjectId; use serde::{Deserialize, Serialize}; +#[derive(Debug, Serialize, Deserialize)] +struct Email { + address: String, + verified: bool, +} + #[derive(Debug, Serialize, Deserialize)] pub struct User { #[serde(rename = "_id")] id: String, roles: Vec, status: String, + #[serde(rename = "statusDefault")] + status_default: Option, + #[serde(rename = "statusConnection")] + status_connection: Option, + #[serde(rename = "__rooms")] + rooms: Option>, username: String, + name: String, + #[serde(rename = "type")] + utype: String, + emails: Option>, active: bool, } From 2939e800e4855c5dc6036fbc61c7fdd893466685 Mon Sep 17 00:00:00 2001 From: Dmitri Plakhov Date: Wed, 8 May 2024 23:41:31 +0300 Subject: [PATCH 02/19] with data slice --- .env | 2 -- .gitignore | 1 + request.sh | 3 +++ src/api/mod.rs | 1 + src/api/room_api.rs | 11 +++++++++ src/main.rs | 2 ++ src/models/mod.rs | 1 + src/models/room_model.rs | 29 +++++++++++++++++++++++ src/models/user_model.rs | 14 ++++++++--- src/repository/mongodb_repo.rs | 43 +++++++++++++++++++++++++++++++++- 10 files changed, 101 insertions(+), 6 deletions(-) delete mode 100644 .env create mode 100644 request.sh create mode 100644 src/api/room_api.rs create mode 100644 src/models/room_model.rs diff --git a/.env b/.env deleted file mode 100644 index d4ee825..0000000 --- a/.env +++ /dev/null @@ -1,2 +0,0 @@ -export MONGOURI='mongodb://mongodb:27017/rocketchat?replicaSet=rs0' -export LOCALURI='mongodb://mongodb:27017/rocketchat?replicaSet=rs0' diff --git a/.gitignore b/.gitignore index ea8c4bf..fedaa2b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +.env diff --git a/request.sh b/request.sh new file mode 100644 index 0000000..f2f7d97 --- /dev/null +++ b/request.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +curl http://127.0.0.1:8000/user/t98Y3gHncHuByTEPE diff --git a/src/api/mod.rs b/src/api/mod.rs index 8549fb7..08b909b 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,3 +1,4 @@ pub mod permission_api; pub mod role_api; +pub mod room_api; pub mod user_api; diff --git a/src/api/room_api.rs b/src/api/room_api.rs new file mode 100644 index 0000000..7bd5996 --- /dev/null +++ b/src/api/room_api.rs @@ -0,0 +1,11 @@ +use crate::{models::room_model::Room, repository::mongodb_repo::MongoRepo}; +use rocket::{http::Status, serde::json::Json, State}; + +#[get("/rooms")] +pub fn get_all_rooms(db: &State) -> Result>, Status> { + let rooms = db.get_all_rooms(); + match rooms { + Ok(rooms) => Ok(Json(rooms)), + Err(_) => Err(Status::InternalServerError), + } +} diff --git a/src/main.rs b/src/main.rs index c182f6d..1acd38b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ mod tests; use api::{ permission_api::get_all_permissions, role_api::get_all_roles, + room_api::get_all_rooms, user_api::{get_all_users, get_user}, }; use repository::{localdb_repo::LocalRepo, mongodb_repo::MongoRepo}; @@ -30,6 +31,7 @@ fn rocket() -> _ { .mount("/", routes![get_user]) .mount("/", routes![get_all_users]) .mount("/", routes![get_all_roles]) + .mount("/", routes![get_all_rooms]) .mount("/", routes![get_all_permissions]) .mount("/", routes![hello]) } diff --git a/src/models/mod.rs b/src/models/mod.rs index 7434b10..43722f5 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,4 +1,5 @@ pub mod permission_model; pub mod role_model; +pub mod room_model; pub mod setting_model; pub mod user_model; diff --git a/src/models/room_model.rs b/src/models/room_model.rs new file mode 100644 index 0000000..fc8435c --- /dev/null +++ b/src/models/room_model.rs @@ -0,0 +1,29 @@ +// use mongodb::bson::oid::ObjectId; +use serde::{Deserialize, Serialize}; + + +#[derive(Debug, Serialize, Deserialize)] +struct Lmessage { + msg: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Room { + #[serde(rename = "_id")] + id: String, + #[serde(rename = "usersCount")] + users_count: Option, + msgs: Option, + usernames: Option>, + #[serde(rename = "_USERNAMES")] + user_names: Option>, + uids: Option>, + name: Option, + fname: Option, + topic: Option, + encrypted: Option, + #[serde(rename = "teamMain")] + team_main: Option, + #[serde(rename = "lastMessage")] + last_message: Option, +} diff --git a/src/models/user_model.rs b/src/models/user_model.rs index d4968bc..67b299e 100644 --- a/src/models/user_model.rs +++ b/src/models/user_model.rs @@ -1,10 +1,12 @@ // use mongodb::bson::oid::ObjectId; +use mongodb::bson::DateTime; use serde::{Deserialize, Serialize}; + #[derive(Debug, Serialize, Deserialize)] struct Email { address: String, - verified: bool, + verified: Option, } #[derive(Debug, Serialize, Deserialize)] @@ -20,9 +22,15 @@ pub struct User { #[serde(rename = "__rooms")] rooms: Option>, username: String, - name: String, + name: Option, #[serde(rename = "type")] - utype: String, + utype: Option, emails: Option>, active: bool, + #[serde(rename = "createdAt")] + created_at: DateTime, + #[serde(rename = "lastLogin")] + last_login: Option, + #[serde(rename = "_updatedAt")] + updated_at: Option, } diff --git a/src/repository/mongodb_repo.rs b/src/repository/mongodb_repo.rs index 3341750..027a961 100644 --- a/src/repository/mongodb_repo.rs +++ b/src/repository/mongodb_repo.rs @@ -4,9 +4,12 @@ use dotenv::dotenv; use crate::models::permission_model::Permission; use crate::models::role_model::Role; +use crate::models::room_model::Room; use crate::models::user_model::User; +use chrono::{TimeZone, Utc}; use mongodb::{ bson::doc, + options::FindOptions, bson::extjson::de::Error, sync::{Client, Collection}, // results::InsertOneResult, @@ -16,6 +19,7 @@ pub struct MongoRepo { usercol: Collection, rolecol: Collection, permcol: Collection, + roomcol: Collection, } impl MongoRepo { @@ -30,10 +34,12 @@ impl MongoRepo { let usercol: Collection = db.collection("users"); let rolecol: Collection = db.collection("rocketchat_roles"); let permcol: Collection = db.collection("rocketchat_permissions"); + let roomcol: Collection = db.collection("rocketchat_room"); MongoRepo { usercol, permcol, rolecol, + roomcol, } } @@ -66,15 +72,50 @@ impl MongoRepo { } pub fn get_all_users(&self) -> Result, Error> { + let trashold = Utc.ymd(2024,1,1).and_hms_opt(0,0,0); + let filter = + doc! { "$nor": [ + { "roles": { "$exists": false } }, + { "roles": { "$size": 0 } }, + { "roles": { "$in": ["Deactivated"] } }, + { "__rooms": { "$exists": false } }, + { "__rooms": { "$size": 0 } }, + { "active": false }, + { "lastLogin": { "$exists": false } }, + { "lastLogin": { "$lt": trashold } }, + { "emails.verified": false } + ] }; let cursors = self .usercol - .find(None, None) + .find(filter, None) .ok() .expect("Error getting list of users"); let users = cursors.map(|doc| doc.unwrap()).collect(); Ok(users) } + pub fn get_all_rooms(&self) -> Result, Error> { + let trashold = Utc.ymd(2024,4,1).and_hms_opt(0,0,0); + let filter = + doc! { "$nor": [ + { "usersCount": { "$exists": false } }, + { "usersCount": { "$lt": 2 } }, + { "msgs": { "$exists": false } }, + { "msgs": { "$lt": 1 } }, + { "_updatedAt": { "$lt": trashold } } + ] }; + //let find_options = None; + let find_options = FindOptions::builder().sort(doc! { "msgs": 1, "usersCount": 1 }).build(); + let cursors = self + .roomcol + .find(filter, find_options) + .ok() + .expect("Error getting list of rooms"); + let rooms = cursors.map(|doc| doc.unwrap()).collect(); + Ok(rooms) + } + + pub fn get_all_roles(&self) -> Result, Error> { let cursors = self .rolecol From a409593c678a9ce508867193aac7354cdfa97d3e Mon Sep 17 00:00:00 2001 From: Dmitri Plakhov Date: Thu, 9 May 2024 13:18:24 +0300 Subject: [PATCH 03/19] raw documents --- Cargo.toml | 2 +- src/api/room_api.rs | 4 +++- src/api/user_api.rs | 2 ++ src/models/room_model.rs | 2 ++ src/models/user_model.rs | 37 ++++++++++++++++++++++++++++++---- src/repository/mongodb_repo.rs | 10 ++++++++- 6 files changed, 50 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 25e6617..43db1d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" # tokio = "1" # futures = "0.3" rocket = {version = "0.5.0-rc.2", features = ["json"]} -serde = { version = "1.0.136", features = ["derive"] } +serde = { version = "1.0", features = ["derive"] } dotenv = "0.15.0" bson = { version = "2", features = ["chrono-0_4"] } # Needed for using chrono datetime in doc chrono = "0.4" # Used for setting DateTimes diff --git a/src/api/room_api.rs b/src/api/room_api.rs index 7bd5996..c4417d8 100644 --- a/src/api/room_api.rs +++ b/src/api/room_api.rs @@ -1,8 +1,10 @@ use crate::{models::room_model::Room, repository::mongodb_repo::MongoRepo}; +use mongodb::bson::Document; use rocket::{http::Status, serde::json::Json, State}; #[get("/rooms")] -pub fn get_all_rooms(db: &State) -> Result>, Status> { +// pub fn get_all_rooms(db: &State) -> Result>, Status> { +pub fn get_all_rooms(db: &State) -> Result>, Status> { let rooms = db.get_all_rooms(); match rooms { Ok(rooms) => Ok(Json(rooms)), diff --git a/src/api/user_api.rs b/src/api/user_api.rs index ba3e93a..07679ba 100644 --- a/src/api/user_api.rs +++ b/src/api/user_api.rs @@ -1,5 +1,6 @@ use crate::{models::user_model::User, repository::mongodb_repo::MongoRepo}; use rocket::{http::Status, serde::json::Json, State}; +// use mongodb::bson::Document; // use mongodb::results::InsertOneResult; /* @@ -37,6 +38,7 @@ pub fn get_user(db: &State, path: String) -> Result, Statu #[get("/users")] pub fn get_all_users(db: &State) -> Result>, Status> { +// pub fn get_all_users(db: &State) -> Result>, Status> { let users = db.get_all_users(); match users { Ok(users) => Ok(Json(users)), diff --git a/src/models/room_model.rs b/src/models/room_model.rs index fc8435c..9f76d04 100644 --- a/src/models/room_model.rs +++ b/src/models/room_model.rs @@ -1,10 +1,12 @@ // use mongodb::bson::oid::ObjectId; +use mongodb::bson::DateTime; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] struct Lmessage { msg: Option, + ts: DateTime, } #[derive(Debug, Serialize, Deserialize)] diff --git a/src/models/user_model.rs b/src/models/user_model.rs index 67b299e..681e29d 100644 --- a/src/models/user_model.rs +++ b/src/models/user_model.rs @@ -2,6 +2,29 @@ use mongodb::bson::DateTime; use serde::{Deserialize, Serialize}; +#[derive(Debug, Serialize, Deserialize)] +struct CustomFields { + #[serde(rename = "Title")] + title: Option, + #[serde(rename = "Department")] + department: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +struct Totp { + enabled: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +struct Ldap { + id: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +struct Service { + ldap: Option, + totp: Option, +} #[derive(Debug, Serialize, Deserialize)] struct Email { @@ -13,20 +36,26 @@ struct Email { pub struct User { #[serde(rename = "_id")] id: String, + username: String, + name: Option, roles: Vec, + services: Option, status: String, + emails: Option>, + active: bool, + ldap: Option, + #[serde(rename = "importIds")] + import_ids: Option>, + #[serde(rename = "customFields")] + custom_fields: Option, #[serde(rename = "statusDefault")] status_default: Option, #[serde(rename = "statusConnection")] status_connection: Option, #[serde(rename = "__rooms")] rooms: Option>, - username: String, - name: Option, #[serde(rename = "type")] utype: Option, - emails: Option>, - active: bool, #[serde(rename = "createdAt")] created_at: DateTime, #[serde(rename = "lastLogin")] diff --git a/src/repository/mongodb_repo.rs b/src/repository/mongodb_repo.rs index 027a961..02adf71 100644 --- a/src/repository/mongodb_repo.rs +++ b/src/repository/mongodb_repo.rs @@ -8,7 +8,7 @@ use crate::models::room_model::Room; use crate::models::user_model::User; use chrono::{TimeZone, Utc}; use mongodb::{ - bson::doc, + bson::{doc, Document}, options::FindOptions, bson::extjson::de::Error, sync::{Client, Collection}, @@ -20,6 +20,8 @@ pub struct MongoRepo { rolecol: Collection, permcol: Collection, roomcol: Collection, + // roomcolraw: Collection, + // usercolraw: Collection, } impl MongoRepo { @@ -35,11 +37,15 @@ impl MongoRepo { let rolecol: Collection = db.collection("rocketchat_roles"); let permcol: Collection = db.collection("rocketchat_permissions"); let roomcol: Collection = db.collection("rocketchat_room"); + // let roomcolraw: Collection = db.collection("rocketchat_room"); + // let usercolraw: Collection = db.collection("users"); MongoRepo { usercol, permcol, rolecol, roomcol, + // roomcolraw, + // usercolraw, } } @@ -72,6 +78,7 @@ impl MongoRepo { } pub fn get_all_users(&self) -> Result, Error> { + // pub fn get_all_users(&self) -> Result, Error> { let trashold = Utc.ymd(2024,1,1).and_hms_opt(0,0,0); let filter = doc! { "$nor": [ @@ -95,6 +102,7 @@ impl MongoRepo { } pub fn get_all_rooms(&self) -> Result, Error> { + // pub fn get_all_rooms(&self) -> Result, Error> { let trashold = Utc.ymd(2024,4,1).and_hms_opt(0,0,0); let filter = doc! { "$nor": [ From 638c6a2c2b99843e8e74ed4bc128cded6529fac3 Mon Sep 17 00:00:00 2001 From: Dmitri Plakhov Date: Thu, 9 May 2024 16:56:26 +0300 Subject: [PATCH 04/19] got layout --- request.sh => requests.sh | 2 + results/layout.json | 843 +++++++++++++++++++++++++++++++++ src/api/mod.rs | 2 + src/api/rawdoc_api.rs | 12 + src/api/room_api.rs | 6 +- src/api/sdui_api.rs | 11 + src/main.rs | 50 +- src/models/mod.rs | 1 + src/models/sdui_model.rs | 43 ++ src/repository/mongodb_repo.rs | 39 +- 10 files changed, 954 insertions(+), 55 deletions(-) rename request.sh => requests.sh (64%) create mode 100644 results/layout.json create mode 100644 src/api/rawdoc_api.rs create mode 100644 src/api/sdui_api.rs create mode 100644 src/models/sdui_model.rs diff --git a/request.sh b/requests.sh similarity index 64% rename from request.sh rename to requests.sh index f2f7d97..8d4eacd 100644 --- a/request.sh +++ b/requests.sh @@ -1,3 +1,5 @@ #!/bin/bash curl http://127.0.0.1:8000/user/t98Y3gHncHuByTEPE + +curl http://127.0.0.1:8000/layout diff --git a/results/layout.json b/results/layout.json new file mode 100644 index 0000000..e3096e7 --- /dev/null +++ b/results/layout.json @@ -0,0 +1,843 @@ +[ + { + "_id": "UI_Use_Name_Avatar", + "_updatedAt": { + "$date": { + "$numberLong": "1682671172785" + } + }, + "ts": { + "$date": { + "$numberLong": "1682540018236" + } + }, + "i18nLabel": "UI_Use_Name_Avatar", + "i18nDescription": "UI_Use_Name_Avatar_Description", + "type": "boolean", + "valueSource": "packageValue", + "packageValue": false, + "value": true, + "section": "User_Interface", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 2 + }, + { + "_id": "UI_Unread_Counter_Style", + "_updatedAt": { + "$date": { + "$numberLong": "1682540018255" + } + }, + "ts": { + "$date": { + "$numberLong": "1682540018255" + } + }, + "i18nLabel": "UI_Unread_Counter_Style", + "i18nDescription": "UI_Unread_Counter_Style_Description", + "type": "select", + "valueSource": "packageValue", + "packageValue": "Different_Style_For_User_Mentions", + "value": "Different_Style_For_User_Mentions", + "section": "User_Interface", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 6 + }, + { + "_id": "Layout_Home_Custom_Block_Visible", + "_updatedAt": { + "$date": { + "$numberLong": "1689370741571" + } + }, + "ts": { + "$date": { + "$numberLong": "1685722754357" + } + }, + "i18nLabel": "Layout_Home_Custom_Block_Visible", + "i18nDescription": "Layout_Home_Custom_Block_Visible_Description", + "type": "boolean", + "valueSource": "packageValue", + "packageValue": false, + "value": true, + "section": "Layout_Home_Page_Content_Title", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 3 + }, + { + "_id": "UI_Group_Channels_By_Type", + "_updatedAt": { + "$date": { + "$numberLong": "1682540018234" + } + }, + "ts": { + "$date": { + "$numberLong": "1682540018234" + } + }, + "i18nLabel": "UI_Group_Channels_By_Type", + "i18nDescription": "UI_Group_Channels_By_Type_Description", + "type": "boolean", + "valueSource": "packageValue", + "packageValue": true, + "value": true, + "section": "User_Interface", + "group": "Layout", + "public": false, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 1 + }, + { + "_id": "Custom_Script_On_Logout", + "_updatedAt": { + "$date": { + "$numberLong": "1682630355676" + } + }, + "ts": { + "$date": { + "$numberLong": "1682540018224" + } + }, + "i18nLabel": "Custom_Script_On_Logout", + "i18nDescription": "Custom_Script_On_Logout_Description", + "type": "code", + "valueSource": "packageValue", + "packageValue": "//Add your script", + "value": "", + "section": "Custom_Scripts", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 0 + }, + { + "_id": "Layout_Home_Body", + "_updatedAt": { + "$date": { + "$numberLong": "1685722754354" + } + }, + "ts": { + "$date": { + "$numberLong": "1685722754354" + } + }, + "i18nLabel": "Layout_Home_Body", + "i18nDescription": "Layout_Custom_Content_Description", + "type": "code", + "valueSource": "packageValue", + "packageValue": "", + "value": "
\n

Добро пожаловать в MKB.Chat

\n

Это меню поможет вам быстрее найти информацию

\n
\n
\n
\n
\n
Мобильные приложения
\n
Скачайте наше мобильное приложение c80m.4at
\n \n
\n
\n \n\n
\n
\n
Приложение для Windows
\n
Установите наш чат на компьютер.
\n \n
\n
\n
\n
\n
Приложение для компьютера MacOS и Linux
\n
Установите наш чат на компьютер.
\n
\n \n
\n
\n
\n
\n
\n
Документация
\n
Изучите документацию по работе в корпоративном мессенджере.
\n \n
\n
\n
\n
\n
\n
\n\n\n
\n \n \n
\n
  • Подключение с OpenVPN не работает
  • \n
  • \"Залипание\" статуса away (необходима перезагрузка страницы)
  • \n
  • \"Утечка памяти\" electron-приложения
  • \n
    \n
    \n

    \n
    \n \n \n
    \n
  • Интеграция RocketChat с Omnitracker
  • \n
    \n
    \n

    \n
    \n \n \n
    \n
  • Большое использование памяти десктоп приложения
  • \n
    \n \n \n
    \n
  • Похоже на утечку памяти, перезагрузка должна помочь (\"нормальный расход\" памяти ~400мб)
  • \n
    \n
    \n

    \n
  • Не могу подключиться к серверу. Что делать?
  • \n
    \n \n \n
    \n
  • Проверьте домен к которому идет подключение. Со всех устройсв необходимо подключаться на im.mkb.ru
  • \n
    \n
    \n

    \n\t
  • Не отображаются картинки/скриншоты.
  • \n\t
    \n\t\t\n\t \n\t
    \n\t
  • Проверьте домен к которому идет подключение. Со всех устройсв необходимо подключаться на im.mkb.ru
  • \n\t
    \n\t
    \n

    \n\t\t
  • Не могу скачать вложение. Что делать?
  • \n\t\t
    \n\t\t\t\n\t\t\t \n\t\t\t
    \n
  • Скачивание и загрузка вложений доступно только внутри офисной сети.
  • \n\t\t\t
    \n\t\t\t
    \n

    \n\t\t\t\t
  • Как удалить сервер в приложении и добавить новый?
  • \n\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t
    \n
  • В приложении слева наверху есть кнопка \"Файл\", под вы найдете иконку ромба (фигуры). Нажмите на нее правой кнопкой мыши и выберите \"удалить сервер\". Рокет автоматически предложит новый, введите https://im.mkb.ru.\nБолее подробная инструкция
  • \n\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t
    \n

    \n \t\t\t\t
  • При попытке вставить код/формулу получаю ошибку: KaTeX parse error: Expected '}', got 'EOF' at end of input
  • \n\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t
    \n
  • Пожалуйста, используйте символ обратной кавычки для заключения кода в блок:\n ```\n CODE\n \t\t\t\t\t\t\t\t\t ```\n Более подробная инструкция\n
  • \n
    \n
    \n

    \n
    \n
    ", + "section": "Layout_Home_Page_Content_Title", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 2 + }, + { + "_id": "Layout_Show_Home_Button", + "_updatedAt": { + "$date": { + "$numberLong": "1685722754350" + } + }, + "ts": { + "$date": { + "$numberLong": "1685722754350" + } + }, + "i18nLabel": "Layout_Show_Home_Button", + "i18nDescription": "Layout_Show_Home_Button_Description", + "type": "boolean", + "valueSource": "packageValue", + "packageValue": true, + "value": true, + "section": "Layout_Home_Page_Content_Title", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 1 + }, + { + "_id": "Layout_Login_Terms", + "_updatedAt": { + "$date": { + "$numberLong": "1699041697967" + } + }, + "ts": { + "$date": { + "$numberLong": "1699041680726" + } + }, + "i18nLabel": "Layout_Login_Terms", + "i18nDescription": "Layout_Login_Terms_Description", + "type": "code", + "valueSource": "packageValue", + "packageValue": "", + "value": "", + "section": "Layout_Home_Page_Content_Title", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 6 + }, + { + "_id": "theme-custom-css", + "_updatedAt": { + "$date": { + "$numberLong": "1696968898386" + } + }, + "ts": { + "$date": { + "$numberLong": "1682540016558" + } + }, + "i18nLabel": "theme-custom-css", + "i18nDescription": "theme-custom-css_Description", + "type": "code", + "valueSource": "packageValue", + "packageValue": "", + "value": "--black-text-color: #242729;\n/******************************************\n *************Circle Avatars*************\n ******************************************/\n\nbody.dark-mode .rcx-avatar__element {\n\tborder-radius: 100%;\n}\n\nbody.dark-mode .avatar .avatar-image {\n\tborder-radius: 100%;\n}\n\nbody .rcx-avatar__element {\n\tborder-radius: 100%;\n}\n\nbody .avatar .avatar-image {\n\tborder-radius: 100%;\n}\n\n/******************************************\n *************Bubble style*************\n ******************************************/\nbody .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left){\n border-radius: 1.15rem;\n line-height: 1.25;\n max-width: calc(83% - 140px);\n padding: 0.5rem .875rem;\n position: relative;\n word-wrap: break-word; \n align-items: flex-start;\n /*background-color: var(--rcx-color-button-background-secondary-danger-focus,var(--own-true-light-color));*/\n}\n\n/*Перенос ФИО выше цитат */\n.rcx-message-header, .rcx-message-header__wrapper{\n order: -1;\n}\n\n/* \"Ушко\" сообщений */\n/* \nbody .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left)::before{\n \n content: \"\";\n height: 17px;\n position: absolute;\n \n}\n*/\n/*******************/\n\n\n/* переносим цитату наверх */\n\nbody .rcx-box .rcx-box--full .rcx-message-container > div:has(blockquote) {\n order: -1;\n}\n\nbody .rcx-box .rcx-box--full .rcx-message-container > div:has(blockquote) > blockquote {\n padding-top: 0 !important;\n padding-bottom: 0 !important;\n}\n/**************************/\n\n/* убираем полоску разделителя по дням */\n\nbody .rcx-message-divider__bar::after {\n\tcontent: none !important;\n}\nbody .rcx-message-divider__wrapper {\n\tborder-radius: 16px !important;\n\tpadding: 2px 18px;\n\tfont-size: 15px;\n line-height: 18px;\n\tbackground-color: #f4f4f4 !important;\n\tcolor: #242729;\n}\nbody ul.messages-list > div.rcx-message-divider {\n\tmargin: 20px !important;\n}\n/**************************************/\n\n/* не знаю, что этот и следующий блок стилей делают */\nbody .rcx-message[data-own=\"false\"]:not(.rcx-message--sequential) > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left)::before{\n border: 0.4rem solid var(--rcx-color-button-background-secondary-danger-hover,var(--own-false-light-color));\n left: -0.35rem;\n transform: translate(0, -0.2rem);\n border-top-right-radius: 0.8rem;\n border-bottom-left-radius: 2.2rem;\n\n}\nbody .rcx-message[data-own=\"true\"]:not(.rcx-message--sequential) > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left)::before{\n\t\n border-right: var(--befort-border-radius1,0.8rem) solid var(--rcx-color-button-background-secondary-danger-focus,var(--own-true-light-color));\n right: var(--before-arrow,auto);\n \tleft: var(--before-auto,-0.35rem);\n transform: translate(0, -0.2rem);\n border-top-right-radius: var(--befort-border-radius1,unset);\n border-bottom-right-radius: var(--befort-border-radius2,innerit);\n /*border-top-left-radius: var(--before-unset,1.8rem);\n border-bottom-left-radius: var(--before-unset,0.2rem);\n border-top-right-radius: var(--before-initial,0.8rem);*/\n border-bottom-left-radius: var(--before-initial,2.2rem);\n \tbottom: var(--before-01em, unset); /* для своих показываем внизу */\n /*\n \t--before-unset: unset;\n \t--befort-border-radius: 1.8rem;\n \t--befort-border-radius: 0.2rem;\n \t--before-arrow: -0.35rem;\n */\n\n}\n/***************************************************/\nbody .rcx-message{\n\t--own-true-light-color: #cde3ff;\n --own-false-light-color: #ffffff; \n \t/*\n\t--own-true-dark-color: #2b5278;\n --own-false-dark-color: #182533;\n \t--message-background-dark-color: #0e1621;\n\t*/\n}\n\n\n\n/* Контент сообщения к низу */\nbody .rcx-message { \t\n align-items: var(--flex-dir-flex-end, normal)!important; /* для своих показываем аватарки внизу */\n}\n/****************************/\n\n/* Разделение сообщение лево/право */\nbody .rcx-message[data-own=\"true\"]{\n \tflex-direction: var(--flex-dir-row-reverse,row)!important;\n}\n/***********************************/\n\n/* Чужие сообщения */\n\t/* Цвет фона бабла */\nbody .rcx-message[data-own=\"false\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) {\n /* background-color: var(--rcx-color-button-background-secondary-danger-hover,rgba(255, 255, 255, 0.6)); */\n background-color: var(--rcx-color-button-background-secondary-danger-hover,#eff5fd); \t\n}\n \t/* Цвет текста */\nbody .rcx-message[data-own=\"true\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > .rcx-message-body {\n \tcolor: --black-text-color;\n}\n\n/*цвет ссылок для своих и подчеркивание*/\nbody .rcx-message[data-own=\"true\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > .rcx-message-body div div a {\n /* color: var(--rcx-color-font-info, var(--rcx-color-primary-600, #ffffff));\n text-decoration: underline; */\n}\n\n\t/* Стили фона сообщения при фокусе */\nbody .rcx-message[data-own=\"false\"]:hover, body .rcx-message:focus {\n /* background: var(--rcx-message-background-color-focus, var(--rcx-color-surface-hover, var(--rcx-color-neutral-200, #ABC7F4)))\n*/\n}\n/******************/\n\n/* Свои сообщения */\n \t/* Цвет фона бабла */\nbody .rcx-message[data-own=\"true\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) {\n \tbackground-color: var(--rcx-color-button-background-secondary-danger-hover,#d8e7ff); \n}\n \t/* Цвет текста */\nbody .rcx-message[data-own=\"true\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > .rcx-message-body {\n \t/*color: var(--black-text-color,#fff) !important; */\n}\n \t/* Стили имени */\nbody .rcx-message[data-own=\"true\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > .rcx-message-header > .rcx-message-header__wrapper > .rcx-message-header__name-container > span {\n \t/*color: var(--black-text-color, #fff) !important; */\n}\n\n\t/* Стили фона сообщения при фокусе */\nbody .rcx-message[data-own=\"true\"]:hover, body .rcx-message:focus {\n background: var(--rcx-message-background-color-focus, var(--rcx-color-surface-hover, var(--rcx-color-neutral-200, #ABC7F4)))\n}\n/********************/\n\n/* Системные сообщения по центру */\nbody .rcx-box .rcx-box--full .rcx-message-system {\n display: flex;\n justify-content: center;\n}\n\nbody .rcx-box .rcx-box--full .rcx-message-system > .rcx-message-system__container {\n width: auto;\n}\n/*********************************/\n\n/* Аватакрки внизу, отключил из-за логики*/\n/*\nbody .rcx-message{\n align-items: flex-end;\n \n}\n*/\n\n\n/* Фиксим ширину на динамику */\nbody .rcx-message-container{\n flex-grow: 0; \n}\n\n/* Галка внизу и время */\nbody .rcx-message-container > div:not(.rcx-message-body):not(.rcx-message-header) { \n inset-block-start: unset !important;\n /*inset-inline-end: unset !important;*/\n /*bottom: 10px; */\n right: 5px; \n}\nbody .rcx-message > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) div:has( > i.rcx-icon){\n\tbottom: 10px;\n}\nbody .rcx-message-header__time {\n right: 25px;\n bottom: 10px;\n position: absolute;\n}\nbody .rcx-message > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) {\n padding-right: 85px;\n}\nbody .rcx-message[data-sequential='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) {\n padding-right: 30px;\n}\n/* Цвет галки */\nbody .rcx-message[data-own=\"true\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > div:not(.rcx-message-body):not(.rcx-message-header) > i {\n /* color: var(--rcx-color-font-info, rgba(255, 255, 255, 0.6)) !important; */\n}\nbody .rcx-message[data-own=\"false\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > div:not(.rcx-message-body):not(.rcx-message-header) > i {\n color: var(--rcx-color-font-info, var(--rcx-color-primary-600, #095AD2)) !important; \n}\n\n/* Стили кнопок реакции */\n\t/* переносим меню ближе */\nbody .rcx-message .rcx-message-toolbox {\n right: auto;\n top: 0;\n \n}\nbody .rcx-message:hover .rcx-box.rcx-box--full.rcx-message-toolbox__wrapper {\n /* display: var(--flex-dir-flex,initial); */\n display: flex;\n flex-direction: var(--flex-dir-row-reverse,row)!important; \n align-items: flex-start;\n}\nbody .rcx-message .rcx-message-toolbox {\n position: sticky;\n}\n/**************************/\n\n\n/* Контейнер с сообщениями цвет фона */\nbody div .main-content-flex {\n /* background-color: var(--rcx-color-surface-room, #D8E5FA) !important; */\n}\n/***************************/\n\n\n/* ToDo: Поправить на нормальный селектор */\nbody .rcx-css-1rdomle:has( > aside.rcx-box.rcx-box--full.rcx-vertical-bar) {\n\t--flex-dir-row-reverse: row-reverse;\n \t/*--flex-dir-flex-end: flex-end; */\t\n \t--flex-dir-flex: flex;\n \t--before-unset: unset;\n \t--before-initial: initial;\n \t--before-auto: auto;\n \t--befort-border-radius1: 1.8rem;\n \t--befort-border-radius2: 0.2rem;\n \t--befort-border-radius3: 0.8rem;\n \t--before-arrow: -0.35rem;\n \t--before-01em: 0.1em;\n \t\n \t\n \t\n}\nbody aside.rcx-box.rcx-box--full.rcx-vertical-bar .rcx-message-header__time {\n right: auto;\n bottom: auto;\n position: relative;\n}\nbody aside.rcx-vertical-bar .rcx-message-container:not(.rcx-message-container--left) {\n max-width:90%!important;\n padding-right: 30px!important;\n overflow: hidden;\n}\nbody aside.rcx-vertical-bar .rcx-message[data-own=\"false\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) {\n background-color: var(--rcx-color-button-background-secondary-danger-hover,#f0f0f0);\n}\nbody aside.rcx-vertical-bar .rcx-message .rcx-message-toolbox {\n position: absolute;\n \tright: 10px;\n}\n\nbody .rcx-message > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role=\"presentation\"]){\n background: none !important;\n\n}\n/*двигаем смайлик и реакции вправо */\nbody .rcx-css-1rdomle:has( > aside.rcx-box.rcx-box--full.rcx-vertical-bar) .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role=\"presentation\"]) .rcx-message-body,\nbody .rcx-css-1rdomle:has( > aside.rcx-box.rcx-box--full.rcx-vertical-bar) .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role=\"presentation\"]) .rcx-message-block{\n align-self: flex-end;\n}\nbody .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role=\"presentation\"]) > .rcx-message-header > .rcx-message-header__wrapper > span > span {\n color:var(--black-text-color) !important;\n}\n\n/* fix цитат */\n/* ToDo: Поправить на нормальный селектор */\nbody .rcx-css-8baznz {\n /* border-radius: 0 10px 10px 0px!important; */\n background: none!important;\n border-color: initial!important;\n border-left-width: 0.2rem !important;\n border-right-width: 0 !important;\n border-top-width: 0 !important;\n border-bottom-width: 0 !important;\n}\n\n/* Фикс стилей цитаты в своих сообщениях */\nbody .rcx-message[data-own='true'] > .rcx-message-container:not(.rcx-message-container--left) > .rcx-attachment__content > blockquote > div * {\n /* color: rgba(255, 255, 255, 0.6) !important; */\n}\n\n/* Полоска цитаты - отключаю*/\nbody .rcx-message[data-own='true'] > .rcx-message-container:not(.rcx-message-container--left) > .rcx-attachment__content > blockquote {\n /*border-color: rgba(255, 255, 255, 0.8) !important; */\n}\n/*****************************************/\n\n/* Фикс штуковины для тредов (колокольчики и прочая шляпа) */\nbody .rcx-message[data-own='true'] > .rcx-message-container:not(.rcx-message-container--left) > .rcx-message-block > div {\n color: rgba(255, 255, 255, 0.8);\n}\n\n@media (max-width: 1279.98px) {\n /* ToDo: Поправить на нормальный селектор */\n body .main-content {\n\t--flex-dir-row-reverse: row-reverse;\n /*\t--flex-dir-flex-end: flex-end; */\t\n \t--flex-dir-flex: flex;\n \t--before-unset: unset;\n \t--before-initial: initial;\n \t--before-auto: auto;\n \t--befort-border-radius1: 1.8rem;\n \t--befort-border-radius2: 0.2rem;\n \t--befort-border-radius3: 0.8rem;\n \t--before-arrow: -0.35rem;\n \t--before-01em: 0.1em;\n\t}\n /*двигаем смайлик и реакции вправо */\n \tbody .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role=\"presentation\"]) .rcx-message-body,\n \tbody .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role=\"presentation\"]) .rcx-message-block{\n align-self: flex-end;\n \t}\n /* убираем обрезку на 140 пикселей */\n\tbody .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) {\n\t\tmax-width:80%;\n \t}\n \t/*Фиксируем для узких тулбокс */\n body .rcx-message[data-own='false'] .rcx-message-toolbox {\n position: absolute;\n right: 10px;\n\t}\n body .rcx-message[data-own='true'] .rcx-message-toolbox {\n position: absolute;\n left: 10px;\n\t}\n\n}\n\n/* Большие эмодзи */\nbody div[role=\"presentation\"] span .rcx-message__emoji--big {\n height: 4.75rem;\n width: 4.75rem;\n}\n\n/*****************/\nbody .rcx-message-reactions__reaction{\n border-radius: var(--rcx-message-reaction-border-radius,var(--rcx-border-radius-medium,.65rem));\n padding: 0.175rem;\n \tbackground-color: var(--rcx-color-button-background-secondary-danger-hover,#f7f8fa);\n \t /* background-color: var(--rcx-message-reaction-hover-background-color,var(--rcx-color-surface-tint,var(--rcx-color-neutral-100,#f7f8fa))); */\n}\n\n\nbody .rcx-message[data-own='true'] > .rcx-message-container:not(.rcx-message-container--left) > .rcx-message-block > .rcx-message-reactions__container > .rcx-message-reactions__reaction {\n border-radius: var(--rcx-message-reaction-border-radius,var(--rcx-border-radius-medium,.65rem));\n padding: 0.175rem;\n \t background-color: var(--rcx-color-button-background-secondary-danger-hover,#fff) !important;\n \t /* background-color: var(--rcx-message-reaction-hover-background-color,var(--rcx-color-surface-tint,var(--rcx-color-neutral-100,#f7f8fa))); */\n}\n\n/* Замена голосовалки */\nbody .rcx-box.rcx-box--full.rcx-message-block--width-fixed.rcx-message-block span code.code-colors.inline {\n background: -webkit-linear-gradient(327deg, #e3f2fff7 -15%, #6ebaf9f7 50%, #267cf5f7 135%);\n background-clip: text;\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n letter-spacing: -0.05rem;\n}", + "section": "Custom CSS", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 0 + }, + { + "_id": "UI_Show_top_navbar_embedded_layout", + "_updatedAt": { + "$date": { + "$numberLong": "1682540018261" + } + }, + "ts": { + "$date": { + "$numberLong": "1682540018261" + } + }, + "i18nLabel": "UI_Show_top_navbar_embedded_layout", + "i18nDescription": "UI_Show_top_navbar_embedded_layout_Description", + "type": "boolean", + "valueSource": "packageValue", + "packageValue": false, + "value": false, + "section": "User_Interface", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 8 + }, + { + "_id": "Layout_Terms_of_Service", + "_updatedAt": { + "$date": { + "$numberLong": "1685722754364" + } + }, + "ts": { + "$date": { + "$numberLong": "1685722754364" + } + }, + "i18nLabel": "Layout_Terms_of_Service", + "i18nDescription": "Layout_Terms_of_Service_Description", + "type": "code", + "valueSource": "packageValue", + "packageValue": "Terms of Service
    Go to APP SETTINGS → Layout to customize this page.", + "value": "Terms of Service
    Go to APP SETTINGS → Layout to customize this page.", + "section": "Layout_Home_Page_Content_Title", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 5 + }, + { + "_id": "UI_Click_Direct_Message", + "_updatedAt": { + "$date": { + "$numberLong": "1682540018241" + } + }, + "ts": { + "$date": { + "$numberLong": "1682540018241" + } + }, + "i18nLabel": "UI_Click_Direct_Message", + "i18nDescription": "UI_Click_Direct_Message_Description", + "type": "boolean", + "valueSource": "packageValue", + "packageValue": false, + "value": false, + "section": "User_Interface", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 4 + }, + { + "_id": "Accounts_ShowFormLogin", + "_updatedAt": { + "$date": { + "$numberLong": "1685722754344" + } + }, + "ts": { + "$date": { + "$numberLong": "1685722754343" + } + }, + "i18nLabel": "Accounts_ShowFormLogin", + "i18nDescription": "Accounts_ShowFormLogin_Description", + "type": "boolean", + "valueSource": "packageValue", + "packageValue": true, + "value": true, + "section": "Login", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 4 + }, + { + "_id": "Custom_Script_Logged_Out", + "_updatedAt": { + "$date": { + "$numberLong": "1682540018226" + } + }, + "ts": { + "$date": { + "$numberLong": "1682540018226" + } + }, + "i18nLabel": "Custom_Script_Logged_Out", + "i18nDescription": "Custom_Script_Logged_Out_Description", + "type": "code", + "valueSource": "packageValue", + "packageValue": "//Add your script", + "value": "//Add your script", + "section": "Custom_Scripts", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 1 + }, + { + "_id": "Layout_Privacy_Policy", + "_updatedAt": { + "$date": { + "$numberLong": "1685722754372" + } + }, + "ts": { + "$date": { + "$numberLong": "1685722754372" + } + }, + "i18nLabel": "Layout_Privacy_Policy", + "i18nDescription": "Layout_Privacy_Policy_Description", + "type": "code", + "valueSource": "packageValue", + "packageValue": "Privacy Policy
    Go to APP SETTINGS → Layout to customize this page.", + "value": "Privacy Policy
    Go to APP SETTINGS → Layout to customize this page.", + "section": "Layout_Home_Page_Content_Title", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 7 + }, + { + "_id": "UI_Allow_room_names_with_special_chars", + "_updatedAt": { + "$date": { + "$numberLong": "1682540018258" + } + }, + "ts": { + "$date": { + "$numberLong": "1682540018258" + } + }, + "i18nLabel": "UI_Allow_room_names_with_special_chars", + "i18nDescription": "UI_Allow_room_names_with_special_chars_Description", + "type": "boolean", + "valueSource": "packageValue", + "packageValue": false, + "value": true, + "section": "User_Interface", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 7 + }, + { + "_id": "UI_Use_Real_Name", + "_updatedAt": { + "$date": { + "$numberLong": "1682540018239" + } + }, + "ts": { + "$date": { + "$numberLong": "1682540018239" + } + }, + "i18nLabel": "UI_Use_Real_Name", + "i18nDescription": "UI_Use_Real_Name_Description", + "type": "boolean", + "valueSource": "packageValue", + "packageValue": false, + "value": true, + "section": "User_Interface", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 3 + }, + { + "_id": "Layout_Sidenav_Footer", + "_updatedAt": { + "$date": { + "$numberLong": "1685722754382" + } + }, + "ts": { + "$date": { + "$numberLong": "1685722754382" + } + }, + "i18nLabel": "Layout_Sidenav_Footer", + "i18nDescription": "Layout_Sidenav_Footer_description", + "type": "code", + "valueSource": "packageValue", + "packageValue": "\"Home\"", + "value": "\"Home\"", + "section": "Layout_Home_Page_Content_Title", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 10 + }, + { + "_id": "Custom_Script_Logged_In", + "_updatedAt": { + "$date": { + "$numberLong": "1695240692287" + } + }, + "ts": { + "$date": { + "$numberLong": "1682540018229" + } + }, + "i18nLabel": "Custom_Script_Logged_In", + "i18nDescription": "Custom_Script_Logged_In_Description", + "type": "code", + "valueSource": "packageValue", + "packageValue": "//Add your script", + "value": "\n//Hide footer\nvar onReadyDomElement = function(element, callback) {\n if (jQuery(element).length) {\n callback(jQuery(element));\n } else {\n setTimeout(function() {\n onReadyDomElement(element, callback);\n }, 100);\n }\n};\n// example\nonReadyDomElement('div.rcx-sidebar-footer', function(e) {\n e.remove();\n console.log(\"footer removed\");\n});", + "section": "Custom_Scripts", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 2 + }, + { + "_id": "Layout_Login_Template", + "_updatedAt": { + "$date": { + "$numberLong": "1685723681451" + } + }, + "ts": { + "$date": { + "$numberLong": "1685722754341" + } + }, + "i18nLabel": "Layout_Login_Template", + "i18nDescription": "Layout_Login_Template_Description", + "type": "select", + "valueSource": "packageValue", + "packageValue": "horizontal-template", + "value": "vertical-template", + "section": "Login", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": true, + "env": false, + "autocomplete": true, + "sorter": 3 + }, + { + "_id": "Layout_Legal_Notice", + "_updatedAt": { + "$date": { + "$numberLong": "1685722754376" + } + }, + "ts": { + "$date": { + "$numberLong": "1685722754376" + } + }, + "i18nLabel": "Layout_Legal_Notice", + "i18nDescription": "Layout_Legal_Notice_Description", + "type": "code", + "valueSource": "packageValue", + "packageValue": "Legal Notice
    Go to APP SETTINGS -> Layout to customize this page.", + "value": "Legal Notice
    Go to APP SETTINGS -> Layout to customize this page.", + "section": "Layout_Home_Page_Content_Title", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 8 + }, + { + "_id": "Layout_Custom_Body_Only", + "_updatedAt": { + "$date": { + "$numberLong": "1689370754560" + } + }, + "ts": { + "$date": { + "$numberLong": "1685722754360" + } + }, + "i18nLabel": "Layout_Custom_Body_Only", + "i18nDescription": "Layout_Custom_Body_Only_Description", + "type": "boolean", + "valueSource": "packageValue", + "packageValue": false, + "value": true, + "section": "Layout_Home_Page_Content_Title", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": true, + "env": false, + "autocomplete": true, + "sorter": 4 + }, + { + "_id": "Layout_Login_Hide_Title", + "_updatedAt": { + "$date": { + "$numberLong": "1685723663057" + } + }, + "ts": { + "$date": { + "$numberLong": "1685722754335" + } + }, + "i18nLabel": "Layout_Login_Hide_Title", + "i18nDescription": "Layout_Login_Hide_Title_Description", + "type": "boolean", + "valueSource": "packageValue", + "packageValue": false, + "value": true, + "section": "Login", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": true, + "env": false, + "autocomplete": true, + "sorter": 1 + }, + { + "_id": "Layout_Login_Hide_Powered_By", + "_updatedAt": { + "$date": { + "$numberLong": "1685723663057" + } + }, + "ts": { + "$date": { + "$numberLong": "1685722754338" + } + }, + "i18nLabel": "Layout_Login_Hide_Powered_By", + "i18nDescription": "Layout_Login_Hide_Powered_By_Description", + "type": "boolean", + "valueSource": "packageValue", + "packageValue": false, + "value": true, + "section": "Login", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": true, + "env": false, + "autocomplete": true, + "sorter": 2 + }, + { + "_id": "Number_of_users_autocomplete_suggestions", + "_updatedAt": { + "$date": { + "$numberLong": "1682540018243" + } + }, + "ts": { + "$date": { + "$numberLong": "1682540018243" + } + }, + "i18nLabel": "Number_of_users_autocomplete_suggestions", + "i18nDescription": "Number_of_users_autocomplete_suggestions_Description", + "type": "int", + "valueSource": "packageValue", + "packageValue": 5, + "value": 5, + "section": "User_Interface", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 5 + }, + { + "_id": "Layout_Home_Title", + "_updatedAt": { + "$date": { + "$numberLong": "1685722754347" + } + }, + "ts": { + "$date": { + "$numberLong": "1685722754347" + } + }, + "i18nLabel": "Layout_Home_Title", + "i18nDescription": "Layout_Home_Title_Description", + "type": "string", + "valueSource": "packageValue", + "packageValue": "Home", + "value": "Home", + "section": "Layout_Home_Page_Content_Title", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 0 + }, + { + "_id": "UI_DisplayRoles", + "_updatedAt": { + "$date": { + "$numberLong": "1682540018231" + } + }, + "ts": { + "$date": { + "$numberLong": "1682540018231" + } + }, + "i18nLabel": "UI_DisplayRoles", + "i18nDescription": "UI_DisplayRoles_Description", + "type": "boolean", + "valueSource": "packageValue", + "packageValue": true, + "value": true, + "section": "User_Interface", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 0 + }, + { + "_id": "Layout_Sidenav_Footer_Dark", + "_updatedAt": { + "$date": { + "$numberLong": "1685722754379" + } + }, + "ts": { + "$date": { + "$numberLong": "1685722754379" + } + }, + "i18nLabel": "Layout_Sidenav_Footer_Dark", + "i18nDescription": "Layout_Sidenav_Footer_description", + "type": "code", + "valueSource": "packageValue", + "packageValue": "\"Home\"", + "value": "\"Home\"", + "section": "Layout_Home_Page_Content_Title", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": false, + "env": false, + "autocomplete": true, + "sorter": 9 + }, + { + "_id": "Layout_Login_Hide_Logo", + "_updatedAt": { + "$date": { + "$numberLong": "1685723674021" + } + }, + "ts": { + "$date": { + "$numberLong": "1685722754332" + } + }, + "i18nLabel": "Layout_Login_Hide_Logo", + "i18nDescription": "Layout_Login_Hide_Logo_Description", + "type": "boolean", + "valueSource": "packageValue", + "packageValue": false, + "value": true, + "section": "Login", + "group": "Layout", + "public": true, + "secret": false, + "hidden": false, + "blocked": false, + "enterprise": true, + "env": false, + "autocomplete": true, + "sorter": 0 + } +] diff --git a/src/api/mod.rs b/src/api/mod.rs index 08b909b..def917a 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,4 +1,6 @@ pub mod permission_api; pub mod role_api; +pub mod sdui_api; +pub mod rawdoc_api; pub mod room_api; pub mod user_api; diff --git a/src/api/rawdoc_api.rs b/src/api/rawdoc_api.rs new file mode 100644 index 0000000..edfdc2e --- /dev/null +++ b/src/api/rawdoc_api.rs @@ -0,0 +1,12 @@ +use crate::repository::mongodb_repo::MongoRepo; +use rocket::{http::Status, serde::json::Json, State}; +use mongodb::bson::Document; + +#[get("/rawdocs")] +pub fn get_all_docs(db: &State) -> Result>, Status> { + let docs = db.get_all_docs(); + match docs { + Ok(docs) => Ok(Json(docs)), + Err(_) => Err(Status::InternalServerError), + } +} diff --git a/src/api/room_api.rs b/src/api/room_api.rs index c4417d8..a6fec96 100644 --- a/src/api/room_api.rs +++ b/src/api/room_api.rs @@ -1,10 +1,10 @@ use crate::{models::room_model::Room, repository::mongodb_repo::MongoRepo}; -use mongodb::bson::Document; +// use mongodb::bson::Document; use rocket::{http::Status, serde::json::Json, State}; #[get("/rooms")] -// pub fn get_all_rooms(db: &State) -> Result>, Status> { -pub fn get_all_rooms(db: &State) -> Result>, Status> { +pub fn get_all_rooms(db: &State) -> Result>, Status> { +// pub fn get_all_rooms(db: &State) -> Result>, Status> { let rooms = db.get_all_rooms(); match rooms { Ok(rooms) => Ok(Json(rooms)), diff --git a/src/api/sdui_api.rs b/src/api/sdui_api.rs new file mode 100644 index 0000000..9ad9581 --- /dev/null +++ b/src/api/sdui_api.rs @@ -0,0 +1,11 @@ +use crate::{models::sdui_model::Sdui, repository::mongodb_repo::MongoRepo}; +use rocket::{http::Status, serde::json::Json, State}; + +#[get("/layout")] +pub fn get_full_layout(db: &State) -> Result>, Status> { + let layout = db.get_full_layout(); + match layout { + Ok(layout) => Ok(Json(layout)), + Err(_) => Err(Status::InternalServerError), + } +} diff --git a/src/main.rs b/src/main.rs index 1acd38b..c265963 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,9 @@ mod tests; use api::{ permission_api::get_all_permissions, + sdui_api::get_full_layout, role_api::get_all_roles, + rawdoc_api::get_all_docs, room_api::get_all_rooms, user_api::{get_all_users, get_user}, }; @@ -32,52 +34,8 @@ fn rocket() -> _ { .mount("/", routes![get_all_users]) .mount("/", routes![get_all_roles]) .mount("/", routes![get_all_rooms]) + .mount("/", routes![get_full_layout]) + .mount("/", routes![get_all_docs]) .mount("/", routes![get_all_permissions]) .mount("/", routes![hello]) } - -/* -#[derive(Debug, Serialize, Deserialize)] -struct Session { - host: String, - roles: Vec, - #[serde(rename = "userId")] - user_id: String, - #[serde(rename = "loginToken")] - login_token: String, - #[serde(rename = "mostImportantRole")] - most_important_role: String, - #[serde( - rename = "loginAt", - with = "bson::serde_helpers::chrono_datetime_as_bson_datetime" - )] - login_at: chrono::DateTime, -} - -#[derive(Debug, Serialize, Deserialize)] -struct Role { - #[serde(rename = "_id")] - id: String, - // #[serde(rename = "_id", skip_serializing_if = "Option::is_none")] - // id: Option, - scope: String, - name: String, -} - -#[derive(Debug, Serialize, Deserialize)] -struct Permission { - #[serde(rename = "_id")] - id: String, - roles: Vec, -} - -#[derive(Debug, Serialize, Deserialize)] -struct User { - #[serde(rename = "_id")] - id: String, - roles: Vec, - status: String, - username: String, - active: bool, -} -*/ diff --git a/src/models/mod.rs b/src/models/mod.rs index 43722f5..3955587 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,5 +1,6 @@ pub mod permission_model; pub mod role_model; +pub mod sdui_model; pub mod room_model; pub mod setting_model; pub mod user_model; diff --git a/src/models/sdui_model.rs b/src/models/sdui_model.rs new file mode 100644 index 0000000..3a41f0d --- /dev/null +++ b/src/models/sdui_model.rs @@ -0,0 +1,43 @@ +use mongodb::bson::DateTime; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +#[serde(untagged)] +pub enum SomeVal { + Str(String), + Vec(Vec), + Bool(bool), + U64(u64), + I32(i32), + None, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Sdui { + #[serde(rename = "_id")] + id: String, + #[serde(rename = "_updatedAt")] + updated_at: DateTime, + ts: DateTime, + #[serde(rename = "i18nLabel")] + i18n_label: String, + #[serde(rename = "i18nDescription")] + i18n_desc: String, + #[serde(rename = "type")] + utype: String, + #[serde(rename = "valueSource")] + value_source: String, + #[serde(rename = "packageValue")] + package_value: Option, + value: Option, + section: String, + group: String, + public: bool, + secret: bool, + hidden: bool, + blocked: bool, + enterprise: bool, + env: bool, + autocomplete: bool, + sorter: Option, +} diff --git a/src/repository/mongodb_repo.rs b/src/repository/mongodb_repo.rs index 02adf71..b7ec0cc 100644 --- a/src/repository/mongodb_repo.rs +++ b/src/repository/mongodb_repo.rs @@ -4,6 +4,7 @@ use dotenv::dotenv; use crate::models::permission_model::Permission; use crate::models::role_model::Role; +use crate::models::sdui_model::Sdui; use crate::models::room_model::Room; use crate::models::user_model::User; use chrono::{TimeZone, Utc}; @@ -20,8 +21,8 @@ pub struct MongoRepo { rolecol: Collection, permcol: Collection, roomcol: Collection, - // roomcolraw: Collection, - // usercolraw: Collection, + sduicol: Collection, + acolraw: Collection, } impl MongoRepo { @@ -31,21 +32,25 @@ impl MongoRepo { Ok(v) => v.to_string(), Err(_) => format!("Error loading env variable"), }; + let cn = match env::var("COLLECTION") { + Ok(v) => v.to_string(), + Err(_) => format!("Error loading env variable"), + }; let client = Client::with_uri_str(uri).unwrap(); let db = client.database("rocketchat"); let usercol: Collection = db.collection("users"); let rolecol: Collection = db.collection("rocketchat_roles"); let permcol: Collection = db.collection("rocketchat_permissions"); let roomcol: Collection = db.collection("rocketchat_room"); - // let roomcolraw: Collection = db.collection("rocketchat_room"); - // let usercolraw: Collection = db.collection("users"); + let sduicol: Collection = db.collection("rocketchat_settings"); + let acolraw: Collection = db.collection(&cn); MongoRepo { usercol, permcol, rolecol, roomcol, - // roomcolraw, - // usercolraw, + sduicol, + acolraw, } } @@ -123,6 +128,17 @@ impl MongoRepo { Ok(rooms) } + pub fn get_all_docs(&self) -> Result, Error> { + // let filter = doc! { "$nor": [ { "year": 2023 }, { "year": 2022 }, { "month": 3 }, { "day": 3 } ]}; + let cursors = self + .acolraw + .find(None, None) + .ok() + .expect("Error getting list of docs"); + let docs = cursors.map(|doc| doc.unwrap()).collect(); + Ok(docs) + } + pub fn get_all_roles(&self) -> Result, Error> { let cursors = self @@ -134,6 +150,17 @@ impl MongoRepo { Ok(roles) } + pub fn get_full_layout(&self) -> Result, Error> { + let filter = doc! { "group": "Layout" }; + let cursors = self + .sduicol + .find(filter, None) + .ok() + .expect("Error getting list of layout elements"); + let layout = cursors.map(|doc| doc.unwrap()).collect(); + Ok(layout) + } + pub fn get_all_permissions(&self) -> Result, Error> { let filter = doc! { "$nor": [ { "roles": { "$exists": false } }, { "roles": { "$size": 0 } } ] }; From 52f0d3bfd36abaf693b1f724c9be3f839ea41e5d Mon Sep 17 00:00:00 2001 From: Dmitri Plakhov Date: Thu, 9 May 2024 17:24:11 +0300 Subject: [PATCH 05/19] SD UI via CSS :^) --- results/custom_homepage.html | 128 +++++++++++ results/custom_style.css | 397 +++++++++++++++++++++++++++++++++++ 2 files changed, 525 insertions(+) create mode 100644 results/custom_homepage.html create mode 100644 results/custom_style.css diff --git a/results/custom_homepage.html b/results/custom_homepage.html new file mode 100644 index 0000000..dd37c85 --- /dev/null +++ b/results/custom_homepage.html @@ -0,0 +1,128 @@ +
    +

    Добро пожаловать в MKB.Chat

    +

    Это меню поможет вам быстрее найти информацию

    +
    +
    +
    +
    +
    Мобильные приложения
    +
    Скачайте наше мобильное приложение c80m.4at
    + +
    +
    +
    +
    +
    Приложение для Windows
    +
    Установите наш чат на компьютер.
    + +
    +
    +
    +
    +
    Приложение для компьютера MacOS и Linux
    +
    Установите наш чат на компьютер.
    + +
    +
    +
    +
    +
    Документация
    +
    Изучите документацию по работе в корпоративном мессенджере.
    + +
    +
    +
    +
    +
    +
    + + +
  • Подключение с OpenVPN не работает
  • "Залипание" статуса away (необходима перезагрузка страницы)
  • "Утечка памяти" electron-приложения
  • +

    + + +
  • Интеграция RocketChat с Omnitracker
  • +

    + + +
    +
  • Большое использование памяти десктоп приложения
  • +
    + + +
    +
  • Похоже на утечку памяти, перезагрузка должна помочь ("нормальный расход" памяти ~400мб)
  • +
    +
    +

    +
  • Не могу подключиться к серверу. Что делать?
  • +
    + + +
    +
  • Проверьте домен к которому идет подключение. Со всех устройсв необходимо подключаться на im.mkb.ru
  • +
    +
    +

  • Не отображаются картинки/скриншоты.
  • + +
    +
  • Проверьте домен к которому идет подключение. Со всех устройсв необходимо подключаться на im.mkb.ru
  • +
    +
    +

  • Не могу скачать вложение. Что делать?
  • + +
    +
  • Скачивание и загрузка вложений доступно только внутри офисной сети.
  • +
    +
    +

  • Как удалить сервер в приложении и добавить новый?
  • + +
  • В приложении слева наверху есть кнопка "Файл", под вы найдете иконку ромба (фигуры). Нажмите на нее правой кнопкой мыши и выберите "удалить сервер". Рокет автоматически предложит новый, введите https://im.mkb.ru.Более подробная инструкция
  • +
    +
    +

    +
  • При попытке вставить код/формулу получаю ошибку: KaTeX parse error: Expected '}', got 'EOF' at end of input
  • + +
  • Пожалуйста, используйте символ обратной кавычки для заключения кода в блок: ``` CODE ``` Более подробная инструкция
  • +
    +

    +
    diff --git a/results/custom_style.css b/results/custom_style.css new file mode 100644 index 0000000..02c642b --- /dev/null +++ b/results/custom_style.css @@ -0,0 +1,397 @@ +--black-text-color: #242729; +/****************************************** + *************Circle Avatars************* + ******************************************/ + +body.dark-mode .rcx-avatar__element { + border-radius: 100%; +} + +body.dark-mode .avatar .avatar-image { + border-radius: 100%; +} + +body .rcx-avatar__element { + border-radius: 100%; +} + +body .avatar .avatar-image { + border-radius: 100%; +} + +/****************************************** + *************Bubble style************* + ******************************************/ +body .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left){ + border-radius: 1.15rem; + line-height: 1.25; + max-width: calc(83% - 140px); + padding: 0.5rem .875rem; + position: relative; + word-wrap: break-word; + align-items: flex-start; + /*background-color: var(--rcx-color-button-background-secondary-danger-focus,var(--own-true-light-color));*/ +} + +/*Перенос ФИО выше цитат */ +.rcx-message-header, .rcx-message-header__wrapper{ + order: -1; +} + +/* "Ушко" сообщений */ +/* +body .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left)::before{ + + content: ""; + height: 17px; + position: absolute; + +} +*/ +/*******************/ + + +/* переносим цитату наверх */ + +body .rcx-box .rcx-box--full .rcx-message-container > div:has(blockquote) { + order: -1; +} + +body .rcx-box .rcx-box--full .rcx-message-container > div:has(blockquote) > blockquote { + padding-top: 0 !important; + padding-bottom: 0 !important; +} +/**************************/ + +/* убираем полоску разделителя по дням */ + +body .rcx-message-divider__bar::after { + content: none !important; +} +body .rcx-message-divider__wrapper { + border-radius: 16px !important; + padding: 2px 18px; + font-size: 15px; + line-height: 18px; + background-color: #f4f4f4 !important; + color: #242729; +} +body ul.messages-list > div.rcx-message-divider { + margin: 20px !important; +} +/**************************************/ + +/* не знаю, что этот и следующий блок стилей делают */ +body .rcx-message[data-own="false"]:not(.rcx-message--sequential) > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left)::before{ + border: 0.4rem solid var(--rcx-color-button-background-secondary-danger-hover,var(--own-false-light-color)); + left: -0.35rem; + transform: translate(0, -0.2rem); + border-top-right-radius: 0.8rem; + border-bottom-left-radius: 2.2rem; + +} +body .rcx-message[data-own="true"]:not(.rcx-message--sequential) > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left)::before{ + border-right: var(--befort-border-radius1,0.8rem) solid var(--rcx-color-button-background-secondary-danger-focus,var(--own-true-light-color)); + right: var(--before-arrow,auto); + left: var(--before-auto,-0.35rem); + transform: translate(0, -0.2rem); + border-top-right-radius: var(--befort-border-radius1,unset); + border-bottom-right-radius: var(--befort-border-radius2,innerit); + /*border-top-left-radius: var(--before-unset,1.8rem); + border-bottom-left-radius: var(--before-unset,0.2rem); + border-top-right-radius: var(--before-initial,0.8rem);*/ + border-bottom-left-radius: var(--before-initial,2.2rem); + bottom: var(--before-01em, unset); /* для своих показываем внизу */ + /* + --before-unset: unset; + --befort-border-radius: 1.8rem; + --befort-border-radius: 0.2rem; + --before-arrow: -0.35rem; + */ +} +/***************************************************/ +body .rcx-message{ + --own-true-light-color: #cde3ff; + --own-false-light-color: #ffffff; + /* + --own-true-dark-color: #2b5278; + --own-false-dark-color: #182533; + --message-background-dark-color: #0e1621; + */ +} + +/* Контент сообщения к низу */ +body .rcx-message { + align-items: var(--flex-dir-flex-end, normal)!important; /* для своих показываем аватарки внизу */ +} +/****************************/ + +/* Разделение сообщение лево/право */ +body .rcx-message[data-own="true"]{ + flex-direction: var(--flex-dir-row-reverse,row)!important; +} +/***********************************/ + +/* Чужие сообщения */ + /* Цвет фона бабла */ +body .rcx-message[data-own="false"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) { + /* background-color: var(--rcx-color-button-background-secondary-danger-hover,rgba(255, 255, 255, 0.6)); */ + background-color: var(--rcx-color-button-background-secondary-danger-hover,#eff5fd); +} + /* Цвет текста */ +body .rcx-message[data-own="true"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > .rcx-message-body { + color: --black-text-color; +} + +/*цвет ссылок для своих и подчеркивание*/ +body .rcx-message[data-own="true"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > .rcx-message-body div div a { + /* color: var(--rcx-color-font-info, var(--rcx-color-primary-600, #ffffff)); + text-decoration: underline; */ +} + + /* Стили фона сообщения при фокусе */ +body .rcx-message[data-own="false"]:hover, body .rcx-message:focus { + /* background: var(--rcx-message-background-color-focus, var(--rcx-color-surface-hover, var(--rcx-color-neutral-200, #ABC7F4))) +*/ +} +/******************/ + +/* Свои сообщения */ + /* Цвет фона бабла */ +body .rcx-message[data-own="true"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) { + background-color: var(--rcx-color-button-background-secondary-danger-hover,#d8e7ff); +} + /* Цвет текста */ +body .rcx-message[data-own="true"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > .rcx-message-body { + /*color: var(--black-text-color,#fff) !important; */ +} + /* Стили имени */ +body .rcx-message[data-own="true"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > .rcx-message-header > .rcx-message-header__wrapper > .rcx-message-header__name-container > span { + /*color: var(--black-text-color, #fff) !important; */ +} + + /* Стили фона сообщения при фокусе */ +body .rcx-message[data-own="true"]:hover, body .rcx-message:focus { + background: var(--rcx-message-background-color-focus, var(--rcx-color-surface-hover, var(--rcx-color-neutral-200, #ABC7F4))) +} +/********************/ + +/* Системные сообщения по центру */ +body .rcx-box .rcx-box--full .rcx-message-system { + display: flex; + justify-content: center; +} + +body .rcx-box .rcx-box--full .rcx-message-system > .rcx-message-system__container { + width: auto; +} +/*********************************/ + +/* Аватакрки внизу, отключил из-за логики*/ +/* +body .rcx-message{ + align-items: flex-end; + +} +*/ + + +/* Фиксим ширину на динамику */ +body .rcx-message-container{ + flex-grow: 0; +} + +/* Галка внизу и время */ +body .rcx-message-container > div:not(.rcx-message-body):not(.rcx-message-header) { + inset-block-start: unset !important; + /*inset-inline-end: unset !important;*/ + /*bottom: 10px; */ + right: 5px; +} +body .rcx-message > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) div:has( > i.rcx-icon){ + bottom: 10px; +} +body .rcx-message-header__time { + right: 25px; + bottom: 10px; + position: absolute; +} +body .rcx-message > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) { + padding-right: 85px; +} +body .rcx-message[data-sequential='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) { + padding-right: 30px; +} +/* Цвет галки */ +body .rcx-message[data-own="true"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > div:not(.rcx-message-body):not(.rcx-message-header) > i { + /* color: var(--rcx-color-font-info, rgba(255, 255, 255, 0.6)) !important; */ +} +body .rcx-message[data-own="false"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > div:not(.rcx-message-body):not(.rcx-message-header) > i { + color: var(--rcx-color-font-info, var(--rcx-color-primary-600, #095AD2)) !important; +} + +/* Стили кнопок реакции */ + /* переносим меню ближе */ +body .rcx-message .rcx-message-toolbox { + right: auto; + top: 0; + +} +body .rcx-message:hover .rcx-box.rcx-box--full.rcx-message-toolbox__wrapper { + /* display: var(--flex-dir-flex,initial); */ + display: flex; + flex-direction: var(--flex-dir-row-reverse,row)!important; + align-items: flex-start; +} +body .rcx-message .rcx-message-toolbox { + position: sticky; +} +/**************************/ + + +/* Контейнер с сообщениями цвет фона */ +body div .main-content-flex { + /* background-color: var(--rcx-color-surface-room, #D8E5FA) !important; */ +} +/***************************/ + + +/* ToDo: Поправить на нормальный селектор */ +body .rcx-css-1rdomle:has( > aside.rcx-box.rcx-box--full.rcx-vertical-bar) { + --flex-dir-row-reverse: row-reverse; + /*--flex-dir-flex-end: flex-end; */ + --flex-dir-flex: flex; + --before-unset: unset; + --before-initial: initial; + --before-auto: auto; + --befort-border-radius1: 1.8rem; + --befort-border-radius2: 0.2rem; + --befort-border-radius3: 0.8rem; + --before-arrow: -0.35rem; + --before-01em: 0.1em; +} +body aside.rcx-box.rcx-box--full.rcx-vertical-bar .rcx-message-header__time { + right: auto; + bottom: auto; + position: relative; +} +body aside.rcx-vertical-bar .rcx-message-container:not(.rcx-message-container--left) { + max-width:90%!important; + padding-right: 30px!important; + overflow: hidden; +} +body aside.rcx-vertical-bar .rcx-message[data-own="false"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) { + background-color: var(--rcx-color-button-background-secondary-danger-hover,#f0f0f0); +} +body aside.rcx-vertical-bar .rcx-message .rcx-message-toolbox { + position: absolute; + right: 10px; +} + +body .rcx-message > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role="presentation"]){ + background: none !important; + +} +/*двигаем смайлик и реакции вправо */ +body .rcx-css-1rdomle:has( > aside.rcx-box.rcx-box--full.rcx-vertical-bar) .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role="presentation"]) .rcx-message-body, +body .rcx-css-1rdomle:has( > aside.rcx-box.rcx-box--full.rcx-vertical-bar) .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role="presentation"]) .rcx-message-block{ + align-self: flex-end; +} +body .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role="presentation"]) > .rcx-message-header > .rcx-message-header__wrapper > span > span { + color:var(--black-text-color) !important; +} + +/* fix цитат */ +/* ToDo: Поправить на нормальный селектор */ +body .rcx-css-8baznz { + /* border-radius: 0 10px 10px 0px!important; */ + background: none!important; + border-color: initial!important; + border-left-width: 0.2rem !important; + border-right-width: 0 !important; + border-top-width: 0 !important; + border-bottom-width: 0 !important; +} + +/* Фикс стилей цитаты в своих сообщениях */ +body .rcx-message[data-own='true'] > .rcx-message-container:not(.rcx-message-container--left) > .rcx-attachment__content > blockquote > div * { + /* color: rgba(255, 255, 255, 0.6) !important; */ +} + +/* Полоска цитаты - отключаю*/ +body .rcx-message[data-own='true'] > .rcx-message-container:not(.rcx-message-container--left) > .rcx-attachment__content > blockquote { + /*border-color: rgba(255, 255, 255, 0.8) !important; */ +} +/*****************************************/ + +/* Фикс штуковины для тредов (колокольчики и прочая шляпа) */ +body .rcx-message[data-own='true'] > .rcx-message-container:not(.rcx-message-container--left) > .rcx-message-block > div { + color: rgba(255, 255, 255, 0.8); +} + +@media (max-width: 1279.98px) { + /* ToDo: Поправить на нормальный селектор */ + body .main-content { + --flex-dir-row-reverse: row-reverse; + /* --flex-dir-flex-end: flex-end; */ + --flex-dir-flex: flex; + --before-unset: unset; + --before-initial: initial; + --before-auto: auto; + --befort-border-radius1: 1.8rem; + --befort-border-radius2: 0.2rem; + --befort-border-radius3: 0.8rem; + --before-arrow: -0.35rem; + --before-01em: 0.1em; + } + /*двигаем смайлик и реакции вправо */ + body .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role="presentation"]) .rcx-message-body, + body .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role="presentation"]) .rcx-message-block{ + align-self: flex-end; + } + /* убираем обрезку на 140 пикселей */ + body .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) { + max-width:80%; + } + /*Фиксируем для узких тулбокс */ + body .rcx-message[data-own='false'] .rcx-message-toolbox { + position: absolute; + right: 10px; + } + body .rcx-message[data-own='true'] .rcx-message-toolbox { + position: absolute; + left: 10px; + } + +} + +/* Большие эмодзи */ +body div[role="presentation"] span .rcx-message__emoji--big { + height: 4.75rem; + width: 4.75rem; +} + +/*****************/ +body .rcx-message-reactions__reaction{ + border-radius: var(--rcx-message-reaction-border-radius,var(--rcx-border-radius-medium,.65rem)); + padding: 0.175rem; + background-color: var(--rcx-color-button-background-secondary-danger-hover,#f7f8fa); + /* background-color: var(--rcx-message-reaction-hover-background-color,var(--rcx-color-surface-tint,var(--rcx-color-neutral-100,#f7f8fa))); */ +} + + +body .rcx-message[data-own='true'] > .rcx-message-container:not(.rcx-message-container--left) > .rcx-message-block > .rcx-message-reactions__container > .rcx-message-reactions__reaction { + border-radius: var(--rcx-message-reaction-border-radius,var(--rcx-border-radius-medium,.65rem)); + padding: 0.175rem; + background-color: var(--rcx-color-button-background-secondary-danger-hover,#fff) !important; + /* background-color: var(--rcx-message-reaction-hover-background-color,var(--rcx-color-surface-tint,var(--rcx-color-neutral-100,#f7f8fa))); */ +} + +/* Замена голосовалки */ +body .rcx-box.rcx-box--full.rcx-message-block--width-fixed.rcx-message-block span code.code-colors.inline { + background: -webkit-linear-gradient(327deg, #e3f2fff7 -15%, #6ebaf9f7 50%, #267cf5f7 135%); + background-clip: text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + letter-spacing: -0.05rem; +} From 2c551cf81788d432f56a8432fb59537ef4d142e6 Mon Sep 17 00:00:00 2001 From: Dmitri Plakhov Date: Thu, 9 May 2024 20:24:54 +0300 Subject: [PATCH 06/19] clear results --- .gitignore | 1 + results/custom_homepage.html | 128 ------ results/custom_style.css | 397 ----------------- results/layout.json | 843 ----------------------------------- 4 files changed, 1 insertion(+), 1368 deletions(-) delete mode 100644 results/custom_homepage.html delete mode 100644 results/custom_style.css delete mode 100644 results/layout.json diff --git a/.gitignore b/.gitignore index fedaa2b..a1d0104 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target .env +/results diff --git a/results/custom_homepage.html b/results/custom_homepage.html deleted file mode 100644 index dd37c85..0000000 --- a/results/custom_homepage.html +++ /dev/null @@ -1,128 +0,0 @@ -
    -

    Добро пожаловать в MKB.Chat

    -

    Это меню поможет вам быстрее найти информацию

    -
    -
    -
    -
    -
    Мобильные приложения
    -
    Скачайте наше мобильное приложение c80m.4at
    - -
    -
    -
    -
    -
    Приложение для Windows
    -
    Установите наш чат на компьютер.
    - -
    -
    -
    -
    -
    Приложение для компьютера MacOS и Linux
    -
    Установите наш чат на компьютер.
    - -
    -
    -
    -
    -
    Документация
    -
    Изучите документацию по работе в корпоративном мессенджере.
    - -
    -
    -
    -
    -
    -
    - - -
  • Подключение с OpenVPN не работает
  • "Залипание" статуса away (необходима перезагрузка страницы)
  • "Утечка памяти" electron-приложения
  • -

    - - -
  • Интеграция RocketChat с Omnitracker
  • -

    - - -
    -
  • Большое использование памяти десктоп приложения
  • -
    - - -
    -
  • Похоже на утечку памяти, перезагрузка должна помочь ("нормальный расход" памяти ~400мб)
  • -
    -
    -

    -
  • Не могу подключиться к серверу. Что делать?
  • -
    - - -
    -
  • Проверьте домен к которому идет подключение. Со всех устройсв необходимо подключаться на im.mkb.ru
  • -
    -
    -

  • Не отображаются картинки/скриншоты.
  • - -
    -
  • Проверьте домен к которому идет подключение. Со всех устройсв необходимо подключаться на im.mkb.ru
  • -
    -
    -

  • Не могу скачать вложение. Что делать?
  • - -
    -
  • Скачивание и загрузка вложений доступно только внутри офисной сети.
  • -
    -
    -

  • Как удалить сервер в приложении и добавить новый?
  • - -
  • В приложении слева наверху есть кнопка "Файл", под вы найдете иконку ромба (фигуры). Нажмите на нее правой кнопкой мыши и выберите "удалить сервер". Рокет автоматически предложит новый, введите https://im.mkb.ru.Более подробная инструкция
  • -
    -
    -

    -
  • При попытке вставить код/формулу получаю ошибку: KaTeX parse error: Expected '}', got 'EOF' at end of input
  • - -
  • Пожалуйста, используйте символ обратной кавычки для заключения кода в блок: ``` CODE ``` Более подробная инструкция
  • -
    -

    -
    diff --git a/results/custom_style.css b/results/custom_style.css deleted file mode 100644 index 02c642b..0000000 --- a/results/custom_style.css +++ /dev/null @@ -1,397 +0,0 @@ ---black-text-color: #242729; -/****************************************** - *************Circle Avatars************* - ******************************************/ - -body.dark-mode .rcx-avatar__element { - border-radius: 100%; -} - -body.dark-mode .avatar .avatar-image { - border-radius: 100%; -} - -body .rcx-avatar__element { - border-radius: 100%; -} - -body .avatar .avatar-image { - border-radius: 100%; -} - -/****************************************** - *************Bubble style************* - ******************************************/ -body .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left){ - border-radius: 1.15rem; - line-height: 1.25; - max-width: calc(83% - 140px); - padding: 0.5rem .875rem; - position: relative; - word-wrap: break-word; - align-items: flex-start; - /*background-color: var(--rcx-color-button-background-secondary-danger-focus,var(--own-true-light-color));*/ -} - -/*Перенос ФИО выше цитат */ -.rcx-message-header, .rcx-message-header__wrapper{ - order: -1; -} - -/* "Ушко" сообщений */ -/* -body .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left)::before{ - - content: ""; - height: 17px; - position: absolute; - -} -*/ -/*******************/ - - -/* переносим цитату наверх */ - -body .rcx-box .rcx-box--full .rcx-message-container > div:has(blockquote) { - order: -1; -} - -body .rcx-box .rcx-box--full .rcx-message-container > div:has(blockquote) > blockquote { - padding-top: 0 !important; - padding-bottom: 0 !important; -} -/**************************/ - -/* убираем полоску разделителя по дням */ - -body .rcx-message-divider__bar::after { - content: none !important; -} -body .rcx-message-divider__wrapper { - border-radius: 16px !important; - padding: 2px 18px; - font-size: 15px; - line-height: 18px; - background-color: #f4f4f4 !important; - color: #242729; -} -body ul.messages-list > div.rcx-message-divider { - margin: 20px !important; -} -/**************************************/ - -/* не знаю, что этот и следующий блок стилей делают */ -body .rcx-message[data-own="false"]:not(.rcx-message--sequential) > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left)::before{ - border: 0.4rem solid var(--rcx-color-button-background-secondary-danger-hover,var(--own-false-light-color)); - left: -0.35rem; - transform: translate(0, -0.2rem); - border-top-right-radius: 0.8rem; - border-bottom-left-radius: 2.2rem; - -} -body .rcx-message[data-own="true"]:not(.rcx-message--sequential) > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left)::before{ - border-right: var(--befort-border-radius1,0.8rem) solid var(--rcx-color-button-background-secondary-danger-focus,var(--own-true-light-color)); - right: var(--before-arrow,auto); - left: var(--before-auto,-0.35rem); - transform: translate(0, -0.2rem); - border-top-right-radius: var(--befort-border-radius1,unset); - border-bottom-right-radius: var(--befort-border-radius2,innerit); - /*border-top-left-radius: var(--before-unset,1.8rem); - border-bottom-left-radius: var(--before-unset,0.2rem); - border-top-right-radius: var(--before-initial,0.8rem);*/ - border-bottom-left-radius: var(--before-initial,2.2rem); - bottom: var(--before-01em, unset); /* для своих показываем внизу */ - /* - --before-unset: unset; - --befort-border-radius: 1.8rem; - --befort-border-radius: 0.2rem; - --before-arrow: -0.35rem; - */ -} -/***************************************************/ -body .rcx-message{ - --own-true-light-color: #cde3ff; - --own-false-light-color: #ffffff; - /* - --own-true-dark-color: #2b5278; - --own-false-dark-color: #182533; - --message-background-dark-color: #0e1621; - */ -} - -/* Контент сообщения к низу */ -body .rcx-message { - align-items: var(--flex-dir-flex-end, normal)!important; /* для своих показываем аватарки внизу */ -} -/****************************/ - -/* Разделение сообщение лево/право */ -body .rcx-message[data-own="true"]{ - flex-direction: var(--flex-dir-row-reverse,row)!important; -} -/***********************************/ - -/* Чужие сообщения */ - /* Цвет фона бабла */ -body .rcx-message[data-own="false"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) { - /* background-color: var(--rcx-color-button-background-secondary-danger-hover,rgba(255, 255, 255, 0.6)); */ - background-color: var(--rcx-color-button-background-secondary-danger-hover,#eff5fd); -} - /* Цвет текста */ -body .rcx-message[data-own="true"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > .rcx-message-body { - color: --black-text-color; -} - -/*цвет ссылок для своих и подчеркивание*/ -body .rcx-message[data-own="true"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > .rcx-message-body div div a { - /* color: var(--rcx-color-font-info, var(--rcx-color-primary-600, #ffffff)); - text-decoration: underline; */ -} - - /* Стили фона сообщения при фокусе */ -body .rcx-message[data-own="false"]:hover, body .rcx-message:focus { - /* background: var(--rcx-message-background-color-focus, var(--rcx-color-surface-hover, var(--rcx-color-neutral-200, #ABC7F4))) -*/ -} -/******************/ - -/* Свои сообщения */ - /* Цвет фона бабла */ -body .rcx-message[data-own="true"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) { - background-color: var(--rcx-color-button-background-secondary-danger-hover,#d8e7ff); -} - /* Цвет текста */ -body .rcx-message[data-own="true"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > .rcx-message-body { - /*color: var(--black-text-color,#fff) !important; */ -} - /* Стили имени */ -body .rcx-message[data-own="true"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > .rcx-message-header > .rcx-message-header__wrapper > .rcx-message-header__name-container > span { - /*color: var(--black-text-color, #fff) !important; */ -} - - /* Стили фона сообщения при фокусе */ -body .rcx-message[data-own="true"]:hover, body .rcx-message:focus { - background: var(--rcx-message-background-color-focus, var(--rcx-color-surface-hover, var(--rcx-color-neutral-200, #ABC7F4))) -} -/********************/ - -/* Системные сообщения по центру */ -body .rcx-box .rcx-box--full .rcx-message-system { - display: flex; - justify-content: center; -} - -body .rcx-box .rcx-box--full .rcx-message-system > .rcx-message-system__container { - width: auto; -} -/*********************************/ - -/* Аватакрки внизу, отключил из-за логики*/ -/* -body .rcx-message{ - align-items: flex-end; - -} -*/ - - -/* Фиксим ширину на динамику */ -body .rcx-message-container{ - flex-grow: 0; -} - -/* Галка внизу и время */ -body .rcx-message-container > div:not(.rcx-message-body):not(.rcx-message-header) { - inset-block-start: unset !important; - /*inset-inline-end: unset !important;*/ - /*bottom: 10px; */ - right: 5px; -} -body .rcx-message > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) div:has( > i.rcx-icon){ - bottom: 10px; -} -body .rcx-message-header__time { - right: 25px; - bottom: 10px; - position: absolute; -} -body .rcx-message > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) { - padding-right: 85px; -} -body .rcx-message[data-sequential='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) { - padding-right: 30px; -} -/* Цвет галки */ -body .rcx-message[data-own="true"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > div:not(.rcx-message-body):not(.rcx-message-header) > i { - /* color: var(--rcx-color-font-info, rgba(255, 255, 255, 0.6)) !important; */ -} -body .rcx-message[data-own="false"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > div:not(.rcx-message-body):not(.rcx-message-header) > i { - color: var(--rcx-color-font-info, var(--rcx-color-primary-600, #095AD2)) !important; -} - -/* Стили кнопок реакции */ - /* переносим меню ближе */ -body .rcx-message .rcx-message-toolbox { - right: auto; - top: 0; - -} -body .rcx-message:hover .rcx-box.rcx-box--full.rcx-message-toolbox__wrapper { - /* display: var(--flex-dir-flex,initial); */ - display: flex; - flex-direction: var(--flex-dir-row-reverse,row)!important; - align-items: flex-start; -} -body .rcx-message .rcx-message-toolbox { - position: sticky; -} -/**************************/ - - -/* Контейнер с сообщениями цвет фона */ -body div .main-content-flex { - /* background-color: var(--rcx-color-surface-room, #D8E5FA) !important; */ -} -/***************************/ - - -/* ToDo: Поправить на нормальный селектор */ -body .rcx-css-1rdomle:has( > aside.rcx-box.rcx-box--full.rcx-vertical-bar) { - --flex-dir-row-reverse: row-reverse; - /*--flex-dir-flex-end: flex-end; */ - --flex-dir-flex: flex; - --before-unset: unset; - --before-initial: initial; - --before-auto: auto; - --befort-border-radius1: 1.8rem; - --befort-border-radius2: 0.2rem; - --befort-border-radius3: 0.8rem; - --before-arrow: -0.35rem; - --before-01em: 0.1em; -} -body aside.rcx-box.rcx-box--full.rcx-vertical-bar .rcx-message-header__time { - right: auto; - bottom: auto; - position: relative; -} -body aside.rcx-vertical-bar .rcx-message-container:not(.rcx-message-container--left) { - max-width:90%!important; - padding-right: 30px!important; - overflow: hidden; -} -body aside.rcx-vertical-bar .rcx-message[data-own="false"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) { - background-color: var(--rcx-color-button-background-secondary-danger-hover,#f0f0f0); -} -body aside.rcx-vertical-bar .rcx-message .rcx-message-toolbox { - position: absolute; - right: 10px; -} - -body .rcx-message > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role="presentation"]){ - background: none !important; - -} -/*двигаем смайлик и реакции вправо */ -body .rcx-css-1rdomle:has( > aside.rcx-box.rcx-box--full.rcx-vertical-bar) .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role="presentation"]) .rcx-message-body, -body .rcx-css-1rdomle:has( > aside.rcx-box.rcx-box--full.rcx-vertical-bar) .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role="presentation"]) .rcx-message-block{ - align-self: flex-end; -} -body .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role="presentation"]) > .rcx-message-header > .rcx-message-header__wrapper > span > span { - color:var(--black-text-color) !important; -} - -/* fix цитат */ -/* ToDo: Поправить на нормальный селектор */ -body .rcx-css-8baznz { - /* border-radius: 0 10px 10px 0px!important; */ - background: none!important; - border-color: initial!important; - border-left-width: 0.2rem !important; - border-right-width: 0 !important; - border-top-width: 0 !important; - border-bottom-width: 0 !important; -} - -/* Фикс стилей цитаты в своих сообщениях */ -body .rcx-message[data-own='true'] > .rcx-message-container:not(.rcx-message-container--left) > .rcx-attachment__content > blockquote > div * { - /* color: rgba(255, 255, 255, 0.6) !important; */ -} - -/* Полоска цитаты - отключаю*/ -body .rcx-message[data-own='true'] > .rcx-message-container:not(.rcx-message-container--left) > .rcx-attachment__content > blockquote { - /*border-color: rgba(255, 255, 255, 0.8) !important; */ -} -/*****************************************/ - -/* Фикс штуковины для тредов (колокольчики и прочая шляпа) */ -body .rcx-message[data-own='true'] > .rcx-message-container:not(.rcx-message-container--left) > .rcx-message-block > div { - color: rgba(255, 255, 255, 0.8); -} - -@media (max-width: 1279.98px) { - /* ToDo: Поправить на нормальный селектор */ - body .main-content { - --flex-dir-row-reverse: row-reverse; - /* --flex-dir-flex-end: flex-end; */ - --flex-dir-flex: flex; - --before-unset: unset; - --before-initial: initial; - --before-auto: auto; - --befort-border-radius1: 1.8rem; - --befort-border-radius2: 0.2rem; - --befort-border-radius3: 0.8rem; - --before-arrow: -0.35rem; - --before-01em: 0.1em; - } - /*двигаем смайлик и реакции вправо */ - body .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role="presentation"]) .rcx-message-body, - body .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role="presentation"]) .rcx-message-block{ - align-self: flex-end; - } - /* убираем обрезку на 140 пикселей */ - body .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) { - max-width:80%; - } - /*Фиксируем для узких тулбокс */ - body .rcx-message[data-own='false'] .rcx-message-toolbox { - position: absolute; - right: 10px; - } - body .rcx-message[data-own='true'] .rcx-message-toolbox { - position: absolute; - left: 10px; - } - -} - -/* Большие эмодзи */ -body div[role="presentation"] span .rcx-message__emoji--big { - height: 4.75rem; - width: 4.75rem; -} - -/*****************/ -body .rcx-message-reactions__reaction{ - border-radius: var(--rcx-message-reaction-border-radius,var(--rcx-border-radius-medium,.65rem)); - padding: 0.175rem; - background-color: var(--rcx-color-button-background-secondary-danger-hover,#f7f8fa); - /* background-color: var(--rcx-message-reaction-hover-background-color,var(--rcx-color-surface-tint,var(--rcx-color-neutral-100,#f7f8fa))); */ -} - - -body .rcx-message[data-own='true'] > .rcx-message-container:not(.rcx-message-container--left) > .rcx-message-block > .rcx-message-reactions__container > .rcx-message-reactions__reaction { - border-radius: var(--rcx-message-reaction-border-radius,var(--rcx-border-radius-medium,.65rem)); - padding: 0.175rem; - background-color: var(--rcx-color-button-background-secondary-danger-hover,#fff) !important; - /* background-color: var(--rcx-message-reaction-hover-background-color,var(--rcx-color-surface-tint,var(--rcx-color-neutral-100,#f7f8fa))); */ -} - -/* Замена голосовалки */ -body .rcx-box.rcx-box--full.rcx-message-block--width-fixed.rcx-message-block span code.code-colors.inline { - background: -webkit-linear-gradient(327deg, #e3f2fff7 -15%, #6ebaf9f7 50%, #267cf5f7 135%); - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - letter-spacing: -0.05rem; -} diff --git a/results/layout.json b/results/layout.json deleted file mode 100644 index e3096e7..0000000 --- a/results/layout.json +++ /dev/null @@ -1,843 +0,0 @@ -[ - { - "_id": "UI_Use_Name_Avatar", - "_updatedAt": { - "$date": { - "$numberLong": "1682671172785" - } - }, - "ts": { - "$date": { - "$numberLong": "1682540018236" - } - }, - "i18nLabel": "UI_Use_Name_Avatar", - "i18nDescription": "UI_Use_Name_Avatar_Description", - "type": "boolean", - "valueSource": "packageValue", - "packageValue": false, - "value": true, - "section": "User_Interface", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 2 - }, - { - "_id": "UI_Unread_Counter_Style", - "_updatedAt": { - "$date": { - "$numberLong": "1682540018255" - } - }, - "ts": { - "$date": { - "$numberLong": "1682540018255" - } - }, - "i18nLabel": "UI_Unread_Counter_Style", - "i18nDescription": "UI_Unread_Counter_Style_Description", - "type": "select", - "valueSource": "packageValue", - "packageValue": "Different_Style_For_User_Mentions", - "value": "Different_Style_For_User_Mentions", - "section": "User_Interface", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 6 - }, - { - "_id": "Layout_Home_Custom_Block_Visible", - "_updatedAt": { - "$date": { - "$numberLong": "1689370741571" - } - }, - "ts": { - "$date": { - "$numberLong": "1685722754357" - } - }, - "i18nLabel": "Layout_Home_Custom_Block_Visible", - "i18nDescription": "Layout_Home_Custom_Block_Visible_Description", - "type": "boolean", - "valueSource": "packageValue", - "packageValue": false, - "value": true, - "section": "Layout_Home_Page_Content_Title", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 3 - }, - { - "_id": "UI_Group_Channels_By_Type", - "_updatedAt": { - "$date": { - "$numberLong": "1682540018234" - } - }, - "ts": { - "$date": { - "$numberLong": "1682540018234" - } - }, - "i18nLabel": "UI_Group_Channels_By_Type", - "i18nDescription": "UI_Group_Channels_By_Type_Description", - "type": "boolean", - "valueSource": "packageValue", - "packageValue": true, - "value": true, - "section": "User_Interface", - "group": "Layout", - "public": false, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 1 - }, - { - "_id": "Custom_Script_On_Logout", - "_updatedAt": { - "$date": { - "$numberLong": "1682630355676" - } - }, - "ts": { - "$date": { - "$numberLong": "1682540018224" - } - }, - "i18nLabel": "Custom_Script_On_Logout", - "i18nDescription": "Custom_Script_On_Logout_Description", - "type": "code", - "valueSource": "packageValue", - "packageValue": "//Add your script", - "value": "", - "section": "Custom_Scripts", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 0 - }, - { - "_id": "Layout_Home_Body", - "_updatedAt": { - "$date": { - "$numberLong": "1685722754354" - } - }, - "ts": { - "$date": { - "$numberLong": "1685722754354" - } - }, - "i18nLabel": "Layout_Home_Body", - "i18nDescription": "Layout_Custom_Content_Description", - "type": "code", - "valueSource": "packageValue", - "packageValue": "", - "value": "
    \n

    Добро пожаловать в MKB.Chat

    \n

    Это меню поможет вам быстрее найти информацию

    \n
    \n
    \n
    \n
    \n
    Мобильные приложения
    \n
    Скачайте наше мобильное приложение c80m.4at
    \n \n
    \n
    \n \n\n
    \n
    \n
    Приложение для Windows
    \n
    Установите наш чат на компьютер.
    \n \n
    \n
    \n
    \n
    \n
    Приложение для компьютера MacOS и Linux
    \n
    Установите наш чат на компьютер.
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    Документация
    \n
    Изучите документацию по работе в корпоративном мессенджере.
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n\n\n
    \n \n \n
    \n
  • Подключение с OpenVPN не работает
  • \n
  • \"Залипание\" статуса away (необходима перезагрузка страницы)
  • \n
  • \"Утечка памяти\" electron-приложения
  • \n
    \n
    \n

    \n
    \n \n \n
    \n
  • Интеграция RocketChat с Omnitracker
  • \n
    \n
    \n

    \n
    \n \n \n
    \n
  • Большое использование памяти десктоп приложения
  • \n
    \n \n \n
    \n
  • Похоже на утечку памяти, перезагрузка должна помочь (\"нормальный расход\" памяти ~400мб)
  • \n
    \n
    \n

    \n
  • Не могу подключиться к серверу. Что делать?
  • \n
    \n \n \n
    \n
  • Проверьте домен к которому идет подключение. Со всех устройсв необходимо подключаться на im.mkb.ru
  • \n
    \n
    \n

    \n\t
  • Не отображаются картинки/скриншоты.
  • \n\t
    \n\t\t\n\t \n\t
    \n\t
  • Проверьте домен к которому идет подключение. Со всех устройсв необходимо подключаться на im.mkb.ru
  • \n\t
    \n\t
    \n

    \n\t\t
  • Не могу скачать вложение. Что делать?
  • \n\t\t
    \n\t\t\t\n\t\t\t \n\t\t\t
    \n
  • Скачивание и загрузка вложений доступно только внутри офисной сети.
  • \n\t\t\t
    \n\t\t\t
    \n

    \n\t\t\t\t
  • Как удалить сервер в приложении и добавить новый?
  • \n\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t
    \n
  • В приложении слева наверху есть кнопка \"Файл\", под вы найдете иконку ромба (фигуры). Нажмите на нее правой кнопкой мыши и выберите \"удалить сервер\". Рокет автоматически предложит новый, введите https://im.mkb.ru.\nБолее подробная инструкция
  • \n\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t
    \n

    \n \t\t\t\t
  • При попытке вставить код/формулу получаю ошибку: KaTeX parse error: Expected '}', got 'EOF' at end of input
  • \n\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t
    \n
  • Пожалуйста, используйте символ обратной кавычки для заключения кода в блок:\n ```\n CODE\n \t\t\t\t\t\t\t\t\t ```\n Более подробная инструкция\n
  • \n
    \n
    \n

    \n
    \n
    ", - "section": "Layout_Home_Page_Content_Title", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 2 - }, - { - "_id": "Layout_Show_Home_Button", - "_updatedAt": { - "$date": { - "$numberLong": "1685722754350" - } - }, - "ts": { - "$date": { - "$numberLong": "1685722754350" - } - }, - "i18nLabel": "Layout_Show_Home_Button", - "i18nDescription": "Layout_Show_Home_Button_Description", - "type": "boolean", - "valueSource": "packageValue", - "packageValue": true, - "value": true, - "section": "Layout_Home_Page_Content_Title", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 1 - }, - { - "_id": "Layout_Login_Terms", - "_updatedAt": { - "$date": { - "$numberLong": "1699041697967" - } - }, - "ts": { - "$date": { - "$numberLong": "1699041680726" - } - }, - "i18nLabel": "Layout_Login_Terms", - "i18nDescription": "Layout_Login_Terms_Description", - "type": "code", - "valueSource": "packageValue", - "packageValue": "", - "value": "", - "section": "Layout_Home_Page_Content_Title", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 6 - }, - { - "_id": "theme-custom-css", - "_updatedAt": { - "$date": { - "$numberLong": "1696968898386" - } - }, - "ts": { - "$date": { - "$numberLong": "1682540016558" - } - }, - "i18nLabel": "theme-custom-css", - "i18nDescription": "theme-custom-css_Description", - "type": "code", - "valueSource": "packageValue", - "packageValue": "", - "value": "--black-text-color: #242729;\n/******************************************\n *************Circle Avatars*************\n ******************************************/\n\nbody.dark-mode .rcx-avatar__element {\n\tborder-radius: 100%;\n}\n\nbody.dark-mode .avatar .avatar-image {\n\tborder-radius: 100%;\n}\n\nbody .rcx-avatar__element {\n\tborder-radius: 100%;\n}\n\nbody .avatar .avatar-image {\n\tborder-radius: 100%;\n}\n\n/******************************************\n *************Bubble style*************\n ******************************************/\nbody .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left){\n border-radius: 1.15rem;\n line-height: 1.25;\n max-width: calc(83% - 140px);\n padding: 0.5rem .875rem;\n position: relative;\n word-wrap: break-word; \n align-items: flex-start;\n /*background-color: var(--rcx-color-button-background-secondary-danger-focus,var(--own-true-light-color));*/\n}\n\n/*Перенос ФИО выше цитат */\n.rcx-message-header, .rcx-message-header__wrapper{\n order: -1;\n}\n\n/* \"Ушко\" сообщений */\n/* \nbody .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left)::before{\n \n content: \"\";\n height: 17px;\n position: absolute;\n \n}\n*/\n/*******************/\n\n\n/* переносим цитату наверх */\n\nbody .rcx-box .rcx-box--full .rcx-message-container > div:has(blockquote) {\n order: -1;\n}\n\nbody .rcx-box .rcx-box--full .rcx-message-container > div:has(blockquote) > blockquote {\n padding-top: 0 !important;\n padding-bottom: 0 !important;\n}\n/**************************/\n\n/* убираем полоску разделителя по дням */\n\nbody .rcx-message-divider__bar::after {\n\tcontent: none !important;\n}\nbody .rcx-message-divider__wrapper {\n\tborder-radius: 16px !important;\n\tpadding: 2px 18px;\n\tfont-size: 15px;\n line-height: 18px;\n\tbackground-color: #f4f4f4 !important;\n\tcolor: #242729;\n}\nbody ul.messages-list > div.rcx-message-divider {\n\tmargin: 20px !important;\n}\n/**************************************/\n\n/* не знаю, что этот и следующий блок стилей делают */\nbody .rcx-message[data-own=\"false\"]:not(.rcx-message--sequential) > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left)::before{\n border: 0.4rem solid var(--rcx-color-button-background-secondary-danger-hover,var(--own-false-light-color));\n left: -0.35rem;\n transform: translate(0, -0.2rem);\n border-top-right-radius: 0.8rem;\n border-bottom-left-radius: 2.2rem;\n\n}\nbody .rcx-message[data-own=\"true\"]:not(.rcx-message--sequential) > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left)::before{\n\t\n border-right: var(--befort-border-radius1,0.8rem) solid var(--rcx-color-button-background-secondary-danger-focus,var(--own-true-light-color));\n right: var(--before-arrow,auto);\n \tleft: var(--before-auto,-0.35rem);\n transform: translate(0, -0.2rem);\n border-top-right-radius: var(--befort-border-radius1,unset);\n border-bottom-right-radius: var(--befort-border-radius2,innerit);\n /*border-top-left-radius: var(--before-unset,1.8rem);\n border-bottom-left-radius: var(--before-unset,0.2rem);\n border-top-right-radius: var(--before-initial,0.8rem);*/\n border-bottom-left-radius: var(--before-initial,2.2rem);\n \tbottom: var(--before-01em, unset); /* для своих показываем внизу */\n /*\n \t--before-unset: unset;\n \t--befort-border-radius: 1.8rem;\n \t--befort-border-radius: 0.2rem;\n \t--before-arrow: -0.35rem;\n */\n\n}\n/***************************************************/\nbody .rcx-message{\n\t--own-true-light-color: #cde3ff;\n --own-false-light-color: #ffffff; \n \t/*\n\t--own-true-dark-color: #2b5278;\n --own-false-dark-color: #182533;\n \t--message-background-dark-color: #0e1621;\n\t*/\n}\n\n\n\n/* Контент сообщения к низу */\nbody .rcx-message { \t\n align-items: var(--flex-dir-flex-end, normal)!important; /* для своих показываем аватарки внизу */\n}\n/****************************/\n\n/* Разделение сообщение лево/право */\nbody .rcx-message[data-own=\"true\"]{\n \tflex-direction: var(--flex-dir-row-reverse,row)!important;\n}\n/***********************************/\n\n/* Чужие сообщения */\n\t/* Цвет фона бабла */\nbody .rcx-message[data-own=\"false\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) {\n /* background-color: var(--rcx-color-button-background-secondary-danger-hover,rgba(255, 255, 255, 0.6)); */\n background-color: var(--rcx-color-button-background-secondary-danger-hover,#eff5fd); \t\n}\n \t/* Цвет текста */\nbody .rcx-message[data-own=\"true\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > .rcx-message-body {\n \tcolor: --black-text-color;\n}\n\n/*цвет ссылок для своих и подчеркивание*/\nbody .rcx-message[data-own=\"true\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > .rcx-message-body div div a {\n /* color: var(--rcx-color-font-info, var(--rcx-color-primary-600, #ffffff));\n text-decoration: underline; */\n}\n\n\t/* Стили фона сообщения при фокусе */\nbody .rcx-message[data-own=\"false\"]:hover, body .rcx-message:focus {\n /* background: var(--rcx-message-background-color-focus, var(--rcx-color-surface-hover, var(--rcx-color-neutral-200, #ABC7F4)))\n*/\n}\n/******************/\n\n/* Свои сообщения */\n \t/* Цвет фона бабла */\nbody .rcx-message[data-own=\"true\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) {\n \tbackground-color: var(--rcx-color-button-background-secondary-danger-hover,#d8e7ff); \n}\n \t/* Цвет текста */\nbody .rcx-message[data-own=\"true\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > .rcx-message-body {\n \t/*color: var(--black-text-color,#fff) !important; */\n}\n \t/* Стили имени */\nbody .rcx-message[data-own=\"true\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > .rcx-message-header > .rcx-message-header__wrapper > .rcx-message-header__name-container > span {\n \t/*color: var(--black-text-color, #fff) !important; */\n}\n\n\t/* Стили фона сообщения при фокусе */\nbody .rcx-message[data-own=\"true\"]:hover, body .rcx-message:focus {\n background: var(--rcx-message-background-color-focus, var(--rcx-color-surface-hover, var(--rcx-color-neutral-200, #ABC7F4)))\n}\n/********************/\n\n/* Системные сообщения по центру */\nbody .rcx-box .rcx-box--full .rcx-message-system {\n display: flex;\n justify-content: center;\n}\n\nbody .rcx-box .rcx-box--full .rcx-message-system > .rcx-message-system__container {\n width: auto;\n}\n/*********************************/\n\n/* Аватакрки внизу, отключил из-за логики*/\n/*\nbody .rcx-message{\n align-items: flex-end;\n \n}\n*/\n\n\n/* Фиксим ширину на динамику */\nbody .rcx-message-container{\n flex-grow: 0; \n}\n\n/* Галка внизу и время */\nbody .rcx-message-container > div:not(.rcx-message-body):not(.rcx-message-header) { \n inset-block-start: unset !important;\n /*inset-inline-end: unset !important;*/\n /*bottom: 10px; */\n right: 5px; \n}\nbody .rcx-message > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) div:has( > i.rcx-icon){\n\tbottom: 10px;\n}\nbody .rcx-message-header__time {\n right: 25px;\n bottom: 10px;\n position: absolute;\n}\nbody .rcx-message > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) {\n padding-right: 85px;\n}\nbody .rcx-message[data-sequential='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) {\n padding-right: 30px;\n}\n/* Цвет галки */\nbody .rcx-message[data-own=\"true\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > div:not(.rcx-message-body):not(.rcx-message-header) > i {\n /* color: var(--rcx-color-font-info, rgba(255, 255, 255, 0.6)) !important; */\n}\nbody .rcx-message[data-own=\"false\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) > div:not(.rcx-message-body):not(.rcx-message-header) > i {\n color: var(--rcx-color-font-info, var(--rcx-color-primary-600, #095AD2)) !important; \n}\n\n/* Стили кнопок реакции */\n\t/* переносим меню ближе */\nbody .rcx-message .rcx-message-toolbox {\n right: auto;\n top: 0;\n \n}\nbody .rcx-message:hover .rcx-box.rcx-box--full.rcx-message-toolbox__wrapper {\n /* display: var(--flex-dir-flex,initial); */\n display: flex;\n flex-direction: var(--flex-dir-row-reverse,row)!important; \n align-items: flex-start;\n}\nbody .rcx-message .rcx-message-toolbox {\n position: sticky;\n}\n/**************************/\n\n\n/* Контейнер с сообщениями цвет фона */\nbody div .main-content-flex {\n /* background-color: var(--rcx-color-surface-room, #D8E5FA) !important; */\n}\n/***************************/\n\n\n/* ToDo: Поправить на нормальный селектор */\nbody .rcx-css-1rdomle:has( > aside.rcx-box.rcx-box--full.rcx-vertical-bar) {\n\t--flex-dir-row-reverse: row-reverse;\n \t/*--flex-dir-flex-end: flex-end; */\t\n \t--flex-dir-flex: flex;\n \t--before-unset: unset;\n \t--before-initial: initial;\n \t--before-auto: auto;\n \t--befort-border-radius1: 1.8rem;\n \t--befort-border-radius2: 0.2rem;\n \t--befort-border-radius3: 0.8rem;\n \t--before-arrow: -0.35rem;\n \t--before-01em: 0.1em;\n \t\n \t\n \t\n}\nbody aside.rcx-box.rcx-box--full.rcx-vertical-bar .rcx-message-header__time {\n right: auto;\n bottom: auto;\n position: relative;\n}\nbody aside.rcx-vertical-bar .rcx-message-container:not(.rcx-message-container--left) {\n max-width:90%!important;\n padding-right: 30px!important;\n overflow: hidden;\n}\nbody aside.rcx-vertical-bar .rcx-message[data-own=\"false\"] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) {\n background-color: var(--rcx-color-button-background-secondary-danger-hover,#f0f0f0);\n}\nbody aside.rcx-vertical-bar .rcx-message .rcx-message-toolbox {\n position: absolute;\n \tright: 10px;\n}\n\nbody .rcx-message > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role=\"presentation\"]){\n background: none !important;\n\n}\n/*двигаем смайлик и реакции вправо */\nbody .rcx-css-1rdomle:has( > aside.rcx-box.rcx-box--full.rcx-vertical-bar) .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role=\"presentation\"]) .rcx-message-body,\nbody .rcx-css-1rdomle:has( > aside.rcx-box.rcx-box--full.rcx-vertical-bar) .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role=\"presentation\"]) .rcx-message-block{\n align-self: flex-end;\n}\nbody .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role=\"presentation\"]) > .rcx-message-header > .rcx-message-header__wrapper > span > span {\n color:var(--black-text-color) !important;\n}\n\n/* fix цитат */\n/* ToDo: Поправить на нормальный селектор */\nbody .rcx-css-8baznz {\n /* border-radius: 0 10px 10px 0px!important; */\n background: none!important;\n border-color: initial!important;\n border-left-width: 0.2rem !important;\n border-right-width: 0 !important;\n border-top-width: 0 !important;\n border-bottom-width: 0 !important;\n}\n\n/* Фикс стилей цитаты в своих сообщениях */\nbody .rcx-message[data-own='true'] > .rcx-message-container:not(.rcx-message-container--left) > .rcx-attachment__content > blockquote > div * {\n /* color: rgba(255, 255, 255, 0.6) !important; */\n}\n\n/* Полоска цитаты - отключаю*/\nbody .rcx-message[data-own='true'] > .rcx-message-container:not(.rcx-message-container--left) > .rcx-attachment__content > blockquote {\n /*border-color: rgba(255, 255, 255, 0.8) !important; */\n}\n/*****************************************/\n\n/* Фикс штуковины для тредов (колокольчики и прочая шляпа) */\nbody .rcx-message[data-own='true'] > .rcx-message-container:not(.rcx-message-container--left) > .rcx-message-block > div {\n color: rgba(255, 255, 255, 0.8);\n}\n\n@media (max-width: 1279.98px) {\n /* ToDo: Поправить на нормальный селектор */\n body .main-content {\n\t--flex-dir-row-reverse: row-reverse;\n /*\t--flex-dir-flex-end: flex-end; */\t\n \t--flex-dir-flex: flex;\n \t--before-unset: unset;\n \t--before-initial: initial;\n \t--before-auto: auto;\n \t--befort-border-radius1: 1.8rem;\n \t--befort-border-radius2: 0.2rem;\n \t--befort-border-radius3: 0.8rem;\n \t--before-arrow: -0.35rem;\n \t--before-01em: 0.1em;\n\t}\n /*двигаем смайлик и реакции вправо */\n \tbody .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role=\"presentation\"]) .rcx-message-body,\n \tbody .rcx-message[data-own='true'] > .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left):has(.rcx-message-body div div[role=\"presentation\"]) .rcx-message-block{\n align-self: flex-end;\n \t}\n /* убираем обрезку на 140 пикселей */\n\tbody .rcx-box.rcx-box--full.rcx-message-container:not(.rcx-message-container--left) {\n\t\tmax-width:80%;\n \t}\n \t/*Фиксируем для узких тулбокс */\n body .rcx-message[data-own='false'] .rcx-message-toolbox {\n position: absolute;\n right: 10px;\n\t}\n body .rcx-message[data-own='true'] .rcx-message-toolbox {\n position: absolute;\n left: 10px;\n\t}\n\n}\n\n/* Большие эмодзи */\nbody div[role=\"presentation\"] span .rcx-message__emoji--big {\n height: 4.75rem;\n width: 4.75rem;\n}\n\n/*****************/\nbody .rcx-message-reactions__reaction{\n border-radius: var(--rcx-message-reaction-border-radius,var(--rcx-border-radius-medium,.65rem));\n padding: 0.175rem;\n \tbackground-color: var(--rcx-color-button-background-secondary-danger-hover,#f7f8fa);\n \t /* background-color: var(--rcx-message-reaction-hover-background-color,var(--rcx-color-surface-tint,var(--rcx-color-neutral-100,#f7f8fa))); */\n}\n\n\nbody .rcx-message[data-own='true'] > .rcx-message-container:not(.rcx-message-container--left) > .rcx-message-block > .rcx-message-reactions__container > .rcx-message-reactions__reaction {\n border-radius: var(--rcx-message-reaction-border-radius,var(--rcx-border-radius-medium,.65rem));\n padding: 0.175rem;\n \t background-color: var(--rcx-color-button-background-secondary-danger-hover,#fff) !important;\n \t /* background-color: var(--rcx-message-reaction-hover-background-color,var(--rcx-color-surface-tint,var(--rcx-color-neutral-100,#f7f8fa))); */\n}\n\n/* Замена голосовалки */\nbody .rcx-box.rcx-box--full.rcx-message-block--width-fixed.rcx-message-block span code.code-colors.inline {\n background: -webkit-linear-gradient(327deg, #e3f2fff7 -15%, #6ebaf9f7 50%, #267cf5f7 135%);\n background-clip: text;\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n letter-spacing: -0.05rem;\n}", - "section": "Custom CSS", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 0 - }, - { - "_id": "UI_Show_top_navbar_embedded_layout", - "_updatedAt": { - "$date": { - "$numberLong": "1682540018261" - } - }, - "ts": { - "$date": { - "$numberLong": "1682540018261" - } - }, - "i18nLabel": "UI_Show_top_navbar_embedded_layout", - "i18nDescription": "UI_Show_top_navbar_embedded_layout_Description", - "type": "boolean", - "valueSource": "packageValue", - "packageValue": false, - "value": false, - "section": "User_Interface", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 8 - }, - { - "_id": "Layout_Terms_of_Service", - "_updatedAt": { - "$date": { - "$numberLong": "1685722754364" - } - }, - "ts": { - "$date": { - "$numberLong": "1685722754364" - } - }, - "i18nLabel": "Layout_Terms_of_Service", - "i18nDescription": "Layout_Terms_of_Service_Description", - "type": "code", - "valueSource": "packageValue", - "packageValue": "Terms of Service
    Go to APP SETTINGS → Layout to customize this page.", - "value": "Terms of Service
    Go to APP SETTINGS → Layout to customize this page.", - "section": "Layout_Home_Page_Content_Title", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 5 - }, - { - "_id": "UI_Click_Direct_Message", - "_updatedAt": { - "$date": { - "$numberLong": "1682540018241" - } - }, - "ts": { - "$date": { - "$numberLong": "1682540018241" - } - }, - "i18nLabel": "UI_Click_Direct_Message", - "i18nDescription": "UI_Click_Direct_Message_Description", - "type": "boolean", - "valueSource": "packageValue", - "packageValue": false, - "value": false, - "section": "User_Interface", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 4 - }, - { - "_id": "Accounts_ShowFormLogin", - "_updatedAt": { - "$date": { - "$numberLong": "1685722754344" - } - }, - "ts": { - "$date": { - "$numberLong": "1685722754343" - } - }, - "i18nLabel": "Accounts_ShowFormLogin", - "i18nDescription": "Accounts_ShowFormLogin_Description", - "type": "boolean", - "valueSource": "packageValue", - "packageValue": true, - "value": true, - "section": "Login", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 4 - }, - { - "_id": "Custom_Script_Logged_Out", - "_updatedAt": { - "$date": { - "$numberLong": "1682540018226" - } - }, - "ts": { - "$date": { - "$numberLong": "1682540018226" - } - }, - "i18nLabel": "Custom_Script_Logged_Out", - "i18nDescription": "Custom_Script_Logged_Out_Description", - "type": "code", - "valueSource": "packageValue", - "packageValue": "//Add your script", - "value": "//Add your script", - "section": "Custom_Scripts", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 1 - }, - { - "_id": "Layout_Privacy_Policy", - "_updatedAt": { - "$date": { - "$numberLong": "1685722754372" - } - }, - "ts": { - "$date": { - "$numberLong": "1685722754372" - } - }, - "i18nLabel": "Layout_Privacy_Policy", - "i18nDescription": "Layout_Privacy_Policy_Description", - "type": "code", - "valueSource": "packageValue", - "packageValue": "Privacy Policy
    Go to APP SETTINGS → Layout to customize this page.", - "value": "Privacy Policy
    Go to APP SETTINGS → Layout to customize this page.", - "section": "Layout_Home_Page_Content_Title", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 7 - }, - { - "_id": "UI_Allow_room_names_with_special_chars", - "_updatedAt": { - "$date": { - "$numberLong": "1682540018258" - } - }, - "ts": { - "$date": { - "$numberLong": "1682540018258" - } - }, - "i18nLabel": "UI_Allow_room_names_with_special_chars", - "i18nDescription": "UI_Allow_room_names_with_special_chars_Description", - "type": "boolean", - "valueSource": "packageValue", - "packageValue": false, - "value": true, - "section": "User_Interface", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 7 - }, - { - "_id": "UI_Use_Real_Name", - "_updatedAt": { - "$date": { - "$numberLong": "1682540018239" - } - }, - "ts": { - "$date": { - "$numberLong": "1682540018239" - } - }, - "i18nLabel": "UI_Use_Real_Name", - "i18nDescription": "UI_Use_Real_Name_Description", - "type": "boolean", - "valueSource": "packageValue", - "packageValue": false, - "value": true, - "section": "User_Interface", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 3 - }, - { - "_id": "Layout_Sidenav_Footer", - "_updatedAt": { - "$date": { - "$numberLong": "1685722754382" - } - }, - "ts": { - "$date": { - "$numberLong": "1685722754382" - } - }, - "i18nLabel": "Layout_Sidenav_Footer", - "i18nDescription": "Layout_Sidenav_Footer_description", - "type": "code", - "valueSource": "packageValue", - "packageValue": "\"Home\"", - "value": "\"Home\"", - "section": "Layout_Home_Page_Content_Title", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 10 - }, - { - "_id": "Custom_Script_Logged_In", - "_updatedAt": { - "$date": { - "$numberLong": "1695240692287" - } - }, - "ts": { - "$date": { - "$numberLong": "1682540018229" - } - }, - "i18nLabel": "Custom_Script_Logged_In", - "i18nDescription": "Custom_Script_Logged_In_Description", - "type": "code", - "valueSource": "packageValue", - "packageValue": "//Add your script", - "value": "\n//Hide footer\nvar onReadyDomElement = function(element, callback) {\n if (jQuery(element).length) {\n callback(jQuery(element));\n } else {\n setTimeout(function() {\n onReadyDomElement(element, callback);\n }, 100);\n }\n};\n// example\nonReadyDomElement('div.rcx-sidebar-footer', function(e) {\n e.remove();\n console.log(\"footer removed\");\n});", - "section": "Custom_Scripts", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 2 - }, - { - "_id": "Layout_Login_Template", - "_updatedAt": { - "$date": { - "$numberLong": "1685723681451" - } - }, - "ts": { - "$date": { - "$numberLong": "1685722754341" - } - }, - "i18nLabel": "Layout_Login_Template", - "i18nDescription": "Layout_Login_Template_Description", - "type": "select", - "valueSource": "packageValue", - "packageValue": "horizontal-template", - "value": "vertical-template", - "section": "Login", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": true, - "env": false, - "autocomplete": true, - "sorter": 3 - }, - { - "_id": "Layout_Legal_Notice", - "_updatedAt": { - "$date": { - "$numberLong": "1685722754376" - } - }, - "ts": { - "$date": { - "$numberLong": "1685722754376" - } - }, - "i18nLabel": "Layout_Legal_Notice", - "i18nDescription": "Layout_Legal_Notice_Description", - "type": "code", - "valueSource": "packageValue", - "packageValue": "Legal Notice
    Go to APP SETTINGS -> Layout to customize this page.", - "value": "Legal Notice
    Go to APP SETTINGS -> Layout to customize this page.", - "section": "Layout_Home_Page_Content_Title", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 8 - }, - { - "_id": "Layout_Custom_Body_Only", - "_updatedAt": { - "$date": { - "$numberLong": "1689370754560" - } - }, - "ts": { - "$date": { - "$numberLong": "1685722754360" - } - }, - "i18nLabel": "Layout_Custom_Body_Only", - "i18nDescription": "Layout_Custom_Body_Only_Description", - "type": "boolean", - "valueSource": "packageValue", - "packageValue": false, - "value": true, - "section": "Layout_Home_Page_Content_Title", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": true, - "env": false, - "autocomplete": true, - "sorter": 4 - }, - { - "_id": "Layout_Login_Hide_Title", - "_updatedAt": { - "$date": { - "$numberLong": "1685723663057" - } - }, - "ts": { - "$date": { - "$numberLong": "1685722754335" - } - }, - "i18nLabel": "Layout_Login_Hide_Title", - "i18nDescription": "Layout_Login_Hide_Title_Description", - "type": "boolean", - "valueSource": "packageValue", - "packageValue": false, - "value": true, - "section": "Login", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": true, - "env": false, - "autocomplete": true, - "sorter": 1 - }, - { - "_id": "Layout_Login_Hide_Powered_By", - "_updatedAt": { - "$date": { - "$numberLong": "1685723663057" - } - }, - "ts": { - "$date": { - "$numberLong": "1685722754338" - } - }, - "i18nLabel": "Layout_Login_Hide_Powered_By", - "i18nDescription": "Layout_Login_Hide_Powered_By_Description", - "type": "boolean", - "valueSource": "packageValue", - "packageValue": false, - "value": true, - "section": "Login", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": true, - "env": false, - "autocomplete": true, - "sorter": 2 - }, - { - "_id": "Number_of_users_autocomplete_suggestions", - "_updatedAt": { - "$date": { - "$numberLong": "1682540018243" - } - }, - "ts": { - "$date": { - "$numberLong": "1682540018243" - } - }, - "i18nLabel": "Number_of_users_autocomplete_suggestions", - "i18nDescription": "Number_of_users_autocomplete_suggestions_Description", - "type": "int", - "valueSource": "packageValue", - "packageValue": 5, - "value": 5, - "section": "User_Interface", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 5 - }, - { - "_id": "Layout_Home_Title", - "_updatedAt": { - "$date": { - "$numberLong": "1685722754347" - } - }, - "ts": { - "$date": { - "$numberLong": "1685722754347" - } - }, - "i18nLabel": "Layout_Home_Title", - "i18nDescription": "Layout_Home_Title_Description", - "type": "string", - "valueSource": "packageValue", - "packageValue": "Home", - "value": "Home", - "section": "Layout_Home_Page_Content_Title", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 0 - }, - { - "_id": "UI_DisplayRoles", - "_updatedAt": { - "$date": { - "$numberLong": "1682540018231" - } - }, - "ts": { - "$date": { - "$numberLong": "1682540018231" - } - }, - "i18nLabel": "UI_DisplayRoles", - "i18nDescription": "UI_DisplayRoles_Description", - "type": "boolean", - "valueSource": "packageValue", - "packageValue": true, - "value": true, - "section": "User_Interface", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 0 - }, - { - "_id": "Layout_Sidenav_Footer_Dark", - "_updatedAt": { - "$date": { - "$numberLong": "1685722754379" - } - }, - "ts": { - "$date": { - "$numberLong": "1685722754379" - } - }, - "i18nLabel": "Layout_Sidenav_Footer_Dark", - "i18nDescription": "Layout_Sidenav_Footer_description", - "type": "code", - "valueSource": "packageValue", - "packageValue": "\"Home\"", - "value": "\"Home\"", - "section": "Layout_Home_Page_Content_Title", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": false, - "env": false, - "autocomplete": true, - "sorter": 9 - }, - { - "_id": "Layout_Login_Hide_Logo", - "_updatedAt": { - "$date": { - "$numberLong": "1685723674021" - } - }, - "ts": { - "$date": { - "$numberLong": "1685722754332" - } - }, - "i18nLabel": "Layout_Login_Hide_Logo", - "i18nDescription": "Layout_Login_Hide_Logo_Description", - "type": "boolean", - "valueSource": "packageValue", - "packageValue": false, - "value": true, - "section": "Login", - "group": "Layout", - "public": true, - "secret": false, - "hidden": false, - "blocked": false, - "enterprise": true, - "env": false, - "autocomplete": true, - "sorter": 0 - } -] From 167ed8f22a2107e8330cecf3b2ccbf9980f46e87 Mon Sep 17 00:00:00 2001 From: Aran Varun Date: Fri, 10 May 2024 00:10:45 +0300 Subject: [PATCH 07/19] Tera templating --- Cargo.lock | 451 ++++++++++++++++++++++++++++++++- Cargo.toml | 7 +- Rocket.toml | 1 + src/api/user_api.rs | 13 +- src/main.rs | 11 +- src/repository/mongodb_repo.rs | 56 ++-- templates/base.html.tera | 19 ++ templates/error/404.html.tera | 11 + templates/index.html.tera | 7 + templates/user.html.tera | 5 + templates/users.html.tera | 17 ++ 11 files changed, 560 insertions(+), 38 deletions(-) create mode 100644 templates/base.html.tera create mode 100644 templates/error/404.html.tera create mode 100644 templates/index.html.tera create mode 100644 templates/user.html.tera create mode 100644 templates/users.html.tera diff --git a/Cargo.lock b/Cargo.lock index 4a1d1a4..ebf0951 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -422,6 +422,16 @@ dependencies = [ "uuid", ] +[[package]] +name = "bstr" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -466,6 +476,28 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "chrono-tz" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59ae0466b83e838b81a54256c39d5d7c20b9d7daa10510a242d9b75abd5936e" +dependencies = [ + "chrono", + "chrono-tz-build", + "phf", +] + +[[package]] +name = "chrono-tz-build" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "433e39f13c9a060046954e0592a8d0a4bcb1040125cbf91cb8ee58964cfb350f" +dependencies = [ + "parse-zoneinfo", + "phf", + "phf_codegen", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -507,6 +539,34 @@ dependencies = [ "libc", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.19" @@ -597,6 +657,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "deunicode" +version = "1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322ef0094744e63628e6f0eb2295517f79276a5b342a4c2ff3042566ca181d4e" + [[package]] name = "devise" version = "0.4.1" @@ -778,6 +844,18 @@ dependencies = [ "version_check", ] +[[package]] +name = "filetime" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.4.1", + "windows-sys 0.52.0", +] + [[package]] name = "finl_unicode" version = "1.2.0" @@ -799,6 +877,15 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + [[package]] name = "funty" version = "2.0.0" @@ -964,6 +1051,30 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "globset" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", +] + +[[package]] +name = "globwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +dependencies = [ + "bitflags 1.3.2", + "ignore", + "walkdir", +] + [[package]] name = "gloo-timers" version = "0.2.6" @@ -1073,6 +1184,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humansize" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" +dependencies = [ + "libm", +] + [[package]] name = "hyper" version = "0.14.28" @@ -1147,6 +1267,22 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "ignore" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata 0.4.6", + "same-file", + "walkdir", + "winapi-util", +] + [[package]] name = "indexmap" version = "2.2.6" @@ -1164,6 +1300,26 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "instant" version = "0.1.12" @@ -1228,6 +1384,26 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + [[package]] name = "kv-log-macro" version = "1.0.7" @@ -1249,6 +1425,12 @@ version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + [[package]] name = "linked-hash-map" version = "0.5.6" @@ -1369,6 +1551,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", + "log", "wasi", "windows-sys 0.48.0", ] @@ -1442,6 +1625,34 @@ dependencies = [ "version_check", ] +[[package]] +name = "normpath" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5831952a9476f2fed74b77d74182fa5ddc4d21c72ec45a333b250e3ed0272804" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "notify" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +dependencies = [ + "bitflags 2.5.0", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "log", + "mio", + "walkdir", + "windows-sys 0.48.0", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1522,11 +1733,20 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.1", "smallvec", "windows-targets 0.52.5", ] +[[package]] +name = "parse-zoneinfo" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24" +dependencies = [ + "regex", +] + [[package]] name = "pbkdf2" version = "0.11.0" @@ -1565,6 +1785,89 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pest" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "pest_meta" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -1704,6 +2007,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_syscall" version = "0.5.1" @@ -1857,6 +2169,19 @@ dependencies = [ "version_check", ] +[[package]] +name = "rocket_dyn_templates" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04bfc006e547e4f72b760ab861f5943b688aed8a82c4977b5500c98f5d17dbfa" +dependencies = [ + "normpath", + "notify", + "rocket", + "tera", + "walkdir", +] + [[package]] name = "rocket_http" version = "0.5.0" @@ -1893,7 +2218,9 @@ dependencies = [ "dotenv", "mongodb", "rocket", + "rocket_dyn_templates", "serde", + "tera", ] [[package]] @@ -2000,6 +2327,15 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -2155,6 +2491,12 @@ dependencies = [ "libc", ] +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + [[package]] name = "slab" version = "0.4.9" @@ -2164,6 +2506,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "slug" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bd94acec9c8da640005f8e135a39fc0372e74535e6b368b7a04b875f784c8c4" +dependencies = [ + "deunicode", + "wasm-bindgen", +] + [[package]] name = "smallvec" version = "1.13.2" @@ -2283,6 +2635,28 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "tera" +version = "1.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "970dff17c11e884a4a09bc76e3a17ef71e01bb13447a11e85226e254fe6d10b8" +dependencies = [ + "chrono", + "chrono-tz", + "globwalk", + "humansize", + "lazy_static", + "percent-encoding", + "pest", + "pest_derive", + "rand", + "regex", + "serde", + "serde_json", + "slug", + "unic-segment", +] + [[package]] name = "thiserror" version = "1.0.59" @@ -2602,6 +2976,12 @@ dependencies = [ "serde", ] +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + [[package]] name = "uncased" version = "0.9.10" @@ -2612,6 +2992,56 @@ dependencies = [ "version_check", ] +[[package]] +name = "unic-char-property" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +dependencies = [ + "unic-char-range", +] + +[[package]] +name = "unic-char-range" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" + +[[package]] +name = "unic-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" + +[[package]] +name = "unic-segment" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23" +dependencies = [ + "unic-ucd-segment", +] + +[[package]] +name = "unic-ucd-segment" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-version" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" +dependencies = [ + "unic-common", +] + [[package]] name = "unicode-bidi" version = "0.3.15" @@ -2690,6 +3120,16 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -2809,6 +3249,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 43db1d8..b249e77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rocketmongoman" -version = "0.1.1" +version = "0.1.2" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -13,8 +13,13 @@ serde = { version = "1.0", features = ["derive"] } dotenv = "0.15.0" bson = { version = "2", features = ["chrono-0_4"] } # Needed for using chrono datetime in doc chrono = "0.4" # Used for setting DateTimes +tera = { version = "1", default-features = false } [dependencies.mongodb] version = "2.8.2" default-features = false features = ["sync"] + +[dependencies.rocket_dyn_templates] +version = "0.1.0" +features = ["tera"] diff --git a/Rocket.toml b/Rocket.toml index c3d76b4..4fcfc37 100644 --- a/Rocket.toml +++ b/Rocket.toml @@ -9,6 +9,7 @@ key = "a default app-key" extra = false ident = "Rocket" ip_header = "CF-Connecting-IP" +template_dir = "templates" [debug] address = "127.0.0.1" diff --git a/src/api/user_api.rs b/src/api/user_api.rs index 07679ba..5bc8cbd 100644 --- a/src/api/user_api.rs +++ b/src/api/user_api.rs @@ -2,6 +2,16 @@ use crate::{models::user_model::User, repository::mongodb_repo::MongoRepo}; use rocket::{http::Status, serde::json::Json, State}; // use mongodb::bson::Document; // use mongodb::results::InsertOneResult; +use rocket_dyn_templates::{context, Template}; + +#[get("/")] +pub fn index(db: &State) -> Template { + let users = db.get_all_users_obj(); + match users { + Ok(users) => Template::render("index", context! { users: users }), + Err(_) => Template::render("error/404", context! { uri: "" }), + } +} /* #[post("/user", data = "")] @@ -38,8 +48,7 @@ pub fn get_user(db: &State, path: String) -> Result, Statu #[get("/users")] pub fn get_all_users(db: &State) -> Result>, Status> { -// pub fn get_all_users(db: &State) -> Result>, Status> { - let users = db.get_all_users(); + let users = db.get_all_users_obj(); match users { Ok(users) => Ok(Json(users)), Err(_) => Err(Status::InternalServerError), diff --git a/src/main.rs b/src/main.rs index c265963..4535087 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,16 +10,17 @@ mod tests; use api::{ permission_api::get_all_permissions, - sdui_api::get_full_layout, - role_api::get_all_roles, rawdoc_api::get_all_docs, + role_api::get_all_roles, room_api::get_all_rooms, - user_api::{get_all_users, get_user}, + sdui_api::get_full_layout, + user_api::{get_all_users, get_user, index}, }; use repository::{localdb_repo::LocalRepo, mongodb_repo::MongoRepo}; use rocket::{get, http::Status, serde::json::Json}; +use rocket_dyn_templates::Template; -#[get("/")] +#[get("/hello")] fn hello() -> Result, Status> { Ok(Json(String::from("Hello world"))) } @@ -38,4 +39,6 @@ fn rocket() -> _ { .mount("/", routes![get_all_docs]) .mount("/", routes![get_all_permissions]) .mount("/", routes![hello]) + .mount("/", routes![index]) + .attach(Template::fairing()) } diff --git a/src/repository/mongodb_repo.rs b/src/repository/mongodb_repo.rs index b7ec0cc..cbccb3f 100644 --- a/src/repository/mongodb_repo.rs +++ b/src/repository/mongodb_repo.rs @@ -4,14 +4,14 @@ use dotenv::dotenv; use crate::models::permission_model::Permission; use crate::models::role_model::Role; -use crate::models::sdui_model::Sdui; use crate::models::room_model::Room; +use crate::models::sdui_model::Sdui; use crate::models::user_model::User; use chrono::{TimeZone, Utc}; use mongodb::{ + bson::extjson::de::Error, bson::{doc, Document}, options::FindOptions, - bson::extjson::de::Error, sync::{Client, Collection}, // results::InsertOneResult, }; @@ -82,21 +82,19 @@ impl MongoRepo { Ok(user_detail.unwrap()) } - pub fn get_all_users(&self) -> Result, Error> { - // pub fn get_all_users(&self) -> Result, Error> { - let trashold = Utc.ymd(2024,1,1).and_hms_opt(0,0,0); - let filter = - doc! { "$nor": [ - { "roles": { "$exists": false } }, - { "roles": { "$size": 0 } }, - { "roles": { "$in": ["Deactivated"] } }, - { "__rooms": { "$exists": false } }, - { "__rooms": { "$size": 0 } }, - { "active": false }, - { "lastLogin": { "$exists": false } }, - { "lastLogin": { "$lt": trashold } }, - { "emails.verified": false } - ] }; + pub fn get_all_users_obj(&self) -> Result, Error> { + let trashold = Utc.ymd(2024, 1, 1).and_hms_opt(0, 0, 0); + let filter = doc! { "$nor": [ + { "roles": { "$exists": false } }, + { "roles": { "$size": 0 } }, + { "roles": { "$in": ["Deactivated"] } }, + { "__rooms": { "$exists": false } }, + { "__rooms": { "$size": 0 } }, + { "active": false }, + { "lastLogin": { "$exists": false } }, + { "lastLogin": { "$lt": trashold } }, + { "emails.verified": false } + ] }; let cursors = self .usercol .find(filter, None) @@ -107,18 +105,17 @@ impl MongoRepo { } pub fn get_all_rooms(&self) -> Result, Error> { - // pub fn get_all_rooms(&self) -> Result, Error> { - let trashold = Utc.ymd(2024,4,1).and_hms_opt(0,0,0); - let filter = - doc! { "$nor": [ - { "usersCount": { "$exists": false } }, - { "usersCount": { "$lt": 2 } }, - { "msgs": { "$exists": false } }, - { "msgs": { "$lt": 1 } }, - { "_updatedAt": { "$lt": trashold } } - ] }; - //let find_options = None; - let find_options = FindOptions::builder().sort(doc! { "msgs": 1, "usersCount": 1 }).build(); + let trashold = Utc.ymd(2024, 4, 1).and_hms_opt(0, 0, 0); + let filter = doc! { "$nor": [ + { "usersCount": { "$exists": false } }, + { "usersCount": { "$lt": 2 } }, + { "msgs": { "$exists": false } }, + { "msgs": { "$lt": 1 } }, + { "_updatedAt": { "$lt": trashold } } + ] }; + let find_options = FindOptions::builder() + .sort(doc! { "msgs": 1, "usersCount": 1 }) + .build(); let cursors = self .roomcol .find(filter, find_options) @@ -139,7 +136,6 @@ impl MongoRepo { Ok(docs) } - pub fn get_all_roles(&self) -> Result, Error> { let cursors = self .rolecol diff --git a/templates/base.html.tera b/templates/base.html.tera new file mode 100644 index 0000000..e81023b --- /dev/null +++ b/templates/base.html.tera @@ -0,0 +1,19 @@ + + + + + {# + + #} + Index + {% block head %}{% endblock head %} + + +
    + {% block content %} + {% endblock content%} +
    + + diff --git a/templates/error/404.html.tera b/templates/error/404.html.tera new file mode 100644 index 0000000..afda653 --- /dev/null +++ b/templates/error/404.html.tera @@ -0,0 +1,11 @@ + + + + + 404 - tera + + +

    404: Hey! There's nothing here.

    + The page at {{ uri }} does not exist! + + diff --git a/templates/index.html.tera b/templates/index.html.tera new file mode 100644 index 0000000..5faa830 --- /dev/null +++ b/templates/index.html.tera @@ -0,0 +1,7 @@ +{% extends "base" %} + +{% block content %} + +{% include "users" %} + +{% endblock content %} diff --git a/templates/user.html.tera b/templates/user.html.tera new file mode 100644 index 0000000..c17029e --- /dev/null +++ b/templates/user.html.tera @@ -0,0 +1,5 @@ + + + {{ user._id }} + {{ user.username }} + diff --git a/templates/users.html.tera b/templates/users.html.tera new file mode 100644 index 0000000..e5599fc --- /dev/null +++ b/templates/users.html.tera @@ -0,0 +1,17 @@ + +

    Users

    +
    + + + + + + + + + {% for user in users %} + {% include "user" %} + {% endfor %} + +
    IDUsername
    +
    From d75ac2260bc67e6c5119f85028d72d0e7497d0fc Mon Sep 17 00:00:00 2001 From: Dmitri Plakhov Date: Fri, 10 May 2024 01:05:02 +0300 Subject: [PATCH 08/19] index page --- Cargo.lock | 2 +- src/api/role_api.rs | 13 +++++++++++++ src/main.rs | 3 ++- src/repository/mongodb_repo.rs | 11 +++++++++++ templates/user.html.tera | 9 +++++++++ templates/users.html.tera | 4 ++++ 6 files changed, 40 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ebf0951..7bc5101 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2211,7 +2211,7 @@ dependencies = [ [[package]] name = "rocketmongoman" -version = "0.1.1" +version = "0.1.2" dependencies = [ "bson", "chrono", diff --git a/src/api/role_api.rs b/src/api/role_api.rs index 1e4ed03..41b3239 100644 --- a/src/api/role_api.rs +++ b/src/api/role_api.rs @@ -1,6 +1,19 @@ use crate::{models::role_model::Role, repository::mongodb_repo::MongoRepo}; use rocket::{http::Status, serde::json::Json, State}; +#[get("/role/")] +pub fn get_role(db: &State, path: String) -> Result, Status> { + let id = path; + if id.is_empty() { + return Err(Status::BadRequest); + }; + let role = db.get_role(&id); + match role { + Ok(role) => Ok(Json(role)), + Err(_) => Err(Status::InternalServerError), + } +} + #[get("/roles")] pub fn get_all_roles(db: &State) -> Result>, Status> { let roles = db.get_all_roles(); diff --git a/src/main.rs b/src/main.rs index 4535087..da66fb7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ mod tests; use api::{ permission_api::get_all_permissions, rawdoc_api::get_all_docs, - role_api::get_all_roles, + role_api::{get_all_roles, get_role}, room_api::get_all_rooms, sdui_api::get_full_layout, user_api::{get_all_users, get_user, index}, @@ -32,6 +32,7 @@ fn rocket() -> _ { rocket::build() .manage(mdb) .mount("/", routes![get_user]) + .mount("/", routes![get_role]) .mount("/", routes![get_all_users]) .mount("/", routes![get_all_roles]) .mount("/", routes![get_all_rooms]) diff --git a/src/repository/mongodb_repo.rs b/src/repository/mongodb_repo.rs index cbccb3f..db709fd 100644 --- a/src/repository/mongodb_repo.rs +++ b/src/repository/mongodb_repo.rs @@ -146,6 +146,17 @@ impl MongoRepo { Ok(roles) } + pub fn get_role(&self, id: &String) -> Result { + let filter = doc! {"_id": id}; + let role = self + .rolecol + .find_one(filter, None) + .ok() + .expect("Error getting role's detail"); + Ok(role.unwrap()) + } + + pub fn get_full_layout(&self) -> Result, Error> { let filter = doc! { "group": "Layout" }; let cursors = self diff --git a/templates/user.html.tera b/templates/user.html.tera index c17029e..b89ecd0 100644 --- a/templates/user.html.tera +++ b/templates/user.html.tera @@ -1,5 +1,14 @@ + {{ user._id }} {{ user.username }} + + {{user.name}} + {# if user.custom_fields is defined #} + {# endif #} + + {% for e in user.roles %} {{e}} {% endfor %} + {% for e in user.emails %} {{e.address}} {% endfor %} + {{user.status}} diff --git a/templates/users.html.tera b/templates/users.html.tera index e5599fc..2703cfb 100644 --- a/templates/users.html.tera +++ b/templates/users.html.tera @@ -6,6 +6,10 @@ ID Username + Name, Fields + Roles + Emails + Status From 878db955f49629f5a6142630e0ea21334e6637bb Mon Sep 17 00:00:00 2001 From: Aran Varun Date: Fri, 10 May 2024 23:57:21 +0300 Subject: [PATCH 09/19] fix tera template --- src/main.rs | 25 +++++++++++++++---------- src/repository/mongodb_repo.rs | 21 ++++++++++----------- src/tests.rs | 9 ++++++++- templates/user.html.tera | 18 +++++++++++++----- 4 files changed, 46 insertions(+), 27 deletions(-) diff --git a/src/main.rs b/src/main.rs index da66fb7..e3948cf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,15 +31,20 @@ fn rocket() -> _ { let mdb = MongoRepo::init(); rocket::build() .manage(mdb) - .mount("/", routes![get_user]) - .mount("/", routes![get_role]) - .mount("/", routes![get_all_users]) - .mount("/", routes![get_all_roles]) - .mount("/", routes![get_all_rooms]) - .mount("/", routes![get_full_layout]) - .mount("/", routes![get_all_docs]) - .mount("/", routes![get_all_permissions]) - .mount("/", routes![hello]) - .mount("/", routes![index]) + .mount( + "/", + routes![ + get_user, + get_role, + get_all_users, + get_all_roles, + get_all_rooms, + get_full_layout, + get_all_docs, + get_all_permissions, + hello, + index + ], + ) .attach(Template::fairing()) } diff --git a/src/repository/mongodb_repo.rs b/src/repository/mongodb_repo.rs index db709fd..eb2f461 100644 --- a/src/repository/mongodb_repo.rs +++ b/src/repository/mongodb_repo.rs @@ -2,12 +2,11 @@ use std::env; extern crate dotenv; use dotenv::dotenv; -use crate::models::permission_model::Permission; -use crate::models::role_model::Role; -use crate::models::room_model::Room; -use crate::models::sdui_model::Sdui; -use crate::models::user_model::User; -use chrono::{TimeZone, Utc}; +use crate::models::{ + permission_model::Permission, role_model::Role, room_model::Room, sdui_model::Sdui, + user_model::User, +}; +// use chrono::{TimeZone, Utc}; use mongodb::{ bson::extjson::de::Error, bson::{doc, Document}, @@ -83,6 +82,7 @@ impl MongoRepo { } pub fn get_all_users_obj(&self) -> Result, Error> { + /* let trashold = Utc.ymd(2024, 1, 1).and_hms_opt(0, 0, 0); let filter = doc! { "$nor": [ { "roles": { "$exists": false } }, @@ -95,9 +95,10 @@ impl MongoRepo { { "lastLogin": { "$lt": trashold } }, { "emails.verified": false } ] }; + */ let cursors = self .usercol - .find(filter, None) + .find(None, None) .ok() .expect("Error getting list of users"); let users = cursors.map(|doc| doc.unwrap()).collect(); @@ -105,13 +106,12 @@ impl MongoRepo { } pub fn get_all_rooms(&self) -> Result, Error> { - let trashold = Utc.ymd(2024, 4, 1).and_hms_opt(0, 0, 0); + // let trashold = Utc.ymd(2024, 4, 1).and_hms_opt(0, 0, 0); let filter = doc! { "$nor": [ { "usersCount": { "$exists": false } }, { "usersCount": { "$lt": 2 } }, { "msgs": { "$exists": false } }, - { "msgs": { "$lt": 1 } }, - { "_updatedAt": { "$lt": trashold } } + { "msgs": { "$lt": 1 } } ] }; let find_options = FindOptions::builder() .sort(doc! { "msgs": 1, "usersCount": 1 }) @@ -156,7 +156,6 @@ impl MongoRepo { Ok(role.unwrap()) } - pub fn get_full_layout(&self) -> Result, Error> { let filter = doc! { "group": "Layout" }; let cursors = self diff --git a/src/tests.rs b/src/tests.rs index ad8104d..eac9c27 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -4,10 +4,17 @@ use rocket::local::blocking::Client; #[test] fn hello() { let client = Client::tracked(super::rocket()).unwrap(); - let response = client.get("/").dispatch(); + let response = client.get("/hello").dispatch(); assert_eq!(response.into_string(), Some("\"Hello world\"".into())); } +#[test] +fn index() { + let client = Client::tracked(super::rocket()).unwrap(); + let response = client.get("/").dispatch(); + assert_eq!(response.status(), Status::Ok); +} + #[test] fn roles() { let client = Client::tracked(super::rocket()).unwrap(); diff --git a/templates/user.html.tera b/templates/user.html.tera index b89ecd0..17af6d8 100644 --- a/templates/user.html.tera +++ b/templates/user.html.tera @@ -4,11 +4,19 @@ {{ user._id }} {{ user.username }} - {{user.name}} - {# if user.custom_fields is defined #} - {# endif #} + {% if user.name is defined %} + {{user.name}} + {% endif %} - {% for e in user.roles %} {{e}} {% endfor %} - {% for e in user.emails %} {{e.address}} {% endfor %} + + {% if user.roles is object %} + {% for e in user.roles %} {{e}} {% endfor %} + {% endif %} + + + {% if user.emails is object %} + {% for e in user.emails %} {{e.address}} {% endfor %} + {% endif %} + {{user.status}} From 2a622b88263d76207a25f9b56acfcc8fee911138 Mon Sep 17 00:00:00 2001 From: Aran Varun Date: Sat, 11 May 2024 01:17:53 +0300 Subject: [PATCH 10/19] get user email with htmx load delay and special endpoint --- src/api/user_api.rs | 17 +++++++++++ src/main.rs | 12 ++++++-- src/models/user_model.rs | 8 ++--- static/css/style.css | 66 ++++++++++++++++++++++++++++++++++++++++ static/favicon.ico | 0 static/js/htmx-1.9.12.js | 1 + templates/base.html.tera | 7 ++--- templates/user.html.tera | 10 ++++-- 8 files changed, 108 insertions(+), 13 deletions(-) create mode 100644 static/css/style.css create mode 100644 static/favicon.ico create mode 100644 static/js/htmx-1.9.12.js diff --git a/src/api/user_api.rs b/src/api/user_api.rs index 5bc8cbd..d0dd545 100644 --- a/src/api/user_api.rs +++ b/src/api/user_api.rs @@ -46,6 +46,23 @@ pub fn get_user(db: &State, path: String) -> Result, Statu } } +#[get("/user//email")] +pub fn get_user_email(db: &State, path: String) -> Result { + let id = path; + if id.is_empty() { + return Err(Status::BadRequest); + }; + let user = db.get_user(&id); + match user { + Ok(user) => Ok(if let Some(email) = user.emails.unwrap().first() { + email.address.to_string() + } else { + "None".to_string() + }), + Err(_) => Err(Status::InternalServerError), + } +} + #[get("/users")] pub fn get_all_users(db: &State) -> Result>, Status> { let users = db.get_all_users_obj(); diff --git a/src/main.rs b/src/main.rs index e3948cf..76e4814 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,12 +14,18 @@ use api::{ role_api::{get_all_roles, get_role}, room_api::get_all_rooms, sdui_api::get_full_layout, - user_api::{get_all_users, get_user, index}, + user_api::{get_all_users, get_user, get_user_email, index}, }; use repository::{localdb_repo::LocalRepo, mongodb_repo::MongoRepo}; -use rocket::{get, http::Status, serde::json::Json}; +use rocket::{ + fs::{relative, FileServer}, + get, + http::Status, + serde::json::Json, +}; use rocket_dyn_templates::Template; +// for test only #[get("/hello")] fn hello() -> Result, Status> { Ok(Json(String::from("Hello world"))) @@ -31,10 +37,12 @@ fn rocket() -> _ { let mdb = MongoRepo::init(); rocket::build() .manage(mdb) + .mount("/", FileServer::from(relative!("static"))) .mount( "/", routes![ get_user, + get_user_email, get_role, get_all_users, get_all_roles, diff --git a/src/models/user_model.rs b/src/models/user_model.rs index 681e29d..213169a 100644 --- a/src/models/user_model.rs +++ b/src/models/user_model.rs @@ -27,9 +27,9 @@ struct Service { } #[derive(Debug, Serialize, Deserialize)] -struct Email { - address: String, - verified: Option, +pub struct Email { + pub address: String, + pub verified: Option, } #[derive(Debug, Serialize, Deserialize)] @@ -41,7 +41,7 @@ pub struct User { roles: Vec, services: Option, status: String, - emails: Option>, + pub emails: Option>, active: bool, ldap: Option, #[serde(rename = "importIds")] diff --git a/static/css/style.css b/static/css/style.css new file mode 100644 index 0000000..1a1ce0e --- /dev/null +++ b/static/css/style.css @@ -0,0 +1,66 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +:root { + --background-color: #f5f5f5; + --primary-color: #1a73e8; + --text-color: #202124; +} + +@media screen and (prefers-color-scheme: dark) { + :root { + --background-color: #202124; + --primary-color: #1a73e8; + --text-color: #f5f5f5; + } +} + +body { + font-family: 'Roboto', sans-serif; + background-color: var(--background-color); + color: var(--text-color); +} + +main { + width: 100%; + max-width: + 75rem; + margin: 0 auto; + padding: 1rem; +} + +.counters { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); + grid-gap: 1rem; +} + +.counter { + border: 1px solid var(--primary-color); + border-radius: 0.25rem; + padding: 1rem; + margin-bottom: 1rem; + width: 100%; + + display: flex; + flex-direction: row; + justify-content: space-between; +} + +.counter button { + border: none; + background-color: var(--primary-color); + color: var(--background-color); + padding: 0.5rem 1rem; + border-radius: 0.25rem; + font-size: 1rem; + cursor: pointer; +} + +.counter-count { + line-height: 1; + font-weight: bold; +} \ No newline at end of file diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/static/js/htmx-1.9.12.js b/static/js/htmx-1.9.12.js new file mode 100644 index 0000000..de5f0f1 --- /dev/null +++ b/static/js/htmx-1.9.12.js @@ -0,0 +1 @@ +(function(e,t){if(typeof define==="function"&&define.amd){define([],t)}else if(typeof module==="object"&&module.exports){module.exports=t()}else{e.htmx=e.htmx||t()}})(typeof self!=="undefined"?self:this,function(){return function(){"use strict";var Q={onLoad:F,process:zt,on:de,off:ge,trigger:ce,ajax:Nr,find:C,findAll:f,closest:v,values:function(e,t){var r=dr(e,t||"post");return r.values},remove:_,addClass:z,removeClass:n,toggleClass:$,takeClass:W,defineExtension:Ur,removeExtension:Br,logAll:V,logNone:j,logger:null,config:{historyEnabled:true,historyCacheSize:10,refreshOnHistoryMiss:false,defaultSwapStyle:"innerHTML",defaultSwapDelay:0,defaultSettleDelay:20,includeIndicatorStyles:true,indicatorClass:"htmx-indicator",requestClass:"htmx-request",addedClass:"htmx-added",settlingClass:"htmx-settling",swappingClass:"htmx-swapping",allowEval:true,allowScriptTags:true,inlineScriptNonce:"",attributesToSettle:["class","style","width","height"],withCredentials:false,timeout:0,wsReconnectDelay:"full-jitter",wsBinaryType:"blob",disableSelector:"[hx-disable], [data-hx-disable]",useTemplateFragments:false,scrollBehavior:"smooth",defaultFocusScroll:false,getCacheBusterParam:false,globalViewTransitions:false,methodsThatUseUrlParams:["get"],selfRequestsOnly:false,ignoreTitle:false,scrollIntoViewOnBoost:true,triggerSpecsCache:null},parseInterval:d,_:t,createEventSource:function(e){return new EventSource(e,{withCredentials:true})},createWebSocket:function(e){var t=new WebSocket(e,[]);t.binaryType=Q.config.wsBinaryType;return t},version:"1.9.12"};var r={addTriggerHandler:Lt,bodyContains:se,canAccessLocalStorage:U,findThisElement:xe,filterValues:yr,hasAttribute:o,getAttributeValue:te,getClosestAttributeValue:ne,getClosestMatch:c,getExpressionVars:Hr,getHeaders:xr,getInputValues:dr,getInternalData:ae,getSwapSpecification:wr,getTriggerSpecs:it,getTarget:ye,makeFragment:l,mergeObjects:le,makeSettleInfo:T,oobSwap:Ee,querySelectorExt:ue,selectAndSwap:je,settleImmediately:nr,shouldCancel:ut,triggerEvent:ce,triggerErrorEvent:fe,withExtensions:R};var w=["get","post","put","delete","patch"];var i=w.map(function(e){return"[hx-"+e+"], [data-hx-"+e+"]"}).join(", ");var S=e("head"),q=e("title"),H=e("svg",true);function e(e,t){return new RegExp("<"+e+"(\\s[^>]*>|>)([\\s\\S]*?)<\\/"+e+">",!!t?"gim":"im")}function d(e){if(e==undefined){return undefined}let t=NaN;if(e.slice(-2)=="ms"){t=parseFloat(e.slice(0,-2))}else if(e.slice(-1)=="s"){t=parseFloat(e.slice(0,-1))*1e3}else if(e.slice(-1)=="m"){t=parseFloat(e.slice(0,-1))*1e3*60}else{t=parseFloat(e)}return isNaN(t)?undefined:t}function ee(e,t){return e.getAttribute&&e.getAttribute(t)}function o(e,t){return e.hasAttribute&&(e.hasAttribute(t)||e.hasAttribute("data-"+t))}function te(e,t){return ee(e,t)||ee(e,"data-"+t)}function u(e){return e.parentElement}function re(){return document}function c(e,t){while(e&&!t(e)){e=u(e)}return e?e:null}function L(e,t,r){var n=te(t,r);var i=te(t,"hx-disinherit");if(e!==t&&i&&(i==="*"||i.split(" ").indexOf(r)>=0)){return"unset"}else{return n}}function ne(t,r){var n=null;c(t,function(e){return n=L(t,e,r)});if(n!=="unset"){return n}}function h(e,t){var r=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.oMatchesSelector;return r&&r.call(e,t)}function A(e){var t=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i;var r=t.exec(e);if(r){return r[1].toLowerCase()}else{return""}}function s(e,t){var r=new DOMParser;var n=r.parseFromString(e,"text/html");var i=n.body;while(t>0){t--;i=i.firstChild}if(i==null){i=re().createDocumentFragment()}return i}function N(e){return/",0);var a=i.querySelector("template").content;if(Q.config.allowScriptTags){oe(a.querySelectorAll("script"),function(e){if(Q.config.inlineScriptNonce){e.nonce=Q.config.inlineScriptNonce}e.htmxExecuted=navigator.userAgent.indexOf("Firefox")===-1})}else{oe(a.querySelectorAll("script"),function(e){_(e)})}return a}switch(r){case"thead":case"tbody":case"tfoot":case"colgroup":case"caption":return s(""+n+"
    ",1);case"col":return s(""+n+"
    ",2);case"tr":return s(""+n+"
    ",2);case"td":case"th":return s(""+n+"
    ",3);case"script":case"style":return s("
    "+n+"
    ",1);default:return s(n,0)}}function ie(e){if(e){e()}}function I(e,t){return Object.prototype.toString.call(e)==="[object "+t+"]"}function k(e){return I(e,"Function")}function P(e){return I(e,"Object")}function ae(e){var t="htmx-internal-data";var r=e[t];if(!r){r=e[t]={}}return r}function M(e){var t=[];if(e){for(var r=0;r=0}function se(e){if(e.getRootNode&&e.getRootNode()instanceof window.ShadowRoot){return re().body.contains(e.getRootNode().host)}else{return re().body.contains(e)}}function D(e){return e.trim().split(/\s+/)}function le(e,t){for(var r in t){if(t.hasOwnProperty(r)){e[r]=t[r]}}return e}function E(e){try{return JSON.parse(e)}catch(e){b(e);return null}}function U(){var e="htmx:localStorageTest";try{localStorage.setItem(e,e);localStorage.removeItem(e);return true}catch(e){return false}}function B(t){try{var e=new URL(t);if(e){t=e.pathname+e.search}if(!/^\/$/.test(t)){t=t.replace(/\/+$/,"")}return t}catch(e){return t}}function t(e){return Tr(re().body,function(){return eval(e)})}function F(t){var e=Q.on("htmx:load",function(e){t(e.detail.elt)});return e}function V(){Q.logger=function(e,t,r){if(console){console.log(t,e,r)}}}function j(){Q.logger=null}function C(e,t){if(t){return e.querySelector(t)}else{return C(re(),e)}}function f(e,t){if(t){return e.querySelectorAll(t)}else{return f(re(),e)}}function _(e,t){e=p(e);if(t){setTimeout(function(){_(e);e=null},t)}else{e.parentElement.removeChild(e)}}function z(e,t,r){e=p(e);if(r){setTimeout(function(){z(e,t);e=null},r)}else{e.classList&&e.classList.add(t)}}function n(e,t,r){e=p(e);if(r){setTimeout(function(){n(e,t);e=null},r)}else{if(e.classList){e.classList.remove(t);if(e.classList.length===0){e.removeAttribute("class")}}}}function $(e,t){e=p(e);e.classList.toggle(t)}function W(e,t){e=p(e);oe(e.parentElement.children,function(e){n(e,t)});z(e,t)}function v(e,t){e=p(e);if(e.closest){return e.closest(t)}else{do{if(e==null||h(e,t)){return e}}while(e=e&&u(e));return null}}function g(e,t){return e.substring(0,t.length)===t}function G(e,t){return e.substring(e.length-t.length)===t}function J(e){var t=e.trim();if(g(t,"<")&&G(t,"/>")){return t.substring(1,t.length-2)}else{return t}}function Z(e,t){if(t.indexOf("closest ")===0){return[v(e,J(t.substr(8)))]}else if(t.indexOf("find ")===0){return[C(e,J(t.substr(5)))]}else if(t==="next"){return[e.nextElementSibling]}else if(t.indexOf("next ")===0){return[K(e,J(t.substr(5)))]}else if(t==="previous"){return[e.previousElementSibling]}else if(t.indexOf("previous ")===0){return[Y(e,J(t.substr(9)))]}else if(t==="document"){return[document]}else if(t==="window"){return[window]}else if(t==="body"){return[document.body]}else{return re().querySelectorAll(J(t))}}var K=function(e,t){var r=re().querySelectorAll(t);for(var n=0;n=0;n--){var i=r[n];if(i.compareDocumentPosition(e)===Node.DOCUMENT_POSITION_FOLLOWING){return i}}};function ue(e,t){if(t){return Z(e,t)[0]}else{return Z(re().body,e)[0]}}function p(e){if(I(e,"String")){return C(e)}else{return e}}function ve(e,t,r){if(k(t)){return{target:re().body,event:e,listener:t}}else{return{target:p(e),event:t,listener:r}}}function de(t,r,n){jr(function(){var e=ve(t,r,n);e.target.addEventListener(e.event,e.listener)});var e=k(r);return e?r:n}function ge(t,r,n){jr(function(){var e=ve(t,r,n);e.target.removeEventListener(e.event,e.listener)});return k(r)?r:n}var pe=re().createElement("output");function me(e,t){var r=ne(e,t);if(r){if(r==="this"){return[xe(e,t)]}else{var n=Z(e,r);if(n.length===0){b('The selector "'+r+'" on '+t+" returned no matches!");return[pe]}else{return n}}}}function xe(e,t){return c(e,function(e){return te(e,t)!=null})}function ye(e){var t=ne(e,"hx-target");if(t){if(t==="this"){return xe(e,"hx-target")}else{return ue(e,t)}}else{var r=ae(e);if(r.boosted){return re().body}else{return e}}}function be(e){var t=Q.config.attributesToSettle;for(var r=0;r0){o=e.substr(0,e.indexOf(":"));t=e.substr(e.indexOf(":")+1,e.length)}else{o=e}var r=re().querySelectorAll(t);if(r){oe(r,function(e){var t;var r=i.cloneNode(true);t=re().createDocumentFragment();t.appendChild(r);if(!Se(o,e)){t=r}var n={shouldSwap:true,target:e,fragment:t};if(!ce(e,"htmx:oobBeforeSwap",n))return;e=n.target;if(n["shouldSwap"]){Fe(o,e,e,t,a)}oe(a.elts,function(e){ce(e,"htmx:oobAfterSwap",n)})});i.parentNode.removeChild(i)}else{i.parentNode.removeChild(i);fe(re().body,"htmx:oobErrorNoTarget",{content:i})}return e}function Ce(e,t,r){var n=ne(e,"hx-select-oob");if(n){var i=n.split(",");for(var a=0;a0){var r=t.replace("'","\\'");var n=e.tagName.replace(":","\\:");var i=o.querySelector(n+"[id='"+r+"']");if(i&&i!==o){var a=e.cloneNode();we(e,i);s.tasks.push(function(){we(e,a)})}}})}function Oe(e){return function(){n(e,Q.config.addedClass);zt(e);Nt(e);qe(e);ce(e,"htmx:load")}}function qe(e){var t="[autofocus]";var r=h(e,t)?e:e.querySelector(t);if(r!=null){r.focus()}}function a(e,t,r,n){Te(e,r,n);while(r.childNodes.length>0){var i=r.firstChild;z(i,Q.config.addedClass);e.insertBefore(i,t);if(i.nodeType!==Node.TEXT_NODE&&i.nodeType!==Node.COMMENT_NODE){n.tasks.push(Oe(i))}}}function He(e,t){var r=0;while(r-1){var t=e.replace(H,"");var r=t.match(q);if(r){return r[2]}}}function je(e,t,r,n,i,a){i.title=Ve(n);var o=l(n);if(o){Ce(r,o,i);o=Be(r,o,a);Re(o);return Fe(e,r,t,o,i)}}function _e(e,t,r){var n=e.getResponseHeader(t);if(n.indexOf("{")===0){var i=E(n);for(var a in i){if(i.hasOwnProperty(a)){var o=i[a];if(!P(o)){o={value:o}}ce(r,a,o)}}}else{var s=n.split(",");for(var l=0;l0){var o=t[0];if(o==="]"){n--;if(n===0){if(a===null){i=i+"true"}t.shift();i+=")})";try{var s=Tr(e,function(){return Function(i)()},function(){return true});s.source=i;return s}catch(e){fe(re().body,"htmx:syntax:error",{error:e,source:i});return null}}}else if(o==="["){n++}if(Qe(o,a,r)){i+="(("+r+"."+o+") ? ("+r+"."+o+") : (window."+o+"))"}else{i=i+o}a=t.shift()}}}function y(e,t){var r="";while(e.length>0&&!t.test(e[0])){r+=e.shift()}return r}function tt(e){var t;if(e.length>0&&Ze.test(e[0])){e.shift();t=y(e,Ke).trim();e.shift()}else{t=y(e,x)}return t}var rt="input, textarea, select";function nt(e,t,r){var n=[];var i=Ye(t);do{y(i,Je);var a=i.length;var o=y(i,/[,\[\s]/);if(o!==""){if(o==="every"){var s={trigger:"every"};y(i,Je);s.pollInterval=d(y(i,/[,\[\s]/));y(i,Je);var l=et(e,i,"event");if(l){s.eventFilter=l}n.push(s)}else if(o.indexOf("sse:")===0){n.push({trigger:"sse",sseEvent:o.substr(4)})}else{var u={trigger:o};var l=et(e,i,"event");if(l){u.eventFilter=l}while(i.length>0&&i[0]!==","){y(i,Je);var f=i.shift();if(f==="changed"){u.changed=true}else if(f==="once"){u.once=true}else if(f==="consume"){u.consume=true}else if(f==="delay"&&i[0]===":"){i.shift();u.delay=d(y(i,x))}else if(f==="from"&&i[0]===":"){i.shift();if(Ze.test(i[0])){var c=tt(i)}else{var c=y(i,x);if(c==="closest"||c==="find"||c==="next"||c==="previous"){i.shift();var h=tt(i);if(h.length>0){c+=" "+h}}}u.from=c}else if(f==="target"&&i[0]===":"){i.shift();u.target=tt(i)}else if(f==="throttle"&&i[0]===":"){i.shift();u.throttle=d(y(i,x))}else if(f==="queue"&&i[0]===":"){i.shift();u.queue=y(i,x)}else if(f==="root"&&i[0]===":"){i.shift();u[f]=tt(i)}else if(f==="threshold"&&i[0]===":"){i.shift();u[f]=y(i,x)}else{fe(e,"htmx:syntax:error",{token:i.shift()})}}n.push(u)}}if(i.length===a){fe(e,"htmx:syntax:error",{token:i.shift()})}y(i,Je)}while(i[0]===","&&i.shift());if(r){r[t]=n}return n}function it(e){var t=te(e,"hx-trigger");var r=[];if(t){var n=Q.config.triggerSpecsCache;r=n&&n[t]||nt(e,t,n)}if(r.length>0){return r}else if(h(e,"form")){return[{trigger:"submit"}]}else if(h(e,'input[type="button"], input[type="submit"]')){return[{trigger:"click"}]}else if(h(e,rt)){return[{trigger:"change"}]}else{return[{trigger:"click"}]}}function at(e){ae(e).cancelled=true}function ot(e,t,r){var n=ae(e);n.timeout=setTimeout(function(){if(se(e)&&n.cancelled!==true){if(!ct(r,e,Wt("hx:poll:trigger",{triggerSpec:r,target:e}))){t(e)}ot(e,t,r)}},r.pollInterval)}function st(e){return location.hostname===e.hostname&&ee(e,"href")&&ee(e,"href").indexOf("#")!==0}function lt(t,r,e){if(t.tagName==="A"&&st(t)&&(t.target===""||t.target==="_self")||t.tagName==="FORM"){r.boosted=true;var n,i;if(t.tagName==="A"){n="get";i=ee(t,"href")}else{var a=ee(t,"method");n=a?a.toLowerCase():"get";if(n==="get"){}i=ee(t,"action")}e.forEach(function(e){ht(t,function(e,t){if(v(e,Q.config.disableSelector)){m(e);return}he(n,i,e,t)},r,e,true)})}}function ut(e,t){if(e.type==="submit"||e.type==="click"){if(t.tagName==="FORM"){return true}if(h(t,'input[type="submit"], button')&&v(t,"form")!==null){return true}if(t.tagName==="A"&&t.href&&(t.getAttribute("href")==="#"||t.getAttribute("href").indexOf("#")!==0)){return true}}return false}function ft(e,t){return ae(e).boosted&&e.tagName==="A"&&t.type==="click"&&(t.ctrlKey||t.metaKey)}function ct(e,t,r){var n=e.eventFilter;if(n){try{return n.call(t,r)!==true}catch(e){fe(re().body,"htmx:eventFilter:error",{error:e,source:n.source});return true}}return false}function ht(a,o,e,s,l){var u=ae(a);var t;if(s.from){t=Z(a,s.from)}else{t=[a]}if(s.changed){t.forEach(function(e){var t=ae(e);t.lastValue=e.value})}oe(t,function(n){var i=function(e){if(!se(a)){n.removeEventListener(s.trigger,i);return}if(ft(a,e)){return}if(l||ut(e,a)){e.preventDefault()}if(ct(s,a,e)){return}var t=ae(e);t.triggerSpec=s;if(t.handledFor==null){t.handledFor=[]}if(t.handledFor.indexOf(a)<0){t.handledFor.push(a);if(s.consume){e.stopPropagation()}if(s.target&&e.target){if(!h(e.target,s.target)){return}}if(s.once){if(u.triggeredOnce){return}else{u.triggeredOnce=true}}if(s.changed){var r=ae(n);if(r.lastValue===n.value){return}r.lastValue=n.value}if(u.delayed){clearTimeout(u.delayed)}if(u.throttle){return}if(s.throttle>0){if(!u.throttle){o(a,e);u.throttle=setTimeout(function(){u.throttle=null},s.throttle)}}else if(s.delay>0){u.delayed=setTimeout(function(){o(a,e)},s.delay)}else{ce(a,"htmx:trigger");o(a,e)}}};if(e.listenerInfos==null){e.listenerInfos=[]}e.listenerInfos.push({trigger:s.trigger,listener:i,on:n});n.addEventListener(s.trigger,i)})}var vt=false;var dt=null;function gt(){if(!dt){dt=function(){vt=true};window.addEventListener("scroll",dt);setInterval(function(){if(vt){vt=false;oe(re().querySelectorAll("[hx-trigger='revealed'],[data-hx-trigger='revealed']"),function(e){pt(e)})}},200)}}function pt(t){if(!o(t,"data-hx-revealed")&&X(t)){t.setAttribute("data-hx-revealed","true");var e=ae(t);if(e.initHash){ce(t,"revealed")}else{t.addEventListener("htmx:afterProcessNode",function(e){ce(t,"revealed")},{once:true})}}}function mt(e,t,r){var n=D(r);for(var i=0;i=0){var t=wt(n);setTimeout(function(){xt(s,r,n+1)},t)}};t.onopen=function(e){n=0};ae(s).webSocket=t;t.addEventListener("message",function(e){if(yt(s)){return}var t=e.data;R(s,function(e){t=e.transformResponse(t,null,s)});var r=T(s);var n=l(t);var i=M(n.children);for(var a=0;a0){ce(u,"htmx:validation:halted",i);return}t.send(JSON.stringify(l));if(ut(e,u)){e.preventDefault()}})}else{fe(u,"htmx:noWebSocketSourceError")}}function wt(e){var t=Q.config.wsReconnectDelay;if(typeof t==="function"){return t(e)}if(t==="full-jitter"){var r=Math.min(e,6);var n=1e3*Math.pow(2,r);return n*Math.random()}b('htmx.config.wsReconnectDelay must either be a function or the string "full-jitter"')}function St(e,t,r){var n=D(r);for(var i=0;i0){setTimeout(i,n)}else{i()}}function Ht(t,i,e){var a=false;oe(w,function(r){if(o(t,"hx-"+r)){var n=te(t,"hx-"+r);a=true;i.path=n;i.verb=r;e.forEach(function(e){Lt(t,e,i,function(e,t){if(v(e,Q.config.disableSelector)){m(e);return}he(r,n,e,t)})})}});return a}function Lt(n,e,t,r){if(e.sseEvent){Rt(n,r,e.sseEvent)}else if(e.trigger==="revealed"){gt();ht(n,r,t,e);pt(n)}else if(e.trigger==="intersect"){var i={};if(e.root){i.root=ue(n,e.root)}if(e.threshold){i.threshold=parseFloat(e.threshold)}var a=new IntersectionObserver(function(e){for(var t=0;t0){t.polling=true;ot(n,r,e)}else{ht(n,r,t,e)}}function At(e){if(!e.htmxExecuted&&Q.config.allowScriptTags&&(e.type==="text/javascript"||e.type==="module"||e.type==="")){var t=re().createElement("script");oe(e.attributes,function(e){t.setAttribute(e.name,e.value)});t.textContent=e.textContent;t.async=false;if(Q.config.inlineScriptNonce){t.nonce=Q.config.inlineScriptNonce}var r=e.parentElement;try{r.insertBefore(t,e)}catch(e){b(e)}finally{if(e.parentElement){e.parentElement.removeChild(e)}}}}function Nt(e){if(h(e,"script")){At(e)}oe(f(e,"script"),function(e){At(e)})}function It(e){var t=e.attributes;if(!t){return false}for(var r=0;r0){var o=n.shift();var s=o.match(/^\s*([a-zA-Z:\-\.]+:)(.*)/);if(a===0&&s){o.split(":");i=s[1].slice(0,-1);r[i]=s[2]}else{r[i]+=o}a+=Bt(o)}for(var l in r){Ft(e,l,r[l])}}}function jt(e){Ae(e);for(var t=0;tQ.config.historyCacheSize){i.shift()}while(i.length>0){try{localStorage.setItem("htmx-history-cache",JSON.stringify(i));break}catch(e){fe(re().body,"htmx:historyCacheError",{cause:e,cache:i});i.shift()}}}function Yt(e){if(!U()){return null}e=B(e);var t=E(localStorage.getItem("htmx-history-cache"))||[];for(var r=0;r=200&&this.status<400){ce(re().body,"htmx:historyCacheMissLoad",o);var e=l(this.response);e=e.querySelector("[hx-history-elt],[data-hx-history-elt]")||e;var t=Zt();var r=T(t);var n=Ve(this.response);if(n){var i=C("title");if(i){i.innerHTML=n}else{window.document.title=n}}Ue(t,e,r);nr(r.tasks);Jt=a;ce(re().body,"htmx:historyRestore",{path:a,cacheMiss:true,serverResponse:this.response})}else{fe(re().body,"htmx:historyCacheMissLoadError",o)}};e.send()}function ar(e){er();e=e||location.pathname+location.search;var t=Yt(e);if(t){var r=l(t.content);var n=Zt();var i=T(n);Ue(n,r,i);nr(i.tasks);document.title=t.title;setTimeout(function(){window.scrollTo(0,t.scroll)},0);Jt=e;ce(re().body,"htmx:historyRestore",{path:e,item:t})}else{if(Q.config.refreshOnHistoryMiss){window.location.reload(true)}else{ir(e)}}}function or(e){var t=me(e,"hx-indicator");if(t==null){t=[e]}oe(t,function(e){var t=ae(e);t.requestCount=(t.requestCount||0)+1;e.classList["add"].call(e.classList,Q.config.requestClass)});return t}function sr(e){var t=me(e,"hx-disabled-elt");if(t==null){t=[]}oe(t,function(e){var t=ae(e);t.requestCount=(t.requestCount||0)+1;e.setAttribute("disabled","")});return t}function lr(e,t){oe(e,function(e){var t=ae(e);t.requestCount=(t.requestCount||0)-1;if(t.requestCount===0){e.classList["remove"].call(e.classList,Q.config.requestClass)}});oe(t,function(e){var t=ae(e);t.requestCount=(t.requestCount||0)-1;if(t.requestCount===0){e.removeAttribute("disabled")}})}function ur(e,t){for(var r=0;r=0}function wr(e,t){var r=t?t:ne(e,"hx-swap");var n={swapStyle:ae(e).boosted?"innerHTML":Q.config.defaultSwapStyle,swapDelay:Q.config.defaultSwapDelay,settleDelay:Q.config.defaultSettleDelay};if(Q.config.scrollIntoViewOnBoost&&ae(e).boosted&&!br(e)){n["show"]="top"}if(r){var i=D(r);if(i.length>0){for(var a=0;a0?l.join(":"):null;n["scroll"]=u;n["scrollTarget"]=f}else if(o.indexOf("show:")===0){var c=o.substr(5);var l=c.split(":");var h=l.pop();var f=l.length>0?l.join(":"):null;n["show"]=h;n["showTarget"]=f}else if(o.indexOf("focus-scroll:")===0){var v=o.substr("focus-scroll:".length);n["focusScroll"]=v=="true"}else if(a==0){n["swapStyle"]=o}else{b("Unknown modifier in hx-swap: "+o)}}}}return n}function Sr(e){return ne(e,"hx-encoding")==="multipart/form-data"||h(e,"form")&&ee(e,"enctype")==="multipart/form-data"}function Er(t,r,n){var i=null;R(r,function(e){if(i==null){i=e.encodeParameters(t,n,r)}});if(i!=null){return i}else{if(Sr(r)){return mr(n)}else{return pr(n)}}}function T(e){return{tasks:[],elts:[e]}}function Cr(e,t){var r=e[0];var n=e[e.length-1];if(t.scroll){var i=null;if(t.scrollTarget){i=ue(r,t.scrollTarget)}if(t.scroll==="top"&&(r||i)){i=i||r;i.scrollTop=0}if(t.scroll==="bottom"&&(n||i)){i=i||n;i.scrollTop=i.scrollHeight}}if(t.show){var i=null;if(t.showTarget){var a=t.showTarget;if(t.showTarget==="window"){a="body"}i=ue(r,a)}if(t.show==="top"&&(r||i)){i=i||r;i.scrollIntoView({block:"start",behavior:Q.config.scrollBehavior})}if(t.show==="bottom"&&(n||i)){i=i||n;i.scrollIntoView({block:"end",behavior:Q.config.scrollBehavior})}}}function Rr(e,t,r,n){if(n==null){n={}}if(e==null){return n}var i=te(e,t);if(i){var a=i.trim();var o=r;if(a==="unset"){return null}if(a.indexOf("javascript:")===0){a=a.substr(11);o=true}else if(a.indexOf("js:")===0){a=a.substr(3);o=true}if(a.indexOf("{")!==0){a="{"+a+"}"}var s;if(o){s=Tr(e,function(){return Function("return ("+a+")")()},{})}else{s=E(a)}for(var l in s){if(s.hasOwnProperty(l)){if(n[l]==null){n[l]=s[l]}}}}return Rr(u(e),t,r,n)}function Tr(e,t,r){if(Q.config.allowEval){return t()}else{fe(e,"htmx:evalDisallowedError");return r}}function Or(e,t){return Rr(e,"hx-vars",true,t)}function qr(e,t){return Rr(e,"hx-vals",false,t)}function Hr(e){return le(Or(e),qr(e))}function Lr(t,r,n){if(n!==null){try{t.setRequestHeader(r,n)}catch(e){t.setRequestHeader(r,encodeURIComponent(n));t.setRequestHeader(r+"-URI-AutoEncoded","true")}}}function Ar(t){if(t.responseURL&&typeof URL!=="undefined"){try{var e=new URL(t.responseURL);return e.pathname+e.search}catch(e){fe(re().body,"htmx:badResponseUrl",{url:t.responseURL})}}}function O(e,t){return t.test(e.getAllResponseHeaders())}function Nr(e,t,r){e=e.toLowerCase();if(r){if(r instanceof Element||I(r,"String")){return he(e,t,null,null,{targetOverride:p(r),returnPromise:true})}else{return he(e,t,p(r.source),r.event,{handler:r.handler,headers:r.headers,values:r.values,targetOverride:p(r.target),swapOverride:r.swap,select:r.select,returnPromise:true})}}else{return he(e,t,null,null,{returnPromise:true})}}function Ir(e){var t=[];while(e){t.push(e);e=e.parentElement}return t}function kr(e,t,r){var n;var i;if(typeof URL==="function"){i=new URL(t,document.location.href);var a=document.location.origin;n=a===i.origin}else{i=t;n=g(t,document.location.origin)}if(Q.config.selfRequestsOnly){if(!n){return false}}return ce(e,"htmx:validateUrl",le({url:i,sameHost:n},r))}function he(t,r,n,i,a,e){var o=null;var s=null;a=a!=null?a:{};if(a.returnPromise&&typeof Promise!=="undefined"){var l=new Promise(function(e,t){o=e;s=t})}if(n==null){n=re().body}var M=a.handler||Mr;var X=a.select||null;if(!se(n)){ie(o);return l}var u=a.targetOverride||ye(n);if(u==null||u==pe){fe(n,"htmx:targetError",{target:te(n,"hx-target")});ie(s);return l}var f=ae(n);var c=f.lastButtonClicked;if(c){var h=ee(c,"formaction");if(h!=null){r=h}var v=ee(c,"formmethod");if(v!=null){if(v.toLowerCase()!=="dialog"){t=v}}}var d=ne(n,"hx-confirm");if(e===undefined){var D=function(e){return he(t,r,n,i,a,!!e)};var U={target:u,elt:n,path:r,verb:t,triggeringEvent:i,etc:a,issueRequest:D,question:d};if(ce(n,"htmx:confirm",U)===false){ie(o);return l}}var g=n;var p=ne(n,"hx-sync");var m=null;var x=false;if(p){var B=p.split(":");var F=B[0].trim();if(F==="this"){g=xe(n,"hx-sync")}else{g=ue(n,F)}p=(B[1]||"drop").trim();f=ae(g);if(p==="drop"&&f.xhr&&f.abortable!==true){ie(o);return l}else if(p==="abort"){if(f.xhr){ie(o);return l}else{x=true}}else if(p==="replace"){ce(g,"htmx:abort")}else if(p.indexOf("queue")===0){var V=p.split(" ");m=(V[1]||"last").trim()}}if(f.xhr){if(f.abortable){ce(g,"htmx:abort")}else{if(m==null){if(i){var y=ae(i);if(y&&y.triggerSpec&&y.triggerSpec.queue){m=y.triggerSpec.queue}}if(m==null){m="last"}}if(f.queuedRequests==null){f.queuedRequests=[]}if(m==="first"&&f.queuedRequests.length===0){f.queuedRequests.push(function(){he(t,r,n,i,a)})}else if(m==="all"){f.queuedRequests.push(function(){he(t,r,n,i,a)})}else if(m==="last"){f.queuedRequests=[];f.queuedRequests.push(function(){he(t,r,n,i,a)})}ie(o);return l}}var b=new XMLHttpRequest;f.xhr=b;f.abortable=x;var w=function(){f.xhr=null;f.abortable=false;if(f.queuedRequests!=null&&f.queuedRequests.length>0){var e=f.queuedRequests.shift();e()}};var j=ne(n,"hx-prompt");if(j){var S=prompt(j);if(S===null||!ce(n,"htmx:prompt",{prompt:S,target:u})){ie(o);w();return l}}if(d&&!e){if(!confirm(d)){ie(o);w();return l}}var E=xr(n,u,S);if(t!=="get"&&!Sr(n)){E["Content-Type"]="application/x-www-form-urlencoded"}if(a.headers){E=le(E,a.headers)}var _=dr(n,t);var C=_.errors;var R=_.values;if(a.values){R=le(R,a.values)}var z=Hr(n);var $=le(R,z);var T=yr($,n);if(Q.config.getCacheBusterParam&&t==="get"){T["org.htmx.cache-buster"]=ee(u,"id")||"true"}if(r==null||r===""){r=re().location.href}var O=Rr(n,"hx-request");var W=ae(n).boosted;var q=Q.config.methodsThatUseUrlParams.indexOf(t)>=0;var H={boosted:W,useUrlParams:q,parameters:T,unfilteredParameters:$,headers:E,target:u,verb:t,errors:C,withCredentials:a.credentials||O.credentials||Q.config.withCredentials,timeout:a.timeout||O.timeout||Q.config.timeout,path:r,triggeringEvent:i};if(!ce(n,"htmx:configRequest",H)){ie(o);w();return l}r=H.path;t=H.verb;E=H.headers;T=H.parameters;C=H.errors;q=H.useUrlParams;if(C&&C.length>0){ce(n,"htmx:validation:halted",H);ie(o);w();return l}var G=r.split("#");var J=G[0];var L=G[1];var A=r;if(q){A=J;var Z=Object.keys(T).length!==0;if(Z){if(A.indexOf("?")<0){A+="?"}else{A+="&"}A+=pr(T);if(L){A+="#"+L}}}if(!kr(n,A,H)){fe(n,"htmx:invalidPath",H);ie(s);return l}b.open(t.toUpperCase(),A,true);b.overrideMimeType("text/html");b.withCredentials=H.withCredentials;b.timeout=H.timeout;if(O.noHeaders){}else{for(var N in E){if(E.hasOwnProperty(N)){var K=E[N];Lr(b,N,K)}}}var I={xhr:b,target:u,requestConfig:H,etc:a,boosted:W,select:X,pathInfo:{requestPath:r,finalRequestPath:A,anchor:L}};b.onload=function(){try{var e=Ir(n);I.pathInfo.responsePath=Ar(b);M(n,I);lr(k,P);ce(n,"htmx:afterRequest",I);ce(n,"htmx:afterOnLoad",I);if(!se(n)){var t=null;while(e.length>0&&t==null){var r=e.shift();if(se(r)){t=r}}if(t){ce(t,"htmx:afterRequest",I);ce(t,"htmx:afterOnLoad",I)}}ie(o);w()}catch(e){fe(n,"htmx:onLoadError",le({error:e},I));throw e}};b.onerror=function(){lr(k,P);fe(n,"htmx:afterRequest",I);fe(n,"htmx:sendError",I);ie(s);w()};b.onabort=function(){lr(k,P);fe(n,"htmx:afterRequest",I);fe(n,"htmx:sendAbort",I);ie(s);w()};b.ontimeout=function(){lr(k,P);fe(n,"htmx:afterRequest",I);fe(n,"htmx:timeout",I);ie(s);w()};if(!ce(n,"htmx:beforeRequest",I)){ie(o);w();return l}var k=or(n);var P=sr(n);oe(["loadstart","loadend","progress","abort"],function(t){oe([b,b.upload],function(e){e.addEventListener(t,function(e){ce(n,"htmx:xhr:"+t,{lengthComputable:e.lengthComputable,loaded:e.loaded,total:e.total})})})});ce(n,"htmx:beforeSend",I);var Y=q?null:Er(b,n,T);b.send(Y);return l}function Pr(e,t){var r=t.xhr;var n=null;var i=null;if(O(r,/HX-Push:/i)){n=r.getResponseHeader("HX-Push");i="push"}else if(O(r,/HX-Push-Url:/i)){n=r.getResponseHeader("HX-Push-Url");i="push"}else if(O(r,/HX-Replace-Url:/i)){n=r.getResponseHeader("HX-Replace-Url");i="replace"}if(n){if(n==="false"){return{}}else{return{type:i,path:n}}}var a=t.pathInfo.finalRequestPath;var o=t.pathInfo.responsePath;var s=ne(e,"hx-push-url");var l=ne(e,"hx-replace-url");var u=ae(e).boosted;var f=null;var c=null;if(s){f="push";c=s}else if(l){f="replace";c=l}else if(u){f="push";c=o||a}if(c){if(c==="false"){return{}}if(c==="true"){c=o||a}if(t.pathInfo.anchor&&c.indexOf("#")===-1){c=c+"#"+t.pathInfo.anchor}return{type:f,path:c}}else{return{}}}function Mr(l,u){var f=u.xhr;var c=u.target;var e=u.etc;var t=u.requestConfig;var h=u.select;if(!ce(l,"htmx:beforeOnLoad",u))return;if(O(f,/HX-Trigger:/i)){_e(f,"HX-Trigger",l)}if(O(f,/HX-Location:/i)){er();var r=f.getResponseHeader("HX-Location");var v;if(r.indexOf("{")===0){v=E(r);r=v["path"];delete v["path"]}Nr("GET",r,v).then(function(){tr(r)});return}var n=O(f,/HX-Refresh:/i)&&"true"===f.getResponseHeader("HX-Refresh");if(O(f,/HX-Redirect:/i)){location.href=f.getResponseHeader("HX-Redirect");n&&location.reload();return}if(n){location.reload();return}if(O(f,/HX-Retarget:/i)){if(f.getResponseHeader("HX-Retarget")==="this"){u.target=l}else{u.target=ue(l,f.getResponseHeader("HX-Retarget"))}}var d=Pr(l,u);var i=f.status>=200&&f.status<400&&f.status!==204;var g=f.response;var a=f.status>=400;var p=Q.config.ignoreTitle;var o=le({shouldSwap:i,serverResponse:g,isError:a,ignoreTitle:p},u);if(!ce(c,"htmx:beforeSwap",o))return;c=o.target;g=o.serverResponse;a=o.isError;p=o.ignoreTitle;u.target=c;u.failed=a;u.successful=!a;if(o.shouldSwap){if(f.status===286){at(l)}R(l,function(e){g=e.transformResponse(g,f,l)});if(d.type){er()}var s=e.swapOverride;if(O(f,/HX-Reswap:/i)){s=f.getResponseHeader("HX-Reswap")}var v=wr(l,s);if(v.hasOwnProperty("ignoreTitle")){p=v.ignoreTitle}c.classList.add(Q.config.swappingClass);var m=null;var x=null;var y=function(){try{var e=document.activeElement;var t={};try{t={elt:e,start:e?e.selectionStart:null,end:e?e.selectionEnd:null}}catch(e){}var r;if(h){r=h}if(O(f,/HX-Reselect:/i)){r=f.getResponseHeader("HX-Reselect")}if(d.type){ce(re().body,"htmx:beforeHistoryUpdate",le({history:d},u));if(d.type==="push"){tr(d.path);ce(re().body,"htmx:pushedIntoHistory",{path:d.path})}else{rr(d.path);ce(re().body,"htmx:replacedInHistory",{path:d.path})}}var n=T(c);je(v.swapStyle,c,l,g,n,r);if(t.elt&&!se(t.elt)&&ee(t.elt,"id")){var i=document.getElementById(ee(t.elt,"id"));var a={preventScroll:v.focusScroll!==undefined?!v.focusScroll:!Q.config.defaultFocusScroll};if(i){if(t.start&&i.setSelectionRange){try{i.setSelectionRange(t.start,t.end)}catch(e){}}i.focus(a)}}c.classList.remove(Q.config.swappingClass);oe(n.elts,function(e){if(e.classList){e.classList.add(Q.config.settlingClass)}ce(e,"htmx:afterSwap",u)});if(O(f,/HX-Trigger-After-Swap:/i)){var o=l;if(!se(l)){o=re().body}_e(f,"HX-Trigger-After-Swap",o)}var s=function(){oe(n.tasks,function(e){e.call()});oe(n.elts,function(e){if(e.classList){e.classList.remove(Q.config.settlingClass)}ce(e,"htmx:afterSettle",u)});if(u.pathInfo.anchor){var e=re().getElementById(u.pathInfo.anchor);if(e){e.scrollIntoView({block:"start",behavior:"auto"})}}if(n.title&&!p){var t=C("title");if(t){t.innerHTML=n.title}else{window.document.title=n.title}}Cr(n.elts,v);if(O(f,/HX-Trigger-After-Settle:/i)){var r=l;if(!se(l)){r=re().body}_e(f,"HX-Trigger-After-Settle",r)}ie(m)};if(v.settleDelay>0){setTimeout(s,v.settleDelay)}else{s()}}catch(e){fe(l,"htmx:swapError",u);ie(x);throw e}};var b=Q.config.globalViewTransitions;if(v.hasOwnProperty("transition")){b=v.transition}if(b&&ce(l,"htmx:beforeTransition",u)&&typeof Promise!=="undefined"&&document.startViewTransition){var w=new Promise(function(e,t){m=e;x=t});var S=y;y=function(){document.startViewTransition(function(){S();return w})}}if(v.swapDelay>0){setTimeout(y,v.swapDelay)}else{y()}}if(a){fe(l,"htmx:responseError",le({error:"Response Status Error Code "+f.status+" from "+u.pathInfo.requestPath},u))}}var Xr={};function Dr(){return{init:function(e){return null},onEvent:function(e,t){return true},transformResponse:function(e,t,r){return e},isInlineSwap:function(e){return false},handleSwap:function(e,t,r,n){return false},encodeParameters:function(e,t,r){return null}}}function Ur(e,t){if(t.init){t.init(r)}Xr[e]=le(Dr(),t)}function Br(e){delete Xr[e]}function Fr(e,r,n){if(e==undefined){return r}if(r==undefined){r=[]}if(n==undefined){n=[]}var t=te(e,"hx-ext");if(t){oe(t.split(","),function(e){e=e.replace(/ /g,"");if(e.slice(0,7)=="ignore:"){n.push(e.slice(7));return}if(n.indexOf(e)<0){var t=Xr[e];if(t&&r.indexOf(t)<0){r.push(t)}}})}return Fr(u(e),r,n)}var Vr=false;re().addEventListener("DOMContentLoaded",function(){Vr=true});function jr(e){if(Vr||re().readyState==="complete"){e()}else{re().addEventListener("DOMContentLoaded",e)}}function _r(){if(Q.config.includeIndicatorStyles!==false){re().head.insertAdjacentHTML("beforeend","")}}function zr(){var e=re().querySelector('meta[name="htmx-config"]');if(e){return E(e.content)}else{return null}}function $r(){var e=zr();if(e){Q.config=le(Q.config,e)}}jr(function(){$r();_r();var e=re().body;zt(e);var t=re().querySelectorAll("[hx-trigger='restored'],[data-hx-trigger='restored']");e.addEventListener("htmx:abort",function(e){var t=e.target;var r=ae(t);if(r&&r.xhr){r.xhr.abort()}});const r=window.onpopstate?window.onpopstate.bind(window):null;window.onpopstate=function(e){if(e.state&&e.state.htmx){ar();oe(t,function(e){ce(e,"htmx:restored",{document:re(),triggerEvent:ce})})}else{if(r){r(e)}}};setTimeout(function(){ce(e,"htmx:load",{});e=null},0)});return Q}()}); \ No newline at end of file diff --git a/templates/base.html.tera b/templates/base.html.tera index e81023b..7c3b92a 100644 --- a/templates/base.html.tera +++ b/templates/base.html.tera @@ -2,11 +2,8 @@ - {# - - #} + + Index {% block head %}{% endblock head %} diff --git a/templates/user.html.tera b/templates/user.html.tera index 17af6d8..b76ca45 100644 --- a/templates/user.html.tera +++ b/templates/user.html.tera @@ -9,11 +9,17 @@ {% endif %} - {% if user.roles is object %} + {% if user.roles is defined %} {% for e in user.roles %} {{e}} {% endfor %} {% endif %} - + + loading... {% if user.emails is object %} {% for e in user.emails %} {{e.address}} {% endfor %} {% endif %} From 64eb84495e39e8e7e2ef4a8356a26b407a209577 Mon Sep 17 00:00:00 2001 From: Aran Varun Date: Sat, 11 May 2024 01:43:09 +0300 Subject: [PATCH 11/19] get user status by polling --- src/api/user_api.rs | 13 +++++++++++++ src/main.rs | 3 ++- src/models/user_model.rs | 2 +- templates/user.html.tera | 19 +++++++++++++------ 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/api/user_api.rs b/src/api/user_api.rs index d0dd545..2408799 100644 --- a/src/api/user_api.rs +++ b/src/api/user_api.rs @@ -46,6 +46,19 @@ pub fn get_user(db: &State, path: String) -> Result, Statu } } +#[get("/user//status")] +pub fn get_user_status(db: &State, path: String) -> Result { + let id = path; + if id.is_empty() { + return Err(Status::BadRequest); + }; + let user = db.get_user(&id); + match user { + Ok(user) => Ok(user.status.to_string()), + Err(_) => Err(Status::InternalServerError), + } +} + #[get("/user//email")] pub fn get_user_email(db: &State, path: String) -> Result { let id = path; diff --git a/src/main.rs b/src/main.rs index 76e4814..60a9e30 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,7 +14,7 @@ use api::{ role_api::{get_all_roles, get_role}, room_api::get_all_rooms, sdui_api::get_full_layout, - user_api::{get_all_users, get_user, get_user_email, index}, + user_api::{get_all_users, get_user, get_user_email, get_user_status, index}, }; use repository::{localdb_repo::LocalRepo, mongodb_repo::MongoRepo}; use rocket::{ @@ -43,6 +43,7 @@ fn rocket() -> _ { routes![ get_user, get_user_email, + get_user_status, get_role, get_all_users, get_all_roles, diff --git a/src/models/user_model.rs b/src/models/user_model.rs index 213169a..b612ebb 100644 --- a/src/models/user_model.rs +++ b/src/models/user_model.rs @@ -40,7 +40,7 @@ pub struct User { name: Option, roles: Vec, services: Option, - status: String, + pub status: String, pub emails: Option>, active: bool, ldap: Option, diff --git a/templates/user.html.tera b/templates/user.html.tera index b76ca45..06fd7e4 100644 --- a/templates/user.html.tera +++ b/templates/user.html.tera @@ -13,16 +13,23 @@ {% for e in user.roles %} {{e}} {% endfor %} {% endif %} - + hx-target="#email-{{user._id}}"> + + loading... {% if user.emails is object %} {% for e in user.emails %} {{e.address}} {% endfor %} {% endif %} + + + + + + {{user.status}} + - {{user.status}} From b4efb5e1cdd6c708841232f2c063d045ab1952d4 Mon Sep 17 00:00:00 2001 From: Aran Varun Date: Sat, 11 May 2024 17:17:27 +0300 Subject: [PATCH 12/19] user sessions --- src/api/user_api.rs | 42 ++++++++++++++++++++------- src/main.rs | 5 +++- src/models/mod.rs | 3 +- src/models/session_model.rs | 29 +++++++++++++++++++ src/models/user_model.rs | 2 +- src/repository/mongodb_repo.rs | 44 ++++++++++++++++++++--------- static/css/style.css | 36 +++-------------------- templates/{error => }/404.html.tera | 0 templates/base.html.tera | 15 ++++++---- templates/nav.html.tera | 11 ++++++++ templates/sess.html.tera | 35 +++++++++++++++++++++++ templates/user.html.tera | 27 ++++++++---------- templates/user_detail.html.tera | 23 +++++++++++++++ templates/users.html.tera | 3 -- 14 files changed, 194 insertions(+), 81 deletions(-) create mode 100644 src/models/session_model.rs rename templates/{error => }/404.html.tera (100%) create mode 100644 templates/nav.html.tera create mode 100644 templates/sess.html.tera create mode 100644 templates/user_detail.html.tera diff --git a/src/api/user_api.rs b/src/api/user_api.rs index 2408799..958ea66 100644 --- a/src/api/user_api.rs +++ b/src/api/user_api.rs @@ -9,7 +9,7 @@ pub fn index(db: &State) -> Template { let users = db.get_all_users_obj(); match users { Ok(users) => Template::render("index", context! { users: users }), - Err(_) => Template::render("error/404", context! { uri: "" }), + Err(_) => Template::render("404", context! { uri: "" }), } } @@ -34,25 +34,34 @@ pub fn create_user( */ #[get("/user/")] -pub fn get_user(db: &State, path: String) -> Result, Status> { +pub fn get_user(db: &State, path: &str) -> Template { let id = path; if id.is_empty() { - return Err(Status::BadRequest); + return Template::render("404", context! { uri: "" }); }; - let user_detail = db.get_user(&id); + let user_detail = db.get_user(id); match user_detail { - Ok(user) => Ok(Json(user)), - Err(_) => Err(Status::InternalServerError), + Ok(user_detail) => { + let sessions = db.get_sessions(id); + match sessions { + Ok(sessions) => Template::render( + "user_detail", + context! { user: user_detail, sessions: sessions }, + ), + Err(_) => Template::render("404", context! { uri: "" }), + } + } + Err(_) => Template::render("404", context! { uri: "" }), } } #[get("/user//status")] -pub fn get_user_status(db: &State, path: String) -> Result { +pub fn get_user_status(db: &State, path: &str) -> Result { let id = path; if id.is_empty() { return Err(Status::BadRequest); }; - let user = db.get_user(&id); + let user = db.get_user(id); match user { Ok(user) => Ok(user.status.to_string()), Err(_) => Err(Status::InternalServerError), @@ -60,12 +69,12 @@ pub fn get_user_status(db: &State, path: String) -> Result/email")] -pub fn get_user_email(db: &State, path: String) -> Result { +pub fn get_user_email(db: &State, path: &str) -> Result { let id = path; if id.is_empty() { return Err(Status::BadRequest); }; - let user = db.get_user(&id); + let user = db.get_user(id); match user { Ok(user) => Ok(if let Some(email) = user.emails.unwrap().first() { email.address.to_string() @@ -84,3 +93,16 @@ pub fn get_all_users(db: &State) -> Result>, Status> { Err(_) => Err(Status::InternalServerError), } } + +#[get("/users/role/")] +pub fn get_users_by_role(db: &State, path: &str) -> Template { + let id = path; + if id.is_empty() { + return Template::render("404", context! { uri: "" }); + }; + let users = db.get_users_by_role(id); + match users { + Ok(users) => Template::render("index", context! { users: users }), + Err(_) => Template::render("404", context! { uri: "" }), + } +} diff --git a/src/main.rs b/src/main.rs index 60a9e30..9514397 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,7 +14,9 @@ use api::{ role_api::{get_all_roles, get_role}, room_api::get_all_rooms, sdui_api::get_full_layout, - user_api::{get_all_users, get_user, get_user_email, get_user_status, index}, + user_api::{ + get_all_users, get_user, get_user_email, get_user_status, get_users_by_role, index, + }, }; use repository::{localdb_repo::LocalRepo, mongodb_repo::MongoRepo}; use rocket::{ @@ -46,6 +48,7 @@ fn rocket() -> _ { get_user_status, get_role, get_all_users, + get_users_by_role, get_all_roles, get_all_rooms, get_full_layout, diff --git a/src/models/mod.rs b/src/models/mod.rs index 3955587..62361c7 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,6 +1,7 @@ pub mod permission_model; pub mod role_model; -pub mod sdui_model; pub mod room_model; +pub mod sdui_model; +pub mod session_model; pub mod setting_model; pub mod user_model; diff --git a/src/models/session_model.rs b/src/models/session_model.rs new file mode 100644 index 0000000..2e001ea --- /dev/null +++ b/src/models/session_model.rs @@ -0,0 +1,29 @@ +use mongodb::bson::DateTime; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct Session { + //#[serde(rename = "_id")] + //id: String, + year: i16, + month: i16, + day: i16, + + #[serde(rename = "sessionId")] + session_id: Option, + #[serde(rename = "userId")] + user_id: String, + host: Option, + #[serde(rename = "searchTerm")] + search_term: Option, + #[serde(rename = "mostImportantRole")] + most_important_role: String, + #[serde(rename = "createdAt")] + created_at: Option, + #[serde(rename = "lastActivityAt")] + last_activity: Option, + #[serde(rename = "_updatedAt")] + updated_at: Option, + #[serde(rename = "_closedAt")] + closed_at: Option, +} diff --git a/src/models/user_model.rs b/src/models/user_model.rs index b612ebb..f0c0ca3 100644 --- a/src/models/user_model.rs +++ b/src/models/user_model.rs @@ -35,7 +35,7 @@ pub struct Email { #[derive(Debug, Serialize, Deserialize)] pub struct User { #[serde(rename = "_id")] - id: String, + pub id: String, username: String, name: Option, roles: Vec, diff --git a/src/repository/mongodb_repo.rs b/src/repository/mongodb_repo.rs index eb2f461..dca246c 100644 --- a/src/repository/mongodb_repo.rs +++ b/src/repository/mongodb_repo.rs @@ -4,7 +4,7 @@ use dotenv::dotenv; use crate::models::{ permission_model::Permission, role_model::Role, room_model::Room, sdui_model::Sdui, - user_model::User, + session_model::Session, user_model::User, }; // use chrono::{TimeZone, Utc}; use mongodb::{ @@ -19,6 +19,7 @@ pub struct MongoRepo { usercol: Collection, rolecol: Collection, permcol: Collection, + sesscol: Collection, roomcol: Collection, sduicol: Collection, acolraw: Collection, @@ -29,23 +30,25 @@ impl MongoRepo { dotenv().ok(); let uri = match env::var("MONGOURI") { Ok(v) => v.to_string(), - Err(_) => format!("Error loading env variable"), + Err(_) => "Error loading env variable".to_owned(), }; let cn = match env::var("COLLECTION") { Ok(v) => v.to_string(), - Err(_) => format!("Error loading env variable"), + Err(_) => "Error loading env variable".to_owned(), }; let client = Client::with_uri_str(uri).unwrap(); let db = client.database("rocketchat"); let usercol: Collection = db.collection("users"); let rolecol: Collection = db.collection("rocketchat_roles"); let permcol: Collection = db.collection("rocketchat_permissions"); + let sesscol: Collection = db.collection("rocketchat_sessions"); let roomcol: Collection = db.collection("rocketchat_room"); let sduicol: Collection = db.collection("rocketchat_settings"); let acolraw: Collection = db.collection(&cn); MongoRepo { usercol, permcol, + sesscol, rolecol, roomcol, sduicol, @@ -70,17 +73,26 @@ impl MongoRepo { } */ - pub fn get_user(&self, id: &String) -> Result { + pub fn get_user(&self, id: &str) -> Result { // let obj_id = ObjectId::parse_str(id).unwrap(); let filter = doc! {"_id": id}; let user_detail = self .usercol .find_one(filter, None) - .ok() .expect("Error getting user's detail"); Ok(user_detail.unwrap()) } + pub fn get_users_by_role(&self, id: &str) -> Result, Error> { + let filter = doc! {"roles": { "$in": [id] } }; + let cursors = self + .usercol + .find(filter, None) + .expect("Error getting list of users"); + let users = cursors.map(|doc| doc.unwrap()).collect(); + Ok(users) + } + pub fn get_all_users_obj(&self) -> Result, Error> { /* let trashold = Utc.ymd(2024, 1, 1).and_hms_opt(0, 0, 0); @@ -99,7 +111,6 @@ impl MongoRepo { let cursors = self .usercol .find(None, None) - .ok() .expect("Error getting list of users"); let users = cursors.map(|doc| doc.unwrap()).collect(); Ok(users) @@ -119,7 +130,6 @@ impl MongoRepo { let cursors = self .roomcol .find(filter, find_options) - .ok() .expect("Error getting list of rooms"); let rooms = cursors.map(|doc| doc.unwrap()).collect(); Ok(rooms) @@ -130,28 +140,38 @@ impl MongoRepo { let cursors = self .acolraw .find(None, None) - .ok() .expect("Error getting list of docs"); let docs = cursors.map(|doc| doc.unwrap()).collect(); Ok(docs) } + pub fn get_sessions(&self, id: &str) -> Result, Error> { + let filter = doc! {"userId": id }; + let find_options = FindOptions::builder() + .sort(doc! { "year": -1, "month": -1, "day": -1 }) + .build(); + let cursors = self + .sesscol + .find(filter, find_options) + .expect("Error getting list of sessions"); + let sessions = cursors.map(|doc| doc.unwrap()).collect(); + Ok(sessions) + } + pub fn get_all_roles(&self) -> Result, Error> { let cursors = self .rolecol .find(None, None) - .ok() .expect("Error getting list of roles"); let roles = cursors.map(|doc| doc.unwrap()).collect(); Ok(roles) } - pub fn get_role(&self, id: &String) -> Result { + pub fn get_role(&self, id: &str) -> Result { let filter = doc! {"_id": id}; let role = self .rolecol .find_one(filter, None) - .ok() .expect("Error getting role's detail"); Ok(role.unwrap()) } @@ -161,7 +181,6 @@ impl MongoRepo { let cursors = self .sduicol .find(filter, None) - .ok() .expect("Error getting list of layout elements"); let layout = cursors.map(|doc| doc.unwrap()).collect(); Ok(layout) @@ -173,7 +192,6 @@ impl MongoRepo { let cursors = self .permcol .find(filter, None) - .ok() .expect("Error getting list of permissions"); let permissions = cursors.map(|doc| doc.unwrap()).collect(); Ok(permissions) diff --git a/static/css/style.css b/static/css/style.css index 1a1ce0e..d7b7a01 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -1,6 +1,6 @@ * { - margin: 0; - padding: 0; + margin: 10; + padding: 10; box-sizing: border-box; } @@ -32,35 +32,7 @@ main { padding: 1rem; } -.counters { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); - grid-gap: 1rem; -} - -.counter { - border: 1px solid var(--primary-color); - border-radius: 0.25rem; +table { + width: 50%; padding: 1rem; - margin-bottom: 1rem; - width: 100%; - - display: flex; - flex-direction: row; - justify-content: space-between; } - -.counter button { - border: none; - background-color: var(--primary-color); - color: var(--background-color); - padding: 0.5rem 1rem; - border-radius: 0.25rem; - font-size: 1rem; - cursor: pointer; -} - -.counter-count { - line-height: 1; - font-weight: bold; -} \ No newline at end of file diff --git a/templates/error/404.html.tera b/templates/404.html.tera similarity index 100% rename from templates/error/404.html.tera rename to templates/404.html.tera diff --git a/templates/base.html.tera b/templates/base.html.tera index 7c3b92a..3eb5487 100644 --- a/templates/base.html.tera +++ b/templates/base.html.tera @@ -3,14 +3,19 @@ - + Index {% block head %}{% endblock head %} - + +
    +
    - {% block content %} - {% endblock content%} + {% block content %} + {% endblock content%}
    - +
    + diff --git a/templates/nav.html.tera b/templates/nav.html.tera new file mode 100644 index 0000000..85b7354 --- /dev/null +++ b/templates/nav.html.tera @@ -0,0 +1,11 @@ + + diff --git a/templates/sess.html.tera b/templates/sess.html.tera new file mode 100644 index 0000000..156da2e --- /dev/null +++ b/templates/sess.html.tera @@ -0,0 +1,35 @@ + + + + + {#session._id#} + {% if sess.host is string %}{{sess.host}} + {% else %}--- + {% endif %} + {% if sess.mostImportantRole is string %} {{sess.mostImportantRole}} + {% else %}--- + {% endif %} + + + + {{sess.day}}-{{sess.month}}-{{sess.year}} + {# + {% if sess.createdAt is defined %} + {{sess.createdAt}} + {% endif %} + {% if sess._updatedAt is defined %} + {{sess._updatedAt}} + {% endif %} + {% if sess.lastActivityAt is defined %} + {{sess.lastActivityAt}} + {% endif %} + #} + + + + {% if sess.searchTerm is string %} {{sess.searchTerm}} + {% else %}--- + {% endif %} + + + diff --git a/templates/user.html.tera b/templates/user.html.tera index 06fd7e4..23dd54b 100644 --- a/templates/user.html.tera +++ b/templates/user.html.tera @@ -1,29 +1,26 @@ - {{ user._id }} - {{ user.username }} - + + + {{ user.username }} {% if user.name is defined %} - {{user.name}} + + ({{user.name}}) + {% endif %} + {% if user.roles is defined %} - {% for e in user.roles %} {{e}} {% endfor %} + {% for r in user.roles %} + {{r}} + {% endfor %} {% endif %} - - - loading... - {% if user.emails is object %} - {% for e in user.emails %} {{e.address}} {% endfor %} - {% endif %} - - diff --git a/templates/user_detail.html.tera b/templates/user_detail.html.tera new file mode 100644 index 0000000..ad19630 --- /dev/null +++ b/templates/user_detail.html.tera @@ -0,0 +1,23 @@ +{% extends "base" %} + + +{% block content %} +

    User {{ user.username }}

    +
    +

    Sessions

    + + + + + + + + + + {% for sess in sessions %} + {% include "sess" %} + {% endfor %} + +
    ID, Host, roleDatesSearchTerm
    +
    +{% endblock content %} diff --git a/templates/users.html.tera b/templates/users.html.tera index 2703cfb..927606b 100644 --- a/templates/users.html.tera +++ b/templates/users.html.tera @@ -4,11 +4,8 @@ - - - From ecbf480c906f5e61e66fe6ae2aa098e2cb0e178c Mon Sep 17 00:00:00 2001 From: Aran Varun Date: Sat, 11 May 2024 21:49:53 +0300 Subject: [PATCH 13/19] 1 style --- .gitignore | 2 + static/css/style.css | 619 ++++++++++++++++++++++++++++++++++++-- templates/base.html.tera | 2 + templates/users.html.tera | 2 +- 4 files changed, 599 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index a1d0104..0bc43d7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ /target .env /results +/node_modules +/static/src diff --git a/static/css/style.css b/static/css/style.css index d7b7a01..8e73c9e 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -1,38 +1,607 @@ -* { - margin: 10; - padding: 10; - box-sizing: border-box; +/* +! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com +*/ + +/* +1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) +2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) +*/ + +*, +::before, +::after { + box-sizing: border-box; + /* 1 */ + border-width: 0; + /* 2 */ + border-style: solid; + /* 2 */ + border-color: #e5e7eb; + /* 2 */ } -:root { - --background-color: #f5f5f5; - --primary-color: #1a73e8; - --text-color: #202124; +::before, +::after { + --tw-content: ''; } -@media screen and (prefers-color-scheme: dark) { - :root { - --background-color: #202124; - --primary-color: #1a73e8; - --text-color: #f5f5f5; - } +/* +1. Use a consistent sensible line-height in all browsers. +2. Prevent adjustments of font size after orientation changes in iOS. +3. Use a more readable tab size. +4. Use the user's configured `sans` font-family by default. +5. Use the user's configured `sans` font-feature-settings by default. +6. Use the user's configured `sans` font-variation-settings by default. +7. Disable tap highlights on iOS +*/ + +html, +:host { + line-height: 1.5; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ + -moz-tab-size: 4; + /* 3 */ + -o-tab-size: 4; + tab-size: 4; + /* 3 */ + font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + /* 4 */ + font-feature-settings: normal; + /* 5 */ + font-variation-settings: normal; + /* 6 */ + -webkit-tap-highlight-color: transparent; + /* 7 */ } +/* +1. Remove the margin in all browsers. +2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. +*/ + body { - font-family: 'Roboto', sans-serif; - background-color: var(--background-color); - color: var(--text-color); + margin: 0; + /* 1 */ + line-height: inherit; + /* 2 */ +} + +/* +1. Add the correct height in Firefox. +2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) +3. Ensure horizontal rules are visible by default. +*/ + +hr { + height: 0; + /* 1 */ + color: inherit; + /* 2 */ + border-top-width: 1px; + /* 3 */ +} + +/* +Add the correct text decoration in Chrome, Edge, and Safari. +*/ + +abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} + +/* +Remove the default font size and weight for headings. +*/ + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +/* +Reset links to optimize for opt-in styling instead of opt-out. +*/ + +a { + color: inherit; + text-decoration: inherit; } -main { - width: 100%; - max-width: - 75rem; - margin: 0 auto; - padding: 1rem; +/* +Add the correct font weight in Edge and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/* +1. Use the user's configured `mono` font-family by default. +2. Use the user's configured `mono` font-feature-settings by default. +3. Use the user's configured `mono` font-variation-settings by default. +4. Correct the odd `em` font sizing in all browsers. +*/ + +code, +kbd, +samp, +pre { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + /* 1 */ + font-feature-settings: normal; + /* 2 */ + font-variation-settings: normal; + /* 3 */ + font-size: 1em; + /* 4 */ +} + +/* +Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/* +Prevent `sub` and `sup` elements from affecting the line height in all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; } +sup { + top: -0.5em; +} + +/* +1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) +2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) +3. Remove gaps between table borders by default. +*/ + table { - width: 50%; - padding: 1rem; + text-indent: 0; + /* 1 */ + border-color: inherit; + /* 2 */ + border-collapse: collapse; + /* 3 */ +} + +/* +1. Change the font styles in all browsers. +2. Remove the margin in Firefox and Safari. +3. Remove default padding in all browsers. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + /* 1 */ + font-feature-settings: inherit; + /* 1 */ + font-variation-settings: inherit; + /* 1 */ + font-size: 100%; + /* 1 */ + font-weight: inherit; + /* 1 */ + line-height: inherit; + /* 1 */ + letter-spacing: inherit; + /* 1 */ + color: inherit; + /* 1 */ + margin: 0; + /* 2 */ + padding: 0; + /* 3 */ +} + +/* +Remove the inheritance of text transform in Edge and Firefox. +*/ + +button, +select { + text-transform: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Remove default button styles. +*/ + +button, +input:where([type='button']), +input:where([type='reset']), +input:where([type='submit']) { + -webkit-appearance: button; + /* 1 */ + background-color: transparent; + /* 2 */ + background-image: none; + /* 2 */ +} + +/* +Use the modern Firefox focus style for all focusable elements. +*/ + +:-moz-focusring { + outline: auto; +} + +/* +Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) +*/ + +:-moz-ui-invalid { + box-shadow: none; +} + +/* +Add the correct vertical alignment in Chrome and Firefox. +*/ + +progress { + vertical-align: baseline; +} + +/* +Correct the cursor style of increment and decrement buttons in Safari. +*/ + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/* +1. Correct the odd appearance in Chrome and Safari. +2. Correct the outline style in Safari. +*/ + +[type='search'] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ +} + +/* +Remove the inner padding in Chrome and Safari on macOS. +*/ + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Change font properties to `inherit` in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ +} + +/* +Add the correct display in Chrome and Safari. +*/ + +summary { + display: list-item; } + +/* +Removes the default spacing and border for appropriate elements. +*/ + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +figure, +p, +pre { + margin: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +legend { + padding: 0; +} + +ol, +ul, +menu { + list-style: none; + margin: 0; + padding: 0; +} + +/* +Reset default styling for dialogs. +*/ + +dialog { + padding: 0; +} + +/* +Prevent resizing textareas horizontally by default. +*/ + +textarea { + resize: vertical; +} + +/* +1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) +2. Set the default placeholder color to the user's configured gray 400 color. +*/ + +input::-moz-placeholder, textarea::-moz-placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +input::placeholder, +textarea::placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +/* +Set the default cursor for buttons. +*/ + +button, +[role="button"] { + cursor: pointer; +} + +/* +Make sure disabled buttons don't get the pointer cursor. +*/ + +:disabled { + cursor: default; +} + +/* +1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) +2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) + This can trigger a poorly considered lint error in some tools but is included by design. +*/ + +img, +svg, +video, +canvas, +audio, +iframe, +embed, +object { + display: block; + /* 1 */ + vertical-align: middle; + /* 2 */ +} + +/* +Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) +*/ + +img, +video { + max-width: 100%; + height: auto; +} + +/* Make elements with the HTML hidden attribute stay hidden by default */ + +[hidden] { + display: none; +} + +*, ::before, ::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +::backdrop { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +.visible { + visibility: visible; +} + +.collapse { + visibility: collapse; +} + +.relative { + position: relative; +} + +.block { + display: block; +} + +.table { + display: table; +} + +.contents { + display: contents; +} + +.hidden { + display: none; +} + +.border-collapse { + border-collapse: collapse; +} + +.transform { + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.resize { + resize: both; +} + +.border { + border-width: 1px; +} + +.underline { + text-decoration-line: underline; +} + +.outline { + outline-style: solid; +} \ No newline at end of file diff --git a/templates/base.html.tera b/templates/base.html.tera index 3eb5487..9fe374a 100644 --- a/templates/base.html.tera +++ b/templates/base.html.tera @@ -2,6 +2,8 @@ + + Index diff --git a/templates/users.html.tera b/templates/users.html.tera index 927606b..74ccf6c 100644 --- a/templates/users.html.tera +++ b/templates/users.html.tera @@ -1,5 +1,5 @@ -

    Users

    +

    Users

    ID UsernameName, Fields RolesEmails Status
    From 07e50acf4145bdb9e567cb8b83e4f0d304eab5db Mon Sep 17 00:00:00 2001 From: Aran Varun Date: Sat, 11 May 2024 23:40:48 +0300 Subject: [PATCH 14/19] style 1 --- src/api/role_api.rs | 2 +- src/repository/localdb_repo.rs | 2 +- src/repository/mongodb_repo.rs | 2 +- static/css/style.css | 617 ++------------------------------- 4 files changed, 24 insertions(+), 599 deletions(-) diff --git a/src/api/role_api.rs b/src/api/role_api.rs index 41b3239..231d1cb 100644 --- a/src/api/role_api.rs +++ b/src/api/role_api.rs @@ -7,7 +7,7 @@ pub fn get_role(db: &State, path: String) -> Result, Statu if id.is_empty() { return Err(Status::BadRequest); }; - let role = db.get_role(&id); + let role = db.get_role_obj(&id); match role { Ok(role) => Ok(Json(role)), Err(_) => Err(Status::InternalServerError), diff --git a/src/repository/localdb_repo.rs b/src/repository/localdb_repo.rs index 4bf96ac..c5e0e5a 100644 --- a/src/repository/localdb_repo.rs +++ b/src/repository/localdb_repo.rs @@ -19,7 +19,7 @@ impl LocalRepo { dotenv().ok(); let uri = match env::var("LOCALURI") { Ok(v) => v.to_string(), - Err(_) => format!("Error loading env variable"), + Err(_) => "Error loading env variable".to_owned(), }; let client = Client::with_uri_str(uri).unwrap(); let db = client.database("mkbadmin"); diff --git a/src/repository/mongodb_repo.rs b/src/repository/mongodb_repo.rs index dca246c..8e96f00 100644 --- a/src/repository/mongodb_repo.rs +++ b/src/repository/mongodb_repo.rs @@ -167,7 +167,7 @@ impl MongoRepo { Ok(roles) } - pub fn get_role(&self, id: &str) -> Result { + pub fn get_role_obj(&self, id: &str) -> Result { let filter = doc! {"_id": id}; let role = self .rolecol diff --git a/static/css/style.css b/static/css/style.css index 8e73c9e..bfe778d 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -1,607 +1,32 @@ -/* -! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com -*/ - -/* -1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) -2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) -*/ - -*, -::before, -::after { +* { + margin: 10; + padding: 10; box-sizing: border-box; - /* 1 */ - border-width: 0; - /* 2 */ - border-style: solid; - /* 2 */ - border-color: #e5e7eb; - /* 2 */ } -::before, -::after { - --tw-content: ''; +:root { + --background-color: #f5f5f5; + --primary-color: #1a73e8; + --text-color: #202124; } -/* -1. Use a consistent sensible line-height in all browsers. -2. Prevent adjustments of font size after orientation changes in iOS. -3. Use a more readable tab size. -4. Use the user's configured `sans` font-family by default. -5. Use the user's configured `sans` font-feature-settings by default. -6. Use the user's configured `sans` font-variation-settings by default. -7. Disable tap highlights on iOS -*/ - -html, -:host { - line-height: 1.5; - /* 1 */ - -webkit-text-size-adjust: 100%; - /* 2 */ - -moz-tab-size: 4; - /* 3 */ - -o-tab-size: 4; - tab-size: 4; - /* 3 */ - font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - /* 4 */ - font-feature-settings: normal; - /* 5 */ - font-variation-settings: normal; - /* 6 */ - -webkit-tap-highlight-color: transparent; - /* 7 */ +@media screen and (prefers-color-scheme: dark) { + :root { + --background-color: #202124; + --primary-color: #1a73e8; + --text-color: #f5f5f5; + } } -/* -1. Remove the margin in all browsers. -2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. -*/ - body { - margin: 0; - /* 1 */ - line-height: inherit; - /* 2 */ -} - -/* -1. Add the correct height in Firefox. -2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) -3. Ensure horizontal rules are visible by default. -*/ - -hr { - height: 0; - /* 1 */ - color: inherit; - /* 2 */ - border-top-width: 1px; - /* 3 */ -} - -/* -Add the correct text decoration in Chrome, Edge, and Safari. -*/ - -abbr:where([title]) { - -webkit-text-decoration: underline dotted; - text-decoration: underline dotted; -} - -/* -Remove the default font size and weight for headings. -*/ - -h1, -h2, -h3, -h4, -h5, -h6 { - font-size: inherit; - font-weight: inherit; -} - -/* -Reset links to optimize for opt-in styling instead of opt-out. -*/ - -a { - color: inherit; - text-decoration: inherit; -} - -/* -Add the correct font weight in Edge and Safari. -*/ - -b, -strong { - font-weight: bolder; -} - -/* -1. Use the user's configured `mono` font-family by default. -2. Use the user's configured `mono` font-feature-settings by default. -3. Use the user's configured `mono` font-variation-settings by default. -4. Correct the odd `em` font sizing in all browsers. -*/ - -code, -kbd, -samp, -pre { - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - /* 1 */ - font-feature-settings: normal; - /* 2 */ - font-variation-settings: normal; - /* 3 */ - font-size: 1em; - /* 4 */ -} - -/* -Add the correct font size in all browsers. -*/ - -small { - font-size: 80%; -} - -/* -Prevent `sub` and `sup` elements from affecting the line height in all browsers. -*/ - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sub { - bottom: -0.25em; -} - -sup { - top: -0.5em; -} - -/* -1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) -2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) -3. Remove gaps between table borders by default. -*/ - -table { - text-indent: 0; - /* 1 */ - border-color: inherit; - /* 2 */ - border-collapse: collapse; - /* 3 */ -} - -/* -1. Change the font styles in all browsers. -2. Remove the margin in Firefox and Safari. -3. Remove default padding in all browsers. -*/ - -button, -input, -optgroup, -select, -textarea { - font-family: inherit; - /* 1 */ - font-feature-settings: inherit; - /* 1 */ - font-variation-settings: inherit; - /* 1 */ - font-size: 100%; - /* 1 */ - font-weight: inherit; - /* 1 */ - line-height: inherit; - /* 1 */ - letter-spacing: inherit; - /* 1 */ - color: inherit; - /* 1 */ - margin: 0; - /* 2 */ - padding: 0; - /* 3 */ -} - -/* -Remove the inheritance of text transform in Edge and Firefox. -*/ - -button, -select { - text-transform: none; -} - -/* -1. Correct the inability to style clickable types in iOS and Safari. -2. Remove default button styles. -*/ - -button, -input:where([type='button']), -input:where([type='reset']), -input:where([type='submit']) { - -webkit-appearance: button; - /* 1 */ - background-color: transparent; - /* 2 */ - background-image: none; - /* 2 */ -} - -/* -Use the modern Firefox focus style for all focusable elements. -*/ - -:-moz-focusring { - outline: auto; -} - -/* -Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) -*/ - -:-moz-ui-invalid { - box-shadow: none; -} - -/* -Add the correct vertical alignment in Chrome and Firefox. -*/ - -progress { - vertical-align: baseline; -} - -/* -Correct the cursor style of increment and decrement buttons in Safari. -*/ - -::-webkit-inner-spin-button, -::-webkit-outer-spin-button { - height: auto; -} - -/* -1. Correct the odd appearance in Chrome and Safari. -2. Correct the outline style in Safari. -*/ - -[type='search'] { - -webkit-appearance: textfield; - /* 1 */ - outline-offset: -2px; - /* 2 */ -} - -/* -Remove the inner padding in Chrome and Safari on macOS. -*/ - -::-webkit-search-decoration { - -webkit-appearance: none; -} - -/* -1. Correct the inability to style clickable types in iOS and Safari. -2. Change font properties to `inherit` in Safari. -*/ - -::-webkit-file-upload-button { - -webkit-appearance: button; - /* 1 */ - font: inherit; - /* 2 */ -} - -/* -Add the correct display in Chrome and Safari. -*/ - -summary { - display: list-item; -} - -/* -Removes the default spacing and border for appropriate elements. -*/ - -blockquote, -dl, -dd, -h1, -h2, -h3, -h4, -h5, -h6, -hr, -figure, -p, -pre { - margin: 0; -} - -fieldset { - margin: 0; - padding: 0; -} - -legend { - padding: 0; -} - -ol, -ul, -menu { - list-style: none; - margin: 0; - padding: 0; -} - -/* -Reset default styling for dialogs. -*/ - -dialog { - padding: 0; -} - -/* -Prevent resizing textareas horizontally by default. -*/ - -textarea { - resize: vertical; -} - -/* -1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) -2. Set the default placeholder color to the user's configured gray 400 color. -*/ - -input::-moz-placeholder, textarea::-moz-placeholder { - opacity: 1; - /* 1 */ - color: #9ca3af; - /* 2 */ -} - -input::placeholder, -textarea::placeholder { - opacity: 1; - /* 1 */ - color: #9ca3af; - /* 2 */ -} - -/* -Set the default cursor for buttons. -*/ - -button, -[role="button"] { - cursor: pointer; -} - -/* -Make sure disabled buttons don't get the pointer cursor. -*/ - -:disabled { - cursor: default; -} - -/* -1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) -2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) - This can trigger a poorly considered lint error in some tools but is included by design. -*/ - -img, -svg, -video, -canvas, -audio, -iframe, -embed, -object { - display: block; - /* 1 */ - vertical-align: middle; - /* 2 */ -} - -/* -Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) -*/ - -img, -video { - max-width: 100%; - height: auto; -} - -/* Make elements with the HTML hidden attribute stay hidden by default */ - -[hidden] { - display: none; -} - -*, ::before, ::after { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - --tw-contain-size: ; - --tw-contain-layout: ; - --tw-contain-paint: ; - --tw-contain-style: ; -} - -::backdrop { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - --tw-contain-size: ; - --tw-contain-layout: ; - --tw-contain-paint: ; - --tw-contain-style: ; -} - -.visible { - visibility: visible; -} - -.collapse { - visibility: collapse; -} - -.relative { - position: relative; -} - -.block { - display: block; -} - -.table { - display: table; -} - -.contents { - display: contents; -} - -.hidden { - display: none; -} - -.border-collapse { - border-collapse: collapse; -} - -.transform { - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.resize { - resize: both; -} - -.border { - border-width: 1px; -} - -.underline { - text-decoration-line: underline; + font-family: 'Roboto', sans-serif; + background-color: var(--background-color); + color: var(--text-color); } -.outline { - outline-style: solid; +main { + width: 100%; + max-width: 75rem; + margin: 0 auto; + padding: 1rem; } \ No newline at end of file From 496c8dc5758b8302ca4a333db87b32c71c6a4a79 Mon Sep 17 00:00:00 2001 From: Aran Varun Date: Mon, 13 May 2024 19:55:19 +0300 Subject: [PATCH 15/19] register service --- src/api/mod.rs | 5 +++-- src/api/service_api.rs | 11 +++++++++ src/main.rs | 9 +++++--- src/models/setting_model.rs | 10 +++++++++ src/repository/localdb_repo.rs | 41 +++++++++++++++++++++++++++++----- templates/base.html.tera | 2 +- templates/nav.html.tera | 2 +- templates/users.html.tera | 2 +- 8 files changed, 68 insertions(+), 14 deletions(-) create mode 100644 src/api/service_api.rs diff --git a/src/api/mod.rs b/src/api/mod.rs index def917a..3f71330 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,6 +1,7 @@ pub mod permission_api; -pub mod role_api; -pub mod sdui_api; pub mod rawdoc_api; +pub mod role_api; pub mod room_api; +pub mod sdui_api; +pub mod service_api; pub mod user_api; diff --git a/src/api/service_api.rs b/src/api/service_api.rs new file mode 100644 index 0000000..82271b8 --- /dev/null +++ b/src/api/service_api.rs @@ -0,0 +1,11 @@ +use crate::{models::setting_model::InternalService, repository::localdb_repo::LocalRepo}; +use rocket::{http::Status, serde::json::Json, State}; + +#[get("/services")] +pub fn get_all_services(db: &State) -> Result>, Status> { + let services = db.get_all_services(); + match services { + Ok(services) => Ok(Json(services)), + Err(_) => Err(Status::InternalServerError), + } +} diff --git a/src/main.rs b/src/main.rs index 9514397..33f3d8a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,7 @@ use api::{ role_api::{get_all_roles, get_role}, room_api::get_all_rooms, sdui_api::get_full_layout, + service_api::get_all_services, user_api::{ get_all_users, get_user, get_user_email, get_user_status, get_users_by_role, index, }, @@ -35,15 +36,17 @@ fn hello() -> Result, Status> { #[launch] fn rocket() -> _ { - let _ldb = LocalRepo::init(); - let mdb = MongoRepo::init(); + let ldb = LocalRepo::init(); + let db = MongoRepo::init(); rocket::build() - .manage(mdb) + .manage(ldb) + .manage(db) .mount("/", FileServer::from(relative!("static"))) .mount( "/", routes![ get_user, + get_all_services, get_user_email, get_user_status, get_role, diff --git a/src/models/setting_model.rs b/src/models/setting_model.rs index 3a49cfb..0620339 100644 --- a/src/models/setting_model.rs +++ b/src/models/setting_model.rs @@ -9,3 +9,13 @@ pub struct Setting { token: String, active: bool, } + +#[derive(Debug, Serialize, Deserialize)] +pub struct InternalService { + #[serde(rename = "_id", skip_serializing_if = "Option::is_none")] + pub id: Option, + pub name: String, + pub uri: String, + pub roles: Vec, + pub active: bool, +} diff --git a/src/repository/localdb_repo.rs b/src/repository/localdb_repo.rs index c5e0e5a..bbfc858 100644 --- a/src/repository/localdb_repo.rs +++ b/src/repository/localdb_repo.rs @@ -2,16 +2,16 @@ use std::env; extern crate dotenv; use dotenv::dotenv; -use crate::models::setting_model::Setting; +use crate::models::setting_model::InternalService; use mongodb::{ - // bson::extjson::de::Error, + bson::extjson::de::Error, // results::InsertOneResult, sync::{Client, Collection}, }; -#[allow(dead_code)] pub struct LocalRepo { - setcol: Collection, + // setcol: Collection, + servcol: Collection, } impl LocalRepo { @@ -23,8 +23,12 @@ impl LocalRepo { }; let client = Client::with_uri_str(uri).unwrap(); let db = client.database("mkbadmin"); - let setcol: Collection = db.collection("settings"); - LocalRepo { setcol } + // let setcol: Collection = db.collection("settings"); + let servcol: Collection = db.collection("services"); + LocalRepo { + // setcol, + servcol, + } } /* @@ -54,4 +58,29 @@ impl LocalRepo { Ok(users) } */ + + // pub fn create_service(&self) -> Result { + // let new_doc = InternalService { + // id: None, + // name: "CorpPortal1".to_string(), + // uri: "https://mcb.ru/".to_string(), + // roles: vec!["user".to_string(), "admin".to_string()], + // active: true, + // }; + // let service = self + // .servcol + // .insert_one(new_doc, None) + // .expect("Error creating service"); + // Ok(service) + // } + + pub fn get_all_services(&self) -> Result, Error> { + // let _ = self.create_service(); + let cursors = self + .servcol + .find(None, None) + .expect("Error getting list of services"); + let services = cursors.map(|doc| doc.unwrap()).collect(); + Ok(services) + } } diff --git a/templates/base.html.tera b/templates/base.html.tera index 9fe374a..e1178f7 100644 --- a/templates/base.html.tera +++ b/templates/base.html.tera @@ -1,4 +1,3 @@ - @@ -9,6 +8,7 @@ Index {% block head %}{% endblock head %} +
    From cadd3c5dc6505daaab6417c2bbf7c5306f9b26a4 Mon Sep 17 00:00:00 2001 From: Aran Varun Date: Mon, 13 May 2024 21:30:10 +0300 Subject: [PATCH 16/19] show registered service by role --- src/api/user_api.rs | 29 ++++++++++++++++++++++++----- src/repository/localdb_repo.rs | 11 +++++++++++ templates/nav.html.tera | 9 +++++---- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/api/user_api.rs b/src/api/user_api.rs index 958ea66..48c04d7 100644 --- a/src/api/user_api.rs +++ b/src/api/user_api.rs @@ -1,14 +1,25 @@ -use crate::{models::user_model::User, repository::mongodb_repo::MongoRepo}; +use crate::{ + models::user_model::User, + repository::{localdb_repo::LocalRepo, mongodb_repo::MongoRepo}, +}; use rocket::{http::Status, serde::json::Json, State}; // use mongodb::bson::Document; // use mongodb::results::InsertOneResult; use rocket_dyn_templates::{context, Template}; #[get("/")] -pub fn index(db: &State) -> Template { +pub fn index(db: &State, ldb: &State) -> Template { let users = db.get_all_users_obj(); match users { - Ok(users) => Template::render("index", context! { users: users }), + Ok(users) => { + let services = ldb.get_all_services(); + match services { + Ok(services) => { + Template::render("index", context! { users: users, services: services }) + } + Err(_) => Template::render("404", context! { uri: "" }), + } + } Err(_) => Template::render("404", context! { uri: "" }), } } @@ -95,14 +106,22 @@ pub fn get_all_users(db: &State) -> Result>, Status> { } #[get("/users/role/")] -pub fn get_users_by_role(db: &State, path: &str) -> Template { +pub fn get_users_by_role(db: &State, ldb: &State, path: &str) -> Template { let id = path; if id.is_empty() { return Template::render("404", context! { uri: "" }); }; let users = db.get_users_by_role(id); match users { - Ok(users) => Template::render("index", context! { users: users }), + Ok(users) => { + let services = ldb.get_service_by_role(id); + match services { + Ok(services) => { + Template::render("index", context! { users: users, services: services }) + } + Err(_) => Template::render("404", context! { uri: "" }), + } + } Err(_) => Template::render("404", context! { uri: "" }), } } diff --git a/src/repository/localdb_repo.rs b/src/repository/localdb_repo.rs index bbfc858..6ace418 100644 --- a/src/repository/localdb_repo.rs +++ b/src/repository/localdb_repo.rs @@ -4,6 +4,7 @@ use dotenv::dotenv; use crate::models::setting_model::InternalService; use mongodb::{ + bson::doc, bson::extjson::de::Error, // results::InsertOneResult, sync::{Client, Collection}, @@ -83,4 +84,14 @@ impl LocalRepo { let services = cursors.map(|doc| doc.unwrap()).collect(); Ok(services) } + + pub fn get_service_by_role(&self, id: &str) -> Result, Error> { + let filter = doc! {"roles": { "$in": [id] } }; + let cursors = self + .servcol + .find(filter, None) + .expect("Error getting list of services"); + let services = cursors.map(|doc| doc.unwrap()).collect(); + Ok(services) + } } diff --git a/templates/nav.html.tera b/templates/nav.html.tera index 5eadcea..d4ea9c9 100644 --- a/templates/nav.html.tera +++ b/templates/nav.html.tera @@ -1,10 +1,11 @@ -
    {{ user.username }} diff --git a/templates/users.html.tera b/templates/users.html.tera index 81adb8b..b3a0d59 100644 --- a/templates/users.html.tera +++ b/templates/users.html.tera @@ -1,12 +1,25 @@

    Users

    - +
    - - - + + + From 4724bd1fc243ac570836a0a8bb9742f954c58493 Mon Sep 17 00:00:00 2001 From: Aran Varun Date: Thu, 6 Jun 2024 15:14:08 +0300 Subject: [PATCH 18/19] openapi works for roles --- Cargo.lock | 583 +++++++++++++++++++++++++++++++++++++-- Cargo.toml | 7 +- src/api/role_api.rs | 13 + src/main.rs | 33 ++- src/models/role_model.rs | 7 +- 5 files changed, 622 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7bc5101..be32d1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,6 +54,15 @@ dependencies = [ "libc", ] +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +dependencies = [ + "derive_arbitrary", +] + [[package]] name = "async-attributes" version = "1.1.2" @@ -347,6 +356,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "binascii" version = "0.1.4" @@ -539,6 +554,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam-channel" version = "0.5.12" @@ -644,6 +668,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -707,6 +742,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "dotenv" version = "0.15.0" @@ -862,6 +908,16 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" +[[package]] +name = "flate2" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1098,7 +1154,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.12", "indexmap", "slab", "tokio", @@ -1161,6 +1217,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http-body" version = "0.4.6" @@ -1168,7 +1235,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", "pin-project-lite", ] @@ -1204,8 +1294,8 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", @@ -1217,6 +1307,62 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.3.1", + "hyper-util", + "rustls 0.22.4", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.25.0", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.3.1", + "pin-project-lite", + "socket2 0.5.7", + "tokio", + "tower", + "tower-service", + "tracing", +] + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -1349,7 +1495,7 @@ dependencies = [ "socket2 0.5.7", "widestring", "windows-sys 0.48.0", - "winreg", + "winreg 0.50.0", ] [[package]] @@ -1535,6 +1681,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "miniz_oxide" version = "0.7.2" @@ -1584,8 +1740,8 @@ dependencies = [ "percent-encoding", "rand", "rustc_version_runtime", - "rustls", - "rustls-pemfile", + "rustls 0.21.12", + "rustls-pemfile 1.0.4", "serde", "serde_with", "sha-1", @@ -1596,13 +1752,13 @@ dependencies = [ "take_mut", "thiserror", "tokio", - "tokio-rustls", + "tokio-rustls 0.24.1", "tokio-util", "trust-dns-proto", "trust-dns-resolver", "typed-builder", "uuid", - "webpki-roots", + "webpki-roots 0.25.4", ] [[package]] @@ -1614,7 +1770,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http", + "http 0.2.12", "httparse", "log", "memchr", @@ -1688,6 +1844,27 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "object" version = "0.32.2" @@ -1868,6 +2045,26 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -1934,6 +2131,39 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit 0.21.1", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" version = "1.0.81" @@ -2089,6 +2319,48 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +[[package]] +name = "reqwest" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.3.1", + "hyper-rustls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls 0.22.4", + "rustls-pemfile 2.1.2", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls 0.25.0", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots 0.26.2", + "winreg 0.52.0", +] + [[package]] name = "resolv-conf" version = "0.7.0" @@ -2191,8 +2463,8 @@ dependencies = [ "cookie", "either", "futures", - "http", - "hyper", + "http 0.2.12", + "hyper 0.14.28", "indexmap", "log", "memchr", @@ -2221,6 +2493,45 @@ dependencies = [ "rocket_dyn_templates", "serde", "tera", + "utoipa", + "utoipa-rapidoc", + "utoipa-redoc", + "utoipa-scalar", + "utoipa-swagger-ui", +] + +[[package]] +name = "rust-embed" +version = "8.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19549741604902eb99a7ed0ee177a0663ee1eda51a29f71401f166e47e77806a" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb9f96e283ec64401f30d3df8ee2aaeb2561f34c824381efa24a35f79bf40ee4" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn 2.0.60", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c74a686185620830701348de757fd36bef4aa9680fd23c49fc539ddcc1af32" +dependencies = [ + "sha2", + "walkdir", ] [[package]] @@ -2292,10 +2603,24 @@ checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring", - "rustls-webpki", + "rustls-webpki 0.101.7", "sct", ] +[[package]] +name = "rustls" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.4", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -2305,6 +2630,22 @@ dependencies = [ "base64 0.21.7", ] +[[package]] +name = "rustls-pemfile" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +dependencies = [ + "base64 0.22.1", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -2315,6 +2656,17 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustls-webpki" +version = "0.102.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.15" @@ -2429,6 +2781,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "serde_with" version = "1.14.0" @@ -2611,6 +2975,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "take_mut" version = "0.2.2" @@ -2768,7 +3138,18 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls", + "rustls 0.21.12", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls 0.22.4", + "rustls-pki-types", "tokio", ] @@ -2807,7 +3188,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.22.12", ] [[package]] @@ -2819,6 +3200,17 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow 0.5.40", +] + [[package]] name = "toml_edit" version = "0.22.12" @@ -2829,9 +3221,30 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.6.7", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -3042,6 +3455,15 @@ dependencies = [ "unic-common", ] +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-bidi" version = "0.3.15" @@ -3086,6 +3508,85 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utoipa" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5afb1a60e207dca502682537fefcfd9921e71d0b83e9576060f09abc6efab23" +dependencies = [ + "indexmap", + "serde", + "serde_json", + "utoipa-gen", +] + +[[package]] +name = "utoipa-gen" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bf0e16c02bc4bf5322ab65f10ab1149bdbcaa782cba66dc7057370a3f8190be" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "regex", + "syn 2.0.60", +] + +[[package]] +name = "utoipa-rapidoc" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a32488b691c135d58eb78efcf8258ebb3db1ec7447964c6a83bd5e1ab7a39d9" +dependencies = [ + "rocket", + "serde", + "serde_json", + "utoipa", +] + +[[package]] +name = "utoipa-redoc" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca44a24600ba6bead97e455954d2f01b062af9eff5facba4266fd3d62687ef0f" +dependencies = [ + "rocket", + "serde", + "serde_json", + "utoipa", +] + +[[package]] +name = "utoipa-scalar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3ab4b7269d14d93626b0bfedf212f1b0995cb7d13d35daba21d579511e7fae8" +dependencies = [ + "rocket", + "serde", + "serde_json", + "utoipa", +] + +[[package]] +name = "utoipa-swagger-ui" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "943e0ff606c6d57d410fd5663a4d7c074ab2c5f14ab903b9514565e59fa1189e" +dependencies = [ + "mime_guess", + "regex", + "reqwest", + "rocket", + "rust-embed", + "serde", + "serde_json", + "url", + "utoipa", + "zip", +] + [[package]] name = "uuid" version = "1.8.0" @@ -3227,6 +3728,15 @@ version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" +[[package]] +name = "webpki-roots" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c452ad30530b54a4d8e71952716a212b08efd0f3562baa66c29a618b07da7c3" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "widestring" version = "1.1.0" @@ -3421,6 +3931,15 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + [[package]] name = "winnow" version = "0.6.7" @@ -3440,6 +3959,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "wyz" version = "0.5.1" @@ -3477,3 +4006,25 @@ dependencies = [ "quote", "syn 2.0.60", ] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zip" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cc23c04387f4da0374be4533ad1208cbb091d5c11d070dfef13676ad6497164" +dependencies = [ + "arbitrary", + "crc32fast", + "crossbeam-utils", + "displaydoc", + "flate2", + "indexmap", + "num_enum", + "thiserror", +] diff --git a/Cargo.toml b/Cargo.toml index b249e77..a1d14fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,17 @@ edition = "2021" [dependencies] # tokio = "1" # futures = "0.3" -rocket = {version = "0.5.0-rc.2", features = ["json"]} +rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0", features = ["derive"] } dotenv = "0.15.0" bson = { version = "2", features = ["chrono-0_4"] } # Needed for using chrono datetime in doc chrono = "0.4" # Used for setting DateTimes tera = { version = "1", default-features = false } +utoipa-scalar = { version = "0.1.0", features = ["rocket"] } +utoipa-rapidoc = { version = "4.0.0", features = ["rocket"] } +utoipa-redoc = { version = "4.0.0", features = ["rocket"] } +utoipa-swagger-ui = { version = "7.1.0", features = ["rocket"] } +utoipa = { version = "4.2.3", features = ["rocket_extras"] } [dependencies.mongodb] version = "2.8.2" diff --git a/src/api/role_api.rs b/src/api/role_api.rs index 231d1cb..b414855 100644 --- a/src/api/role_api.rs +++ b/src/api/role_api.rs @@ -1,6 +1,13 @@ use crate::{models::role_model::Role, repository::mongodb_repo::MongoRepo}; use rocket::{http::Status, serde::json::Json, State}; +#[utoipa::path( + context_path = "", + // request_body = Role, + responses( + (status = 200, description = "Get role", body = Role) + ) +)] #[get("/role/")] pub fn get_role(db: &State, path: String) -> Result, Status> { let id = path; @@ -14,6 +21,12 @@ pub fn get_role(db: &State, path: String) -> Result, Statu } } +#[utoipa::path( + context_path = "", + responses( + (status = 200, description = "Get all roles", body = [Role]) + ) +)] #[get("/roles")] pub fn get_all_roles(db: &State) -> Result>, Status> { let roles = db.get_all_roles(); diff --git a/src/main.rs b/src/main.rs index 33f3d8a..4d232c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,10 +8,11 @@ extern crate rocket; #[cfg(test)] mod tests; +use crate::models::role_model; use api::{ permission_api::get_all_permissions, rawdoc_api::get_all_docs, - role_api::{get_all_roles, get_role}, + role_api, room_api::get_all_rooms, sdui_api::get_full_layout, service_api::get_all_services, @@ -27,6 +28,10 @@ use rocket::{ serde::json::Json, }; use rocket_dyn_templates::Template; +use utoipa::OpenApi; +use utoipa_rapidoc::RapiDoc; +use utoipa_redoc::{Redoc, Servable}; +use utoipa_swagger_ui::SwaggerUi; // for test only #[get("/hello")] @@ -34,6 +39,22 @@ fn hello() -> Result, Status> { Ok(Json(String::from("Hello world"))) } +#[derive(OpenApi)] +#[openapi( + paths( + role_api::get_all_roles, + role_api::get_role, + ), + components( + schemas(role_model::Role) + ), + tags( + (name = "Role", description = "Role management endpoints.") + ), + // modifiers(&SecurityAddon) +)] +struct ApiDoc; + #[launch] fn rocket() -> _ { let ldb = LocalRepo::init(); @@ -42,6 +63,12 @@ fn rocket() -> _ { .manage(ldb) .manage(db) .mount("/", FileServer::from(relative!("static"))) + .mount( + "/", + SwaggerUi::new("/swagger-ui/<_..>").url("/api-docs/openapi.json", ApiDoc::openapi()), + ) + .mount("/", RapiDoc::new("/api-docs/openapi.json").path("/rapidoc")) + .mount("/", Redoc::with_url("/redoc", ApiDoc::openapi())) .mount( "/", routes![ @@ -49,10 +76,10 @@ fn rocket() -> _ { get_all_services, get_user_email, get_user_status, - get_role, + role_api::get_role, get_all_users, get_users_by_role, - get_all_roles, + role_api::get_all_roles, get_all_rooms, get_full_layout, get_all_docs, diff --git a/src/models/role_model.rs b/src/models/role_model.rs index 48069a9..bbc1369 100644 --- a/src/models/role_model.rs +++ b/src/models/role_model.rs @@ -1,10 +1,15 @@ // use mongodb::bson::oid::ObjectId; use serde::{Deserialize, Serialize}; +use utoipa::ToSchema; -#[derive(Debug, Serialize, Deserialize)] +/// Role struct +#[derive(Debug, ToSchema, Serialize, Deserialize)] pub struct Role { + /// Role name is the same as it's ID and is unique #[serde(rename = "_id")] id: String, + /// No idea what it is scope: String, + /// Role name is the same as it's ID name: String, } From b917ac0fd07a221e017bb1bcf0f7fa9bb4ba4983 Mon Sep 17 00:00:00 2001 From: Aran Varun Date: Thu, 6 Jun 2024 15:17:32 +0300 Subject: [PATCH 19/19] openapi works for roles --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 30d190e..a6a406a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ -# Create custom views for RocketChat database collections (Mongo) +# Create custom views for RocketChat database collections (Mongo) We use Rocket :) web framework written in Rust +Now we have OpenAPI for roles (thanks to `juhaku / utoipa`) and web interface using HTMX and Tera templates. + +--- + ```shell curl http://localhost:8000/users/ | jq ```
    UsernameRolesStatusUsername + {% if roles is defined %} + + {% else %} + Roles + {% endif %} + Status