Автоматизация создания установщика для Arch, доработка API
This commit is contained in:
Generated
+3
@@ -344,8 +344,10 @@ checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
@@ -3212,6 +3214,7 @@ dependencies = [
|
||||
"aes",
|
||||
"block-modes",
|
||||
"block-padding 0.3.3",
|
||||
"chrono",
|
||||
"hex",
|
||||
"magic-crypt",
|
||||
"rand 0.8.5",
|
||||
|
||||
@@ -22,6 +22,7 @@ hex = "0.4"
|
||||
aes = "0.7.5"
|
||||
block-modes = "0.8.1"
|
||||
block-padding = "0.3.3"
|
||||
chrono = "0.4.38"
|
||||
|
||||
[features]
|
||||
# This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!!
|
||||
|
||||
@@ -22,7 +22,7 @@ pub fn decrypt(key: &[u8], encrypted_data: &[u8]) -> String {
|
||||
String::from_utf8(decrypted_ciphertext).unwrap() // Вывод результата в виде строки
|
||||
}
|
||||
|
||||
/// Примеры
|
||||
// Примеры
|
||||
//println!("TEST ENC: {:?}", crate::aes_enc_dec::encrypt(&hex::decode(crate::multi_tcp_listener::get_token()).unwrap(), "{\"command\": \"status1\"}"));
|
||||
//println!("TEST DEC: {:?}\n", crate::aes_enc_dec::decrypt(&hex::decode(crate::multi_tcp_listener::get_token()).unwrap(), &crate::aes_enc_dec::encrypt(&hex::decode(crate::multi_tcp_listener::get_token()).unwrap(), "{\"command\": \"status1\"}")));
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ pub fn check_or_create_config_file(app_handle: tauri::AppHandle) {
|
||||
|
||||
let data = String::from(format!("{}\
|
||||
\"port\": 49494,\
|
||||
\"autostart\": true,\
|
||||
\"autostart\": false,\
|
||||
\"token\": \"{}\"\
|
||||
{}", "{", token, "}"));
|
||||
println!("{}", data);
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
use serde_json::Value;
|
||||
use chrono::{DateTime, Local};
|
||||
|
||||
use crate::aes_enc_dec::encrypt;
|
||||
use crate::tasks;
|
||||
|
||||
pub fn get_tasks_tcp(token: String) -> Vec<u8>{
|
||||
encrypt(&hex::decode(token).unwrap(), tasks::get_tasks().to_string().as_str())
|
||||
}
|
||||
|
||||
pub fn get_task_by_id_tcp(token: String, json: Value) -> Vec<u8> {
|
||||
let tasks: Value = tasks::get_tasks();
|
||||
let res;
|
||||
if !json.get("id").is_none(){
|
||||
res = encrypt(&hex::decode(token).unwrap(), tasks[json["id"].as_str().unwrap_or("")].to_string().as_str());
|
||||
} else{
|
||||
res = encrypt(&hex::decode(token).unwrap(), "400");
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
pub fn create_task_tcp(token: String, json: Value) -> Vec<u8> {
|
||||
if json["task"].is_object(){
|
||||
if json["task"]["name"].is_string(){
|
||||
let current_datetime: DateTime<Local> = Local::now();
|
||||
let date: String = current_datetime.format("%Y.%m.%d").to_string();
|
||||
let time: String = current_datetime.format("%H:%M").to_string();
|
||||
|
||||
let name = json["task"]["name"].as_str().unwrap().to_string();
|
||||
let description = json["task"]["description"].as_str().unwrap_or("").to_string();
|
||||
let priority = json["task"]["priority"].as_str().unwrap_or("0").to_string();
|
||||
|
||||
encrypt(&hex::decode(token).unwrap(), tasks::add_task(date, time, name, description, priority).as_str())
|
||||
} else{
|
||||
encrypt(&hex::decode(token).unwrap(), "400")
|
||||
}
|
||||
} else{
|
||||
encrypt(&hex::decode(token).unwrap(), "400")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn edit_task_tcp(token: String, json: Value) -> Vec<u8> {
|
||||
if json["task"].is_object(){
|
||||
if json["task"]["id"].is_number(){
|
||||
let id_task = json["task"]["id"].as_number().unwrap().to_string();
|
||||
let name = json["task"]["name"].as_str().unwrap().to_string();
|
||||
let description = json["task"]["description"].as_str().unwrap_or("").to_string();
|
||||
let priority = json["task"]["priority"].as_str().unwrap_or("0").to_string();
|
||||
|
||||
if tasks::edit_task(id_task, name, description, priority) {
|
||||
encrypt(&hex::decode(token).unwrap(), "200")
|
||||
} else{
|
||||
encrypt(&hex::decode(token).unwrap(), "400")
|
||||
}
|
||||
} else{
|
||||
encrypt(&hex::decode(token).unwrap(), "400")
|
||||
}
|
||||
} else{
|
||||
encrypt(&hex::decode(token).unwrap(), "400")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete_task_tcp(token: String, json: Value) -> Vec<u8> {
|
||||
let res;
|
||||
if !json.get("id").is_none(){
|
||||
if tasks::delete_task(json["id"].to_string()){
|
||||
res = encrypt(&hex::decode(token).unwrap(), "200");
|
||||
} else{
|
||||
res = encrypt(&hex::decode(token).unwrap(), "400");
|
||||
}
|
||||
} else{
|
||||
res = encrypt(&hex::decode(token).unwrap(), "400");
|
||||
}
|
||||
res
|
||||
}
|
||||
@@ -6,7 +6,7 @@ use std::string::String;
|
||||
use serde_json::Value;
|
||||
use tauri::{AppHandle, Manager};
|
||||
|
||||
use crate::config_tcp;
|
||||
use crate::{config_tcp, handler_commands};
|
||||
use crate::enc_dec_file::decrypt_file;
|
||||
use crate::aes_enc_dec::{encrypt, decrypt};
|
||||
|
||||
@@ -31,7 +31,7 @@ fn enc_hex_to_data(data: &str) -> String{
|
||||
} // Расшифровка обёрнутых в HEX данных до строки
|
||||
|
||||
|
||||
pub fn create_tcp_listener(app_handle: AppHandle) -> TcpListener{
|
||||
fn create_tcp_listener(app_handle: AppHandle) -> TcpListener{
|
||||
let path: PathBuf = [
|
||||
app_handle.path_resolver().app_local_data_dir().unwrap(),
|
||||
"ToDo".into(),
|
||||
@@ -88,19 +88,44 @@ fn handle_connection(mut stream: TcpStream) {
|
||||
let res = enc_hex_to_data(req.trim()); // Дешифрование
|
||||
let json: Value = serde_json::from_str(res.as_str()).unwrap_or(serde_json::json!("")); // Попытка преобразования запроса в JSON
|
||||
if json != serde_json::json!(""){
|
||||
println!("JSON: {:?}", json);
|
||||
println!("JSON command: {:?}", json["command"]);
|
||||
match json["command"].as_str().unwrap() { // Сравнивание команд
|
||||
"stop" => {
|
||||
unsafe {
|
||||
TCP_COMMAND = "stop";
|
||||
}
|
||||
let res = encrypt(&hex::decode(get_token()).unwrap(), "200");
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
},
|
||||
"status" => {
|
||||
let res = encrypt(&hex::decode(get_token()).unwrap(), "200");
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
},
|
||||
"get_tasks" => {
|
||||
let res = handler_commands::get_tasks_tcp(get_token());
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
},
|
||||
"get_task_by_id" => {
|
||||
let res = handler_commands::get_task_by_id_tcp(get_token(), json);
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
},
|
||||
"create_task" => {
|
||||
let res = handler_commands::create_task_tcp(get_token(), json);
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
},
|
||||
"edit_task" => {
|
||||
let res = handler_commands::edit_task_tcp(get_token(), json);
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
},
|
||||
"delete_task" => {
|
||||
let res = handler_commands::delete_task_tcp(get_token(), json);
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
} else{
|
||||
stream.write(hex::encode(encrypt(&hex::decode(get_token()).unwrap(), "400")).as_bytes()).unwrap();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -5,6 +5,7 @@ use std::thread;
|
||||
|
||||
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
|
||||
#[path="api/multithread_tcp_listener.rs"] mod multi_tcp_listener;
|
||||
#[path= "api/handler_commands.rs"] mod handler_commands;
|
||||
#[path= "api/config_tcp.rs"] mod config_tcp;
|
||||
#[path= "api/aes_enc_dec.rs"] mod aes_enc_dec;
|
||||
|
||||
@@ -24,22 +25,21 @@ fn open_api_window(app_handle: tauri::AppHandle){
|
||||
.decorations(false)
|
||||
.build() {
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
println!("{err}");
|
||||
Err(_) => {
|
||||
//println!("{err}");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn main() {
|
||||
std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
let app_handle = app.handle();
|
||||
|
||||
if config_tcp::get_autostart(app_handle.clone()) {
|
||||
thread::spawn(move || {
|
||||
multi_tcp_listener::create_tcp_listener(app_handle);
|
||||
});
|
||||
multi_tcp_listener::start_tcp_server(app_handle);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -1,20 +1,29 @@
|
||||
use std::fs::{read_to_string};
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::fs::File;
|
||||
use serde_json::{Value, json};
|
||||
use rust_fuzzy_search::fuzzy_search_best_n;
|
||||
|
||||
use crate::enc_dec_file::{encrypt_n_save_file, decrypt_file};
|
||||
|
||||
static mut PATH_CONFIG: Option<&'static str> = None;
|
||||
|
||||
#[tauri::command]
|
||||
pub fn check_or_create_tasks_file(app_handle: tauri::AppHandle) {
|
||||
let mut path = app_handle.path_resolver().app_local_data_dir().unwrap();
|
||||
path.push("ToDo");
|
||||
path.push("tasks");
|
||||
let path: PathBuf = [
|
||||
app_handle.path_resolver().app_local_data_dir().unwrap(),
|
||||
"ToDo".into(),
|
||||
"tasks.enc".into(),
|
||||
].iter().collect(); // Путь к конфиг файлу
|
||||
|
||||
path.set_extension("enc");
|
||||
let path_str = Box::leak(Box::new(path.to_string_lossy().into_owned()));
|
||||
|
||||
let exist: bool = Path::new(&path).exists();
|
||||
unsafe {
|
||||
PATH_CONFIG = Some(path_str);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let exist: bool = Path::new(PATH_CONFIG.unwrap()).exists();
|
||||
if exist{
|
||||
let content = read_to_string(path);
|
||||
return match content {
|
||||
@@ -44,32 +53,24 @@ pub fn check_or_create_tasks_file(app_handle: tauri::AppHandle) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_tasks(app_handle: tauri::AppHandle) -> Value {
|
||||
let mut path = app_handle.path_resolver().app_local_data_dir().unwrap();
|
||||
path.push("ToDo");
|
||||
path.push("tasks");
|
||||
|
||||
path.set_extension("enc");
|
||||
|
||||
let content = decrypt_file(path);
|
||||
pub fn get_tasks() -> Value {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
let res = &data["tasks"];
|
||||
|
||||
return res.clone();
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn search_tasks(app_handle: tauri::AppHandle, value: String) -> Value {
|
||||
let mut path = app_handle.path_resolver().app_local_data_dir().unwrap();
|
||||
path.push("ToDo");
|
||||
path.push("tasks");
|
||||
|
||||
path.set_extension("enc");
|
||||
|
||||
let content = decrypt_file(path);
|
||||
pub fn search_tasks(value: String) -> Value {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
let mut tasks = vec![];
|
||||
@@ -102,16 +103,12 @@ pub fn search_tasks(app_handle: tauri::AppHandle, value: String) -> Value {
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn add_task(app_handle: tauri::AppHandle, date: String, time: String, name: String, description: String, priority: String) {
|
||||
let mut path = app_handle.path_resolver().app_local_data_dir().unwrap();
|
||||
path.push("ToDo");
|
||||
path.push("tasks");
|
||||
|
||||
path.set_extension("enc");
|
||||
|
||||
let content = decrypt_file(path.clone());
|
||||
pub fn add_task(date: String, time: String, name: String, description: String, priority: String) -> String {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
let pending = data.clone();
|
||||
@@ -130,35 +127,35 @@ pub fn add_task(app_handle: tauri::AppHandle, date: String, time: String, name:
|
||||
data["id"] = (id.as_i64().unwrap() + 1).into();
|
||||
|
||||
data["tasks"][id.to_string()] = task;
|
||||
encrypt_n_save_file(path.into(), data.to_string());
|
||||
encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data.to_string());
|
||||
|
||||
return id.to_string();
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn edit_task(app_handle: tauri::AppHandle, id_task: String, name: String, description: String, priority: String) {
|
||||
let mut path = app_handle.path_resolver().app_local_data_dir().unwrap();
|
||||
path.push("ToDo");
|
||||
path.push("tasks");
|
||||
|
||||
path.set_extension("enc");
|
||||
|
||||
let content = decrypt_file(path.clone());
|
||||
pub fn edit_task(id_task: String, name: String, description: String, priority: String) -> bool{
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
return if !data["tasks"][id_task.clone()].get("id").is_none(){
|
||||
data["tasks"][id_task.clone()]["name"] = json!(name);
|
||||
data["tasks"][id_task.clone()]["description"] = json!(description);
|
||||
data["tasks"][id_task]["priority"] = json!(priority);
|
||||
|
||||
encrypt_n_save_file(path.into(), data.to_string());
|
||||
encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data.to_string());
|
||||
true
|
||||
} else{
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn delete_task(app_handle: tauri::AppHandle, id_task: String) {
|
||||
let mut path = app_handle.path_resolver().app_local_data_dir().unwrap();
|
||||
path.push("ToDo");
|
||||
path.push("tasks");
|
||||
|
||||
path.set_extension("enc");
|
||||
|
||||
let content = decrypt_file(path.clone());
|
||||
pub fn delete_task(id_task: String) -> bool{
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
let tasks = data["tasks"].as_object_mut().unwrap();
|
||||
@@ -166,24 +163,22 @@ pub fn delete_task(app_handle: tauri::AppHandle, id_task: String) {
|
||||
for (key, value) in binding {
|
||||
if id_task == value["id"] {
|
||||
tasks.remove(&key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
data["tasks"] = json!(tasks);
|
||||
encrypt_n_save_file(path.into(), data.to_string());
|
||||
encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data.to_string());
|
||||
return true
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn set_task_field(app_handle: tauri::AppHandle, id_task: String, field: String, value: String) {
|
||||
let mut path = app_handle.path_resolver().app_local_data_dir().unwrap();
|
||||
path.push("ToDo");
|
||||
path.push("tasks");
|
||||
|
||||
path.set_extension("enc");
|
||||
|
||||
let content = decrypt_file(path.clone());
|
||||
pub fn set_task_field(id_task: String, field: String, value: String) {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
data["tasks"][id_task][field] = json!(value);
|
||||
|
||||
encrypt_n_save_file(path.into(), data.to_string());
|
||||
encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data.to_string());
|
||||
}
|
||||
}
|
||||
+28
-10
@@ -8,10 +8,13 @@ import {invoke} from "@tauri-apps/api";
|
||||
import ConfirmModal from "./api_components/ConfirmModal.vue";
|
||||
import {listen} from "@tauri-apps/api/event";
|
||||
import SettingsModal from "./api_components/SettingsModal.vue";
|
||||
import PageHandler from "./api_wiki/PageHandler.vue";
|
||||
|
||||
const isDark = useDark();
|
||||
const toggleDark = useToggle(isDark);
|
||||
|
||||
let wiki_open = ref(false);
|
||||
|
||||
let pending = ref(true);
|
||||
let api_status = ref(false);
|
||||
|
||||
@@ -106,7 +109,11 @@ function select_input(event){
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div data-tauri-drag-region class="z-50 opacity-50 titlebar h-[30px] select-none fixed flex justify-end top-0 right-0 left-0 bg-gray-100 dark:bg-zinc-800">
|
||||
<div data-tauri-drag-region class="z-50 titlebar h-[30px] select-none fixed flex justify-end top-0 right-0 left-0 bg-gray-100 dark:bg-zinc-800">
|
||||
<p class="fixed left-2 top-0.5 text-lg dark:text-white">
|
||||
<span v-if="!wiki_open">API</span>
|
||||
<span v-else>API Wiki</span>
|
||||
</p>
|
||||
<div @click="appWindow.minimize()" class="titlebar-button hover:bg-gray-200 dark:hover:bg-gray-700 justify-center inline-flex w-[30px] h-[30px] items-center dark:text-white" id="titlebar-minimize">
|
||||
<Icon class="" icon="mdi:window-minimize" width="20" height="20"/>
|
||||
</div>
|
||||
@@ -121,17 +128,17 @@ function select_input(event){
|
||||
<Icon icon="line-md:loading-twotone-loop" width="96" height="96" class="text-green-500 absolute top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%]"/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<button class="absolute top-10 left-2" @click="open_settings">
|
||||
<Icon icon="material-symbols:settings-outline" width="38" height="38" class="text-zinc-600 dark:text-zinc-200"/>
|
||||
</button>
|
||||
<button class="absolute top-10 right-2" @click="toggleDark()">
|
||||
<Icon v-if="!isDark" class="group-hover:invert text-yellow-400" icon="flowbite:sun-solid" width="38" height="38"/>
|
||||
<Icon v-else class="group-hover:invert text-blue-400" icon="ri:moon-fill" width="38" height="38"/>
|
||||
</button>
|
||||
<div v-if="!wiki_open">
|
||||
<button class="absolute top-10 left-2" @click="open_settings">
|
||||
<Icon icon="material-symbols:settings-outline" width="38" height="38" class="text-zinc-600 dark:text-zinc-200"/>
|
||||
</button>
|
||||
<div class="mt-8">
|
||||
<p class="text-center dark:text-white">API</p>
|
||||
<div class="grid grid-cols-1 grid-rows-1 sm:grid-cols-2 sm:grid-rows-2 mt-8 sm:mt-2 gap-2.5 dark:text-white md:mt-4 md:mx-16 lg:mt-8 lg:mx-24">
|
||||
<div class="text-center shadow dark:shadow-white mx-4 sm:mx-0 sm:ml-4 rounded-lg p-1">
|
||||
<div class="mt-[28vh] grid grid-cols-1 grid-rows-3 sm:grid-cols-2 sm:grid-rows-2 gap-2.5 dark:text-white md:mx-16 lg:mx-24">
|
||||
<div class="text-center shadow dark:shadow-white mx-4 sm:mx-0 sm:ml-4 rounded-lg p-1 row-span-1">
|
||||
<p class="mb-4">Статус</p>
|
||||
<div v-if="!api_status" class="flex text-center align-middle items-center">
|
||||
<Icon class="text-red-500" icon="oui:dot" width="36" height="36"/>
|
||||
@@ -144,7 +151,7 @@ function select_input(event){
|
||||
<button @click="stop_api" class="bg-green-500 text-white rounded-lg py-1 px-2 ml-2 hover:bg-green-600 transition-colors">Остановить</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid text-center shadow dark:shadow-white mx-4 sm:mx-0 sm:mr-4 rounded-lg p-1 justify-center items-center">
|
||||
<div class="grid text-center shadow dark:shadow-white mx-4 sm:mx-0 sm:mr-4 rounded-lg p-1 justify-center items-center row-start-2 sm:row-span-1">
|
||||
<div v-if="api_status">
|
||||
<p class="mb-2">Токен подключения</p>
|
||||
<div>
|
||||
@@ -158,12 +165,23 @@ function select_input(event){
|
||||
</div>
|
||||
<p v-else class="underline decoration-red-500 decoration-2 underline-offset-2">Нет подключения</p>
|
||||
</div>
|
||||
<div @click="wiki_open = true" class="cursor-pointer group mt-2 text-center shadow dark:shadow-white hover:shadow-md dark:hover:shadow-white ml-4 mr-6 sm:mr-4 rounded-lg p-1 col-start-1 col-end-3 row-start-3 sm:row-span-2">
|
||||
<Icon class="mt-1 text-zinc-800 dark:text-zinc-100 mx-auto" icon="mingcute:question-line" width="48" height="48"/>
|
||||
<p class="text-xl mt-1 mb-2.5 group-hover:underline">Как этим пользоваться?</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="confirm_modal || settings_modal" class="bg-black w-[100vw] h-full fixed top-0 opacity-70 z-40"/>
|
||||
<ConfirmModal v-if="confirm_modal" @close="confirm_modal = false" @yes="regen_token"/>
|
||||
<SettingsModal v-if="settings_modal" @close="settings_modal = false" :autostart="settings_autostart" :port="settings_port"/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<button class="absolute top-10 left-2" @click="wiki_open = false">
|
||||
<Icon icon="material-symbols:arrow-back" width="38" height="38" class="text-zinc-600 dark:text-zinc-200"/>
|
||||
</button>
|
||||
<PageHandler/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
@@ -178,7 +196,7 @@ function select_input(event){
|
||||
line-height: 24px;
|
||||
font-weight: 400;
|
||||
|
||||
background-color: rgb(246 247 248);
|
||||
background-color: rgb(244 245 246);
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
@@ -188,6 +206,6 @@ function select_input(event){
|
||||
}
|
||||
|
||||
:root.dark {
|
||||
background-color: rgb(30, 30, 30);
|
||||
background-color: rgb(35, 35, 35);
|
||||
}
|
||||
</style>
|
||||
+3
-2
@@ -147,7 +147,8 @@ async function open_api(){
|
||||
|
||||
|
||||
<template>
|
||||
<div data-tauri-drag-region class="z-50 opacity-50 titlebar h-[30px] select-none fixed flex justify-end top-0 right-0 left-0 bg-gray-100 dark:bg-zinc-800">
|
||||
<div data-tauri-drag-region class="z-50 titlebar h-[30px] select-none fixed flex justify-end top-0 right-0 left-0 bg-gray-100 dark:bg-zinc-800">
|
||||
<p class="fixed left-2 top-0.5 text-lg dark:text-white">To Do</p>
|
||||
<div @click="appWindow.minimize()" class="titlebar-button hover:bg-gray-200 dark:hover:bg-gray-700 justify-center inline-flex w-[30px] h-[30px] items-center dark:text-white" id="titlebar-minimize">
|
||||
<Icon class="" icon="mdi:window-minimize" width="20" height="20"/>
|
||||
</div>
|
||||
@@ -162,7 +163,7 @@ async function open_api(){
|
||||
<Icon icon="line-md:loading-twotone-loop" width="96" height="96" class="text-green-500 absolute top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%]"/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<button class="absolute bottom-2 left-2" @click="open_api()">
|
||||
<button class="absolute bottom-2 left-2 opacity-50 hover:opacity-100" @click="open_api()">
|
||||
<Icon icon="icon-park-outline:earth" width="40" height="40" class="relative text-zinc-400 dark:text-zinc-300"/>
|
||||
<Icon v-if="api_status" class="absolute bottom-4 left-4 text-green-500" icon="oui:dot" width="36" height="36"/>
|
||||
<Icon v-else class="absolute bottom-4 left-4 text-red-500" icon="oui:dot" width="36" height="36"/>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<details class="group pt-1 text-md border-gray-400 open:border open:px-1 open:py-1">
|
||||
<summary class="flex cursor-pointer flex-row items-center justify-between py-1 font-semibold text-gray-800 marker:[font-size:0px]">
|
||||
<p class="mx-1 dark:text-gray-100 inline-flex items-center"><slot name="title"/></p>
|
||||
<svg class="h-6 w-6 rotate-0 transform text-gray-400 group-open:rotate-180" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"></path>
|
||||
</svg>
|
||||
</summary>
|
||||
<p class="mx-2 text-gray-700 dark:text-gray-200"><slot name="body"/></p>
|
||||
</details>
|
||||
<hr class="border-gray-400">
|
||||
</template>
|
||||
@@ -0,0 +1,13 @@
|
||||
<script setup>
|
||||
import {Icon} from "@iconify/vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="border-zinc-400 dark:border-zinc-200 border bg-zinc-300 dark:bg-zinc-700 rounded-2xl p-2 mx-1 my-2 dark:text-gray-100">
|
||||
<div class="flex">
|
||||
<Icon icon="material-symbols:code" width="26" height="26"/>
|
||||
<p class="text-md ml-1 mt-0.5"><slot name="title"/></p>
|
||||
</div>
|
||||
<p class="text-lg m-1 dark:text-gray-100 whitespace-pre-wrap"><slot name="body"/></p>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,13 @@
|
||||
<script setup>
|
||||
import {Icon} from "@iconify/vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="border-yellow-500 dark:border-yellow-600 border bg-yellow-50 dark:bg-gray-700 rounded-2xl p-2 m-2 text-yellow-600 dark:text-yellow-300">
|
||||
<div class="flex">
|
||||
<Icon icon="ic:round-warning" width="32" height="32"/>
|
||||
<p class="text-xl ml-1 mt-0.5"><slot name="title"/></p>
|
||||
</div>
|
||||
<p class="text-lg m-1"><slot name="body"/></p>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,376 @@
|
||||
<script setup>
|
||||
import {ref} from "vue";
|
||||
import {Icon} from "@iconify/vue";
|
||||
import Warning from "../api_components/notes/Warning.vue";
|
||||
import AccordionElement from "../api_components/AccordionElement.vue";
|
||||
import Code from "../api_components/notes/Code.vue";
|
||||
|
||||
let page = ref('main');
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="absolute top-11 left-[50%] translate-x-[-50%] flex text-lg dark:text-white gap-6">
|
||||
<div @click="page = 'main'" title="Основы" class="cursor-pointer border-b-2" :class="[page === 'main' ? 'border-b-black dark:border-b-white': 'border-b-transparent']">
|
||||
<Icon icon="material-symbols:home" width="40" height="40"/>
|
||||
</div>
|
||||
<div @click="page = 'commands'" title="Команды" class="cursor-pointer border-b-2" :class="[page === 'commands' ? 'border-b-black dark:border-b-white': 'border-b-transparent']">
|
||||
<Icon icon="ri:slash-commands-2" width="38" height="38"/>
|
||||
</div>
|
||||
<div @click="page = 'examples'" title="Примеры" class="cursor-pointer border-b-2" :class="[page === 'examples' ? 'border-b-black dark:border-b-white': 'border-b-transparent']">
|
||||
<Icon icon="majesticons:list-box" width="40" height="40"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-24 mx-8 dark:text-white">
|
||||
<div v-if="page === 'main'" class="lg:mx-12 lg:mt-32 xl:mx-24 xl:mt-48">
|
||||
<p class="text-2xl ml-4 leading-9">Что это такое?</p>
|
||||
<hr>
|
||||
<p class="text-lg ml-2 mt-2 leading-8">
|
||||
<span class="font-bold">API</span>(application programming interface) - описание способов, взаимодействия компьютерной программы с другими.
|
||||
API (интерфейс программирования приложения) упрощает процесс программирования при создании приложений, предоставляя только объекты или действия, необходимые разработчику.
|
||||
</p>
|
||||
<Warning>
|
||||
<template v-slot:title>Внимание!</template>
|
||||
<template v-slot:body>
|
||||
Эта программа предоставляет API с защищённым соединением с помощью AES256.
|
||||
Подключение без защиты не удастся. Возможно будет добавлена поддержка незащищённого соединения.
|
||||
</template>
|
||||
</Warning>
|
||||
<hr>
|
||||
<p class="text-lg ml-2 mt-2 leading-10">
|
||||
<span class="flex">Доступные команды описаны на вкладке "Команды" - <Icon class="ml-2" icon="ri:slash-commands-2" width="38" height="38"/></span>
|
||||
<span class="flex">Примеры описаны на вкладке "Примеры" - <Icon class="ml-2" icon="majesticons:list-box" width="40" height="40"/></span>
|
||||
</p>
|
||||
</div>
|
||||
<div v-if="page === 'commands'" class="lg:mx-12 lg:mt-32 xl:mx-24 xl:mt-48">
|
||||
<p class="text-2xl ml-4 leading-9">Доступные команды</p>
|
||||
|
||||
<div class="px-3 mx-6 mt-0 grid grid-cols-1 gap-y-1">
|
||||
<AccordionElement>
|
||||
<template v-slot:title>
|
||||
<div class="text-white bg-blue-400 rounded-lg py-1 px-2 mr-2">GET</div>
|
||||
status
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<span class="ml-6 text-lg">Функция для проверки статуса сервера</span>
|
||||
<Code>
|
||||
<template v-slot:title>Структура запроса</template>
|
||||
<template v-slot:body>
|
||||
{ <br>
|
||||
 "command": "status" <br>
|
||||
} <br>
|
||||
</template>
|
||||
</Code>
|
||||
<div class="border border-zinc-400 rounded-xl p-2 mx-1 my-2">
|
||||
<p class="text-lg">Параметры</p>
|
||||
<hr>
|
||||
<div class="mx-3">
|
||||
<div class="my-3">
|
||||
<p>
|
||||
command <span class="text-red-500 text-sm">*обязательно</span><br>
|
||||
название команды <span class="opacity-80">[String]</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border border-zinc-400 rounded-xl p-2 mx-1 my-2">
|
||||
<p class="text-lg">Результат</p>
|
||||
<hr>
|
||||
<div class="mx-3">
|
||||
<div class="my-2">
|
||||
<p>
|
||||
200 - сервер работает <br>
|
||||
*нет доступа* - сервер не работает <br>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</AccordionElement>
|
||||
<AccordionElement>
|
||||
<template v-slot:title>
|
||||
<div class="text-white bg-blue-400 rounded-lg py-1 px-2 mr-2">GET</div>
|
||||
get_tasks
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<span class="ml-6 text-lg">Функция для получения всех задач</span>
|
||||
<Code>
|
||||
<template v-slot:title>Структура запроса</template>
|
||||
<template v-slot:body>
|
||||
{ <br>
|
||||
 "command": "get_tasks" <br>
|
||||
} <br>
|
||||
</template>
|
||||
</Code>
|
||||
<div class="border border-zinc-400 rounded-xl p-2 mx-1 my-2">
|
||||
<p class="text-lg">Параметры</p>
|
||||
<hr>
|
||||
<div class="mx-3">
|
||||
<div class="my-3">
|
||||
<p>
|
||||
command <span class="text-red-500 text-sm">*обязательно</span><br>
|
||||
название команды <span class="opacity-80">[String]</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border border-zinc-400 rounded-xl p-2 mx-1 my-2">
|
||||
<p class="text-lg">Результат</p>
|
||||
<hr>
|
||||
<div class="mx-3">
|
||||
<div class="my-2">
|
||||
<p>
|
||||
JSON - список задач <br>
|
||||
400 - неверные параметры запроса <br>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</AccordionElement>
|
||||
<AccordionElement>
|
||||
<template v-slot:title>
|
||||
<div class="text-white bg-blue-400 rounded-lg py-1 px-2 mr-2">GET</div>
|
||||
get_task_by_id
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<span class="ml-6 text-lg">Функция для получения задачи по id</span>
|
||||
<Code>
|
||||
<template v-slot:title>Структура запроса</template>
|
||||
<template v-slot:body>
|
||||
{ <br>
|
||||
 "command": "get_task_by_id" <br>
|
||||
 "id": "id задачи" <br>
|
||||
} <br>
|
||||
</template>
|
||||
</Code>
|
||||
<div class="border border-zinc-400 rounded-xl p-2 mx-1 my-2">
|
||||
<p class="text-lg">Параметры</p>
|
||||
<hr>
|
||||
<div class="mx-3">
|
||||
<div class="my-3">
|
||||
<p>
|
||||
command <span class="text-red-500 text-sm">*обязательно</span><br>
|
||||
название команды <span class="opacity-80">[String]</span><br>
|
||||
id <span class="text-red-500 text-sm">*обязательно</span><br>
|
||||
id задачи <span class="opacity-80">[String]</span><br>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border border-zinc-400 rounded-xl p-2 mx-1 my-2">
|
||||
<p class="text-lg">Результат</p>
|
||||
<hr>
|
||||
<div class="mx-3">
|
||||
<div class="my-2">
|
||||
<p>
|
||||
JSON - задача <br>
|
||||
null - задача не найдена <br>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</AccordionElement>
|
||||
<AccordionElement>
|
||||
<template v-slot:title>
|
||||
<div class="text-white bg-green-500 rounded-lg py-1 px-2 mr-2">POST</div>
|
||||
create_task
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<span class="ml-6 text-lg">Функция для создания задачи</span>
|
||||
<Code>
|
||||
<template v-slot:title>Структура запроса</template>
|
||||
<template v-slot:body>
|
||||
{ <br>
|
||||
 "command": "get_task_by_id" <br>
|
||||
 "task": { <br>
|
||||
  "name": "Новая задача" <br>
|
||||
  "description": "Описание" <br>
|
||||
  "priority": "4" <br>
|
||||
 } <br>
|
||||
} <br>
|
||||
</template>
|
||||
</Code>
|
||||
<div class="border border-zinc-400 rounded-xl p-2 mx-1 my-2">
|
||||
<p class="text-lg">Параметры</p>
|
||||
<hr>
|
||||
<div class="mx-3">
|
||||
<div class="my-3">
|
||||
<p>
|
||||
command <span class="text-red-500 text-sm">*обязательно</span><br>
|
||||
название команды <span class="opacity-80">[String]</span><br>
|
||||
task <span class="text-red-500 text-sm">*обязательно</span><br>
|
||||
задача <span class="opacity-80">[JSON Object]</span><br>
|
||||
 name <span class="text-red-500 text-sm">*обязательно</span><br>
|
||||
  название задачи <span class="opacity-80">[String]</span><br>
|
||||
 description<br>
|
||||
  описание задачи <span class="opacity-80">[String]</span><br>
|
||||
 priority<br>
|
||||
  проритет задачи (0-10) <span class="opacity-80">[String]</span><br>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border border-zinc-400 rounded-xl p-2 mx-1 my-2">
|
||||
<p class="text-lg">Результат</p>
|
||||
<hr>
|
||||
<div class="mx-3">
|
||||
<div class="my-2">
|
||||
<p>
|
||||
String - id, созданной задачи <br>
|
||||
400 - неверный параметр запроса <br>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</AccordionElement>
|
||||
<AccordionElement>
|
||||
<template v-slot:title>
|
||||
<div class="text-white bg-yellow-500 rounded-lg py-1 px-2 mr-2">PUT</div>
|
||||
edit_task
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<span class="ml-6 text-lg">Функция для изменения задачи по id</span>
|
||||
<Code>
|
||||
<template v-slot:title>Структура запроса</template>
|
||||
<template v-slot:body>
|
||||
{ <br>
|
||||
 "command": "edit_task" <br>
|
||||
 "task": { <br>
|
||||
  "id": "2" <br>
|
||||
  "name": "Новая задача" <br>
|
||||
  "description": "Описание" <br>
|
||||
  "priority": "4" <br>
|
||||
 } <br>
|
||||
} <br>
|
||||
</template>
|
||||
</Code>
|
||||
<div class="border border-zinc-400 rounded-xl p-2 mx-1 my-2">
|
||||
<p class="text-lg">Параметры</p>
|
||||
<hr>
|
||||
<div class="mx-3">
|
||||
<div class="my-3">
|
||||
<p>
|
||||
command <span class="text-red-500 text-sm">*обязательно</span><br>
|
||||
название команды <span class="opacity-80">[String]</span><br>
|
||||
task <span class="text-red-500 text-sm">*обязательно</span><br>
|
||||
задача <span class="opacity-80">[JSON Object]</span><br>
|
||||
 id <span class="text-red-500 text-sm">*обязательно</span><br>
|
||||
  id задачи <span class="opacity-80">[String]</span><br>
|
||||
 name <span class="text-red-500 text-sm">*обязательно</span><br>
|
||||
  название задачи <span class="opacity-80">[String]</span><br>
|
||||
 description<br>
|
||||
  описание задачи <span class="opacity-80">[String]</span><br>
|
||||
 priority<br>
|
||||
  проритет задачи (0-10) <span class="opacity-80">[String]</span><br>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border border-zinc-400 rounded-xl p-2 mx-1 my-2">
|
||||
<p class="text-lg">Результат</p>
|
||||
<hr>
|
||||
<div class="mx-3">
|
||||
<div class="my-2">
|
||||
<p>
|
||||
200 - задача изменена <br>
|
||||
400 - неверный параметр запроса <br>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</AccordionElement>
|
||||
<AccordionElement>
|
||||
<template v-slot:title>
|
||||
<div class="text-white bg-red-400 rounded-lg py-1 px-2 mr-2">DELETE</div>
|
||||
delete_task
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<span class="ml-6 text-lg">Функция для удаления задачи по id</span>
|
||||
<Code>
|
||||
<template v-slot:title>Структура запроса</template>
|
||||
<template v-slot:body>
|
||||
{ <br>
|
||||
 "command": "delete_task" <br>
|
||||
 "id": "id задачи" <br>
|
||||
} <br>
|
||||
</template>
|
||||
</Code>
|
||||
<div class="border border-zinc-400 rounded-xl p-2 mx-1 my-2">
|
||||
<p class="text-lg">Параметры</p>
|
||||
<hr>
|
||||
<div class="mx-3">
|
||||
<div class="my-3">
|
||||
<p>
|
||||
command <span class="text-red-500 text-sm">*обязательно</span><br>
|
||||
название команды <span class="opacity-80">[String]</span><br>
|
||||
id <span class="text-red-500 text-sm">*обязательно</span><br>
|
||||
id задачи <span class="opacity-80">[String]</span><br>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border border-zinc-400 rounded-xl p-2 mx-1 my-2">
|
||||
<p class="text-lg">Результат</p>
|
||||
<hr>
|
||||
<div class="mx-3">
|
||||
<div class="my-2">
|
||||
<p>
|
||||
200 - задача удалена <br>
|
||||
400 - неверный параметр запроса <br>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</AccordionElement>
|
||||
<AccordionElement>
|
||||
<template v-slot:title>
|
||||
<div class="text-white bg-green-500 rounded-lg py-1 px-2 mr-2">POST</div>
|
||||
stop
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<span class="ml-6 text-lg">Функция для выключения API</span>
|
||||
<Code>
|
||||
<template v-slot:title>Структура запроса</template>
|
||||
<template v-slot:body>
|
||||
{ <br>
|
||||
 "command": "stop" <br>
|
||||
} <br>
|
||||
</template>
|
||||
</Code>
|
||||
<div class="border border-zinc-400 rounded-xl p-2 mx-1 my-2">
|
||||
<p class="text-lg">Параметры</p>
|
||||
<hr>
|
||||
<div class="mx-3">
|
||||
<div class="my-3">
|
||||
<p>
|
||||
command <span class="text-red-500 text-sm">*обязательно</span><br>
|
||||
название команды <span class="opacity-80">[String]</span><br>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border border-zinc-400 rounded-xl p-2 mx-1 my-2">
|
||||
<p class="text-lg">Результат</p>
|
||||
<hr>
|
||||
<div class="mx-3">
|
||||
<div class="my-2">
|
||||
<p>
|
||||
200 - API выключается <br>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</AccordionElement>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,18 +1,17 @@
|
||||
<script setup>
|
||||
import {invoke} from "@tauri-apps/api";
|
||||
import {ref} from "vue";
|
||||
import {Icon} from "@iconify/vue";
|
||||
|
||||
let name = "";
|
||||
let description = "";
|
||||
let priority = 0;
|
||||
let priority = ref(0);
|
||||
|
||||
let error = ref(" ");
|
||||
|
||||
async function create_task(){
|
||||
if (name.replace(/ /g,'') === ""){
|
||||
error.value = "Название задачи не может быть пустым!";
|
||||
} else if(priority < 0 || priority > 10){
|
||||
error.value = "Приоритет не может быть меньше 0 или больше 10";
|
||||
} else{
|
||||
let nowDateTime = new Date();
|
||||
let date = nowDateTime.getFullYear() + "." + ('0' + (nowDateTime.getMonth()+1)).slice(-2) + '.'
|
||||
@@ -24,7 +23,7 @@ async function create_task(){
|
||||
time: time,
|
||||
name: name,
|
||||
description: description,
|
||||
priority: priority.toString()
|
||||
priority: priority.value.toString()
|
||||
});
|
||||
|
||||
location.reload();
|
||||
@@ -70,8 +69,12 @@ async function create_task(){
|
||||
<div class="flex items-center justify-between">
|
||||
<label for="priority" class="block text-sm font-medium leading-6 text-gray-900 dark:text-gray-200">Приоритет</label>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<input v-model="priority" type="number" step="1" id="priority" name="priority" class="px-2 py-1.5 block w-48 rounded-md border-0 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-inset sm:text-sm sm:leading-6" />
|
||||
<div class="mt-2 flex gap-3 ml-2">
|
||||
<Icon @click="priority = 0" :class="[priority === 0 ? 'opacity-100' : 'opacity-50']" class="dark:text-white text-gray-500 cursor-pointer" icon="streamline:signal-none-solid" width="26" height="26"/>
|
||||
<Icon @click="priority = 1" :class="[priority > 0 && priority < 4 ? 'opacity-100' : 'opacity-50']" class="text-orange-300 cursor-pointer" icon="streamline:signal-low-solid" width="26" height="26"/>
|
||||
<Icon @click="priority = 5" :class="[priority >= 4 && priority < 7 ? 'opacity-100' : 'opacity-50']" class="text-amber-500 cursor-pointer" icon="streamline:signal-medium-solid" width="26" height="26"/>
|
||||
<Icon @click="priority = 8" :class="[priority >= 7 && priority < 9 ? 'opacity-100' : 'opacity-50']" class="text-orange-600 cursor-pointer" icon="streamline:signal-full-solid" width="26" height="26"/>
|
||||
<Icon @click="priority = 10" :class="[priority >= 9 ? 'opacity-100' : 'opacity-50']" class="text-red-500 cursor-pointer" icon="heroicons-solid:exclamation" width="32" height="32"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script setup>
|
||||
import {invoke} from "@tauri-apps/api";
|
||||
import {Icon} from "@iconify/vue";
|
||||
import {ref} from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
task_id: String,
|
||||
@@ -10,14 +12,14 @@ const props = defineProps({
|
||||
|
||||
let name = props.task_name;
|
||||
let description = props.task_description;
|
||||
let priority = parseInt(props.task_priority);
|
||||
let priority = ref(parseInt(props.task_priority));
|
||||
|
||||
async function send_edited_task(){
|
||||
await invoke('edit_task', {
|
||||
idTask: props.task_id,
|
||||
name: name,
|
||||
description: description,
|
||||
priority: priority.toString()
|
||||
priority: priority.value.toString()
|
||||
}).then(() => location.reload());
|
||||
}
|
||||
</script>
|
||||
@@ -60,8 +62,12 @@ async function send_edited_task(){
|
||||
<div class="flex items-center justify-between">
|
||||
<label for="priority" class="block text-sm font-medium leading-6 text-gray-900 dark:text-gray-200">Приоритет</label>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<input v-model="priority" type="number" required min="0" max="10" step="1" id="priority" name="priority" class="px-2 py-1.5 block w-48 rounded-md border-0 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-inset sm:text-sm sm:leading-6" />
|
||||
<div class="mt-2 flex gap-3 ml-2">
|
||||
<Icon @click="priority = 0" :class="[priority === 0 ? 'opacity-100' : 'opacity-50']" class="dark:text-white text-gray-500 cursor-pointer" icon="streamline:signal-none-solid" width="26" height="26"/>
|
||||
<Icon @click="priority = 1" :class="[priority > 0 && priority < 4 ? 'opacity-100' : 'opacity-50']" class="text-orange-300 cursor-pointer" icon="streamline:signal-low-solid" width="26" height="26"/>
|
||||
<Icon @click="priority = 5" :class="[priority >= 4 && priority < 7 ? 'opacity-100' : 'opacity-50']" class="text-amber-500 cursor-pointer" icon="streamline:signal-medium-solid" width="26" height="26"/>
|
||||
<Icon @click="priority = 8" :class="[priority >= 7 && priority < 9 ? 'opacity-100' : 'opacity-50']" class="text-orange-600 cursor-pointer" icon="streamline:signal-full-solid" width="26" height="26"/>
|
||||
<Icon @click="priority = 10" :class="[priority >= 9 ? 'opacity-100' : 'opacity-50']" class="text-red-500 cursor-pointer" icon="heroicons-solid:exclamation" width="32" height="32"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user