update
This commit is contained in:
parent
791349a2c4
commit
e0b7ebedac
12 changed files with 128 additions and 88 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -3630,6 +3630,7 @@ dependencies = [
|
||||||
"tauri-plugin-single-instance",
|
"tauri-plugin-single-instance",
|
||||||
"tauri-plugin-window-state",
|
"tauri-plugin-window-state",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3674,6 +3675,7 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower",
|
"tower",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
|
"tracing-subscriber",
|
||||||
"utoipa",
|
"utoipa",
|
||||||
"utoipa-scalar",
|
"utoipa-scalar",
|
||||||
"utoipa-swagger-ui",
|
"utoipa-swagger-ui",
|
||||||
|
@ -6038,6 +6040,7 @@ dependencies = [
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -29,6 +29,7 @@ tauri-plugin-shell = "2.0.0-beta.7"
|
||||||
tauri-plugin-single-instance = "2.0.0-beta.9"
|
tauri-plugin-single-instance = "2.0.0-beta.9"
|
||||||
tauri-plugin-window-state = "2.0.0-beta"
|
tauri-plugin-window-state = "2.0.0-beta"
|
||||||
tokio = { version = "1.38.0", features = ["full"] }
|
tokio = { version = "1.38.0", features = ["full"] }
|
||||||
|
tracing-subscriber = "0.3.18"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!!
|
# This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!!
|
||||||
|
|
|
@ -18,6 +18,7 @@ enum Command {
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
tracing_subscriber::fmt::init();
|
||||||
let opt = Opt::parse();
|
let opt = Opt::parse();
|
||||||
|
|
||||||
match opt.command {
|
match opt.command {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { parse as parseDate, format as formatDate } from "date-fns";
|
||||||
import { useDebounce } from "use-debounce";
|
import { useDebounce } from "use-debounce";
|
||||||
|
|
||||||
const JOURNAL_PAGE_CONTENT_FIELD_NAME = "panorama/journal/page/content";
|
const JOURNAL_PAGE_CONTENT_FIELD_NAME = "panorama/journal/page/content";
|
||||||
|
const JOURNAL_PAGE_TITLE_FIELD_NAME = "panorama/journal/page/title";
|
||||||
|
|
||||||
export interface JournalPageProps {
|
export interface JournalPageProps {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -33,44 +34,41 @@ export default function JournalPage({ id, data }: JournalPageProps) {
|
||||||
const previous = usePrevious(valueToSave);
|
const previous = usePrevious(valueToSave);
|
||||||
const changed = valueToSave !== previous;
|
const changed = valueToSave !== previous;
|
||||||
const [mode, setMode] = useState<PreviewType>("preview");
|
const [mode, setMode] = useState<PreviewType>("preview");
|
||||||
const [title, setTitle] = useState(() => data.title);
|
const [title, setTitle] = useState(
|
||||||
|
() => data?.fields?.[JOURNAL_PAGE_TITLE_FIELD_NAME],
|
||||||
|
);
|
||||||
const [isEditingTitle, setIsEditingTitle] = useState(false);
|
const [isEditingTitle, setIsEditingTitle] = useState(false);
|
||||||
|
|
||||||
|
const saveData = useCallback(async () => {
|
||||||
|
const extra_data = {
|
||||||
|
[JOURNAL_PAGE_TITLE_FIELD_NAME]: title,
|
||||||
|
[JOURNAL_PAGE_CONTENT_FIELD_NAME]: valueToSave,
|
||||||
|
};
|
||||||
|
console.log("extra Data", extra_data);
|
||||||
|
const resp = await fetch(`http://localhost:5195/node/${id}`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ extra_data }),
|
||||||
|
});
|
||||||
|
const data = await resp.text();
|
||||||
|
console.log("result", data);
|
||||||
|
}, [title, valueToSave, id]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (changed) {
|
if (changed) {
|
||||||
(async () => {
|
(async () => {
|
||||||
console.log("Saving...");
|
await saveData();
|
||||||
const resp = await fetch(`http://localhost:5195/node/${id}`, {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
extra_data: {
|
|
||||||
"panorama/journal/page/content": valueToSave,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
const data = await resp.text();
|
|
||||||
console.log("result", data);
|
|
||||||
|
|
||||||
queryClient.invalidateQueries({ queryKey: ["fetchNode", id] });
|
queryClient.invalidateQueries({ queryKey: ["fetchNode", id] });
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
}, [id, changed, valueToSave, queryClient]);
|
}, [changed, queryClient, saveData]);
|
||||||
|
|
||||||
const saveChangedTitle = useCallback(() => {
|
const saveChangedTitle = useCallback(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const resp = await fetch(`http://localhost:5195/node/${id}`, {
|
await saveData();
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ title: title }),
|
|
||||||
});
|
|
||||||
setIsEditingTitle(false);
|
setIsEditingTitle(false);
|
||||||
})();
|
})();
|
||||||
}, [title, id]);
|
}, [saveData]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -10,7 +10,7 @@ chrono = { version = "0.4.38", features = ["serde"] }
|
||||||
cozo = { version = "0.7.6", features = ["storage-rocksdb"] }
|
cozo = { version = "0.7.6", features = ["storage-rocksdb"] }
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
itertools = "0.13.0"
|
itertools = "0.13.0"
|
||||||
miette = "5.5.0"
|
miette = { version = "5.5.0", features = ["fancy", "backtrace"] }
|
||||||
serde = { version = "1.0.203", features = ["derive"] }
|
serde = { version = "1.0.203", features = ["derive"] }
|
||||||
serde_json = "1.0.117"
|
serde_json = "1.0.117"
|
||||||
sugars = "3.0.1"
|
sugars = "3.0.1"
|
||||||
|
|
|
@ -107,7 +107,6 @@ fn migration_01(db: &DbInstance) -> Result<()> {
|
||||||
id: String
|
id: String
|
||||||
=>
|
=>
|
||||||
type: String,
|
type: String,
|
||||||
title: String? default null,
|
|
||||||
created_at: Float default now(),
|
created_at: Float default now(),
|
||||||
updated_at: Float default now(),
|
updated_at: Float default now(),
|
||||||
extra_data: Json default {},
|
extra_data: Json default {},
|
||||||
|
@ -131,6 +130,8 @@ fn migration_01(db: &DbInstance) -> Result<()> {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
?[key, relation, field_name, type, is_fts_enabled] <- [
|
?[key, relation, field_name, type, is_fts_enabled] <- [
|
||||||
|
['panorama/journal/page/day', 'journal_day', 'day', 'string', false],
|
||||||
|
['panorama/journal/page/title', 'journal', 'title', 'string', true],
|
||||||
['panorama/journal/page/content', 'journal', 'content', 'string', true],
|
['panorama/journal/page/content', 'journal', 'content', 'string', true],
|
||||||
['panorama/mail/config/imap_hostname', 'mail_config', 'imap_hostname', 'string', false],
|
['panorama/mail/config/imap_hostname', 'mail_config', 'imap_hostname', 'string', false],
|
||||||
['panorama/mail/config/imap_port', 'mail_config', 'imap_port', 'int', false],
|
['panorama/mail/config/imap_port', 'mail_config', 'imap_port', 'int', false],
|
||||||
|
@ -138,13 +139,13 @@ fn migration_01(db: &DbInstance) -> Result<()> {
|
||||||
['panorama/mail/config/imap_password', 'mail_config', 'imap_password', 'string', false],
|
['panorama/mail/config/imap_password', 'mail_config', 'imap_password', 'string', false],
|
||||||
['panorama/mail/message/body', 'message', 'body', 'string', true],
|
['panorama/mail/message/body', 'message', 'body', 'string', true],
|
||||||
['panorama/mail/message/subject', 'message', 'subject', 'string', true],
|
['panorama/mail/message/subject', 'message', 'subject', 'string', true],
|
||||||
['panorama/mail/message/message_id', 'message', 'message_id', 'string', true],
|
['panorama/mail/message/message_id', 'message', 'message_id', 'string', false],
|
||||||
]
|
]
|
||||||
:put fqkey_to_dbkey { key, relation, field_name, type, is_fts_enabled }
|
:put fqkey_to_dbkey { key, relation, field_name, type, is_fts_enabled }
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create journal type
|
# Create journal type
|
||||||
{ :create journal { node_id: String => content: String } }
|
{ :create journal { node_id: String => title: String default '', content: String } }
|
||||||
{ :create journal_day { day: String => node_id: String } }
|
{ :create journal_day { day: String => node_id: String } }
|
||||||
|
|
||||||
# Mail
|
# Mail
|
||||||
|
|
|
@ -7,13 +7,15 @@ use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{AppState, NodeId};
|
use crate::{AppState, NodeId};
|
||||||
|
|
||||||
|
use super::node::CreateOrUpdate;
|
||||||
|
|
||||||
impl AppState {
|
impl AppState {
|
||||||
pub async fn get_todays_journal_id(&self) -> Result<NodeId> {
|
pub async fn get_todays_journal_id(&self) -> Result<NodeId> {
|
||||||
let today = todays_date();
|
let today = todays_date();
|
||||||
|
|
||||||
let result = self.db.run_script(
|
let result = self.db.run_script(
|
||||||
"
|
"
|
||||||
?[node_id] := *journal_day[day, node_id], day = $day
|
?[node_id] := *journal_day{day, node_id}, day = $day
|
||||||
",
|
",
|
||||||
btmap! {
|
btmap! {
|
||||||
"day".to_owned() => today.clone().into(),
|
"day".to_owned() => today.clone().into(),
|
||||||
|
@ -24,33 +26,46 @@ impl AppState {
|
||||||
// TODO: Do this check on the server side
|
// TODO: Do this check on the server side
|
||||||
if result.rows.len() == 0 {
|
if result.rows.len() == 0 {
|
||||||
// Insert a new one
|
// Insert a new one
|
||||||
let uuid = Uuid::now_v7();
|
// let uuid = Uuid::now_v7();
|
||||||
let node_id = uuid.to_string();
|
// let node_id = uuid.to_string();
|
||||||
|
|
||||||
self.db.run_script(
|
let node_info = self
|
||||||
"
|
.create_or_update_node(
|
||||||
{
|
CreateOrUpdate::Create {
|
||||||
?[id, title, type] <- [[$node_id, $title, 'panorama/journal/page']]
|
r#type: "panorama/journal/page".to_owned(),
|
||||||
:put node { id, title, type }
|
|
||||||
}
|
|
||||||
{
|
|
||||||
?[node_id, content] <- [[$node_id, '']]
|
|
||||||
:put journal { node_id => content }
|
|
||||||
}
|
|
||||||
{
|
|
||||||
?[day, node_id] <- [[$day, $node_id]]
|
|
||||||
:put journal_day { day => node_id }
|
|
||||||
}
|
|
||||||
",
|
|
||||||
btmap! {
|
|
||||||
"node_id".to_owned() => node_id.clone().into(),
|
|
||||||
"day".to_owned() => today.clone().into(),
|
|
||||||
"title".to_owned() => today.clone().into(),
|
|
||||||
},
|
},
|
||||||
ScriptMutability::Mutable,
|
Some(btmap! {
|
||||||
)?;
|
"panorama/journal/page/day".to_owned() => today.clone().into(),
|
||||||
|
"panorama/journal/page/content".to_owned() => "".to_owned().into(),
|
||||||
|
"panorama/journal/page/title".to_owned() => today.clone().into(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
return Ok(NodeId(uuid));
|
// self.db.run_script(
|
||||||
|
// "
|
||||||
|
// {
|
||||||
|
// ?[id, type] <- [[$node_id, 'panorama/journal/page']]
|
||||||
|
// :put node { id, type }
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// ?[node_id, title, content] <- [[$node_id, $title, '']]
|
||||||
|
// :put journal { node_id => title, content }
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// ?[day, node_id] <- [[$day, $node_id]]
|
||||||
|
// :put journal_day { day => node_id }
|
||||||
|
// }
|
||||||
|
// ",
|
||||||
|
// btmap! {
|
||||||
|
// "node_id".to_owned() => node_id.clone().into(),
|
||||||
|
// "day".to_owned() => today.clone().into(),
|
||||||
|
// "title".to_owned() => today.clone().into(),
|
||||||
|
// },
|
||||||
|
// ScriptMutability::Mutable,
|
||||||
|
// )?;
|
||||||
|
|
||||||
|
return Ok(node_info.node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
let node_id = result.rows[0][0].get_str().unwrap();
|
let node_id = result.rows[0][0].get_str().unwrap();
|
||||||
|
|
|
@ -12,7 +12,7 @@ use tantivy::{
|
||||||
collector::TopDocs,
|
collector::TopDocs,
|
||||||
query::QueryParser,
|
query::QueryParser,
|
||||||
schema::{OwnedValue, Value as _},
|
schema::{OwnedValue, Value as _},
|
||||||
Document, TantivyDocument,
|
Document, TantivyDocument, Term,
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ pub struct NodeInfo {
|
||||||
pub fields: Option<HashMap<String, Value>>,
|
pub fields: Option<HashMap<String, Value>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct FieldInfo {
|
pub struct FieldInfo {
|
||||||
pub relation_name: String,
|
pub relation_name: String,
|
||||||
pub relation_field: String,
|
pub relation_field: String,
|
||||||
|
@ -157,6 +158,7 @@ impl AppState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum CreateOrUpdate {
|
pub enum CreateOrUpdate {
|
||||||
Create { r#type: String },
|
Create { r#type: String },
|
||||||
Update { node_id: NodeId },
|
Update { node_id: NodeId },
|
||||||
|
@ -175,10 +177,17 @@ impl AppState {
|
||||||
};
|
};
|
||||||
let node_id = node_id.to_string();
|
let node_id = node_id.to_string();
|
||||||
|
|
||||||
|
let action = match opts {
|
||||||
|
CreateOrUpdate::Create { .. } => "put",
|
||||||
|
CreateOrUpdate::Update { .. } => "update",
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("Request: {opts:?} {extra_data:?}");
|
||||||
|
|
||||||
let tx = self.db.multi_transaction(true);
|
let tx = self.db.multi_transaction(true);
|
||||||
|
|
||||||
let (created_at, updated_at) = match opts {
|
let (created_at, updated_at) = match opts {
|
||||||
CreateOrUpdate::Create { r#type } => {
|
CreateOrUpdate::Create { ref r#type } => {
|
||||||
let node_result = tx.run_script(
|
let node_result = tx.run_script(
|
||||||
"
|
"
|
||||||
?[id, type] <- [[$node_id, $type]]
|
?[id, type] <- [[$node_id, $type]]
|
||||||
|
@ -187,16 +196,15 @@ impl AppState {
|
||||||
",
|
",
|
||||||
btmap! {
|
btmap! {
|
||||||
"node_id".to_owned() => DataValue::from(node_id.clone()),
|
"node_id".to_owned() => DataValue::from(node_id.clone()),
|
||||||
"type".to_owned() => DataValue::from(r#type),
|
"type".to_owned() => DataValue::from(r#type.to_owned()),
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
println!("ROWS(1): {:?}", node_result);
|
|
||||||
let created_at = DateTime::from_timestamp_millis(
|
let created_at = DateTime::from_timestamp_millis(
|
||||||
(node_result.rows[0][4].get_float().unwrap() * 1000.0) as i64,
|
(node_result.rows[0][3].get_float().unwrap() * 1000.0) as i64,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let updated_at = DateTime::from_timestamp_millis(
|
let updated_at = DateTime::from_timestamp_millis(
|
||||||
(node_result.rows[0][5].get_float().unwrap() * 1000.0) as i64,
|
(node_result.rows[0][4].get_float().unwrap() * 1000.0) as i64,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
(created_at, updated_at)
|
(created_at, updated_at)
|
||||||
|
@ -211,7 +219,6 @@ impl AppState {
|
||||||
"node_id".to_owned() => DataValue::from(node_id.clone()),
|
"node_id".to_owned() => DataValue::from(node_id.clone()),
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
println!("ROWS(2): {:?}", node_result);
|
|
||||||
let created_at = DateTime::from_timestamp_millis(
|
let created_at = DateTime::from_timestamp_millis(
|
||||||
(node_result.rows[0][2].get_float().unwrap() * 1000.0) as i64,
|
(node_result.rows[0][2].get_float().unwrap() * 1000.0) as i64,
|
||||||
)
|
)
|
||||||
|
@ -230,6 +237,7 @@ impl AppState {
|
||||||
.get_by_left("node_id")
|
.get_by_left("node_id")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
if !extra_data.is_empty() {
|
if !extra_data.is_empty() {
|
||||||
let keys = extra_data.keys().map(|s| s.to_owned()).collect::<Vec<_>>();
|
let keys = extra_data.keys().map(|s| s.to_owned()).collect::<Vec<_>>();
|
||||||
let field_mapping =
|
let field_mapping =
|
||||||
|
@ -279,6 +287,11 @@ impl AppState {
|
||||||
|
|
||||||
let mut writer =
|
let mut writer =
|
||||||
self.tantivy_index.writer(15_000_000).into_diagnostic()?;
|
self.tantivy_index.writer(15_000_000).into_diagnostic()?;
|
||||||
|
|
||||||
|
let delete_term =
|
||||||
|
Term::from_field_text(node_id_field.clone(), &node_id);
|
||||||
|
writer.delete_term(delete_term);
|
||||||
|
|
||||||
writer.add_document(doc).into_diagnostic()?;
|
writer.add_document(doc).into_diagnostic()?;
|
||||||
writer.commit().into_diagnostic()?;
|
writer.commit().into_diagnostic()?;
|
||||||
drop(writer);
|
drop(writer);
|
||||||
|
@ -286,10 +299,11 @@ impl AppState {
|
||||||
let keys = fields_mapping.keys().collect::<Vec<_>>();
|
let keys = fields_mapping.keys().collect::<Vec<_>>();
|
||||||
let keys_joined = keys.iter().join(", ");
|
let keys_joined = keys.iter().join(", ");
|
||||||
|
|
||||||
|
if !keys.is_empty() {
|
||||||
let query = format!(
|
let query = format!(
|
||||||
"
|
"
|
||||||
?[ node_id, {keys_joined} ] <- [$input_data]
|
?[ node_id, {keys_joined} ] <- [$input_data]
|
||||||
:put {relation} {{ node_id, {keys_joined} }}
|
:{action} {relation} {{ node_id, {keys_joined} }}
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -299,14 +313,13 @@ impl AppState {
|
||||||
params.push(fields_mapping[key].clone());
|
params.push(fields_mapping[key].clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Query: {:?} \n {:?}", query, params);
|
|
||||||
|
|
||||||
let result = tx.run_script(
|
let result = tx.run_script(
|
||||||
&query,
|
&query,
|
||||||
btmap! {
|
btmap! {
|
||||||
"input_data".to_owned() => DataValue::List(params),
|
"input_data".to_owned() => DataValue::List(params),
|
||||||
},
|
},
|
||||||
)?;
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let input = DataValue::List(
|
let input = DataValue::List(
|
||||||
|
@ -320,6 +333,7 @@ impl AppState {
|
||||||
})
|
})
|
||||||
.collect_vec(),
|
.collect_vec(),
|
||||||
);
|
);
|
||||||
|
|
||||||
tx.run_script(
|
tx.run_script(
|
||||||
"
|
"
|
||||||
?[key, id] <- $input_data
|
?[key, id] <- $input_data
|
||||||
|
|
|
@ -14,7 +14,7 @@ csv = "1.3.0"
|
||||||
dirs = "5.0.1"
|
dirs = "5.0.1"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
itertools = "0.13.0"
|
itertools = "0.13.0"
|
||||||
miette = "5.5.0"
|
miette = { version = "5.5.0", features = ["fancy", "backtrace"] }
|
||||||
panorama-core = { path = "../panorama-core" }
|
panorama-core = { path = "../panorama-core" }
|
||||||
serde = { version = "1.0.202", features = ["derive"] }
|
serde = { version = "1.0.202", features = ["derive"] }
|
||||||
serde_json = "1.0.117"
|
serde_json = "1.0.117"
|
||||||
|
@ -22,7 +22,8 @@ sugars = "3.0.1"
|
||||||
tantivy = { version = "0.22.0", features = ["zstd"] }
|
tantivy = { version = "0.22.0", features = ["zstd"] }
|
||||||
tokio = { version = "1.37.0", features = ["full"] }
|
tokio = { version = "1.37.0", features = ["full"] }
|
||||||
tower = "0.4.13"
|
tower = "0.4.13"
|
||||||
tower-http = { version = "0.5.2", features = ["cors"] }
|
tower-http = { version = "0.5.2", features = ["cors", "trace"] }
|
||||||
|
tracing-subscriber = "0.3.18"
|
||||||
uuid = { version = "1.8.0", features = ["v7"] }
|
uuid = { version = "1.8.0", features = ["v7"] }
|
||||||
|
|
||||||
[dependencies.utoipa]
|
[dependencies.utoipa]
|
||||||
|
|
|
@ -20,7 +20,10 @@ use miette::{IntoDiagnostic, Result};
|
||||||
use panorama_core::AppState;
|
use panorama_core::AppState;
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
use tower::ServiceBuilder;
|
use tower::ServiceBuilder;
|
||||||
use tower_http::cors::{self, CorsLayer};
|
use tower_http::{
|
||||||
|
cors::{self, CorsLayer},
|
||||||
|
trace::TraceLayer,
|
||||||
|
};
|
||||||
use utoipa::OpenApi;
|
use utoipa::OpenApi;
|
||||||
use utoipa_scalar::{Scalar, Servable};
|
use utoipa_scalar::{Scalar, Servable};
|
||||||
|
|
||||||
|
@ -47,11 +50,13 @@ pub async fn run() -> Result<()> {
|
||||||
|
|
||||||
let state = AppState::new(&panorama_dir).await?;
|
let state = AppState::new(&panorama_dir).await?;
|
||||||
|
|
||||||
let cors = CorsLayer::new()
|
let cors_layer = CorsLayer::new()
|
||||||
.allow_methods([Method::GET, Method::POST, Method::PUT])
|
.allow_methods([Method::GET, Method::POST, Method::PUT])
|
||||||
.allow_headers(cors::Any)
|
.allow_headers(cors::Any)
|
||||||
.allow_origin(cors::Any);
|
.allow_origin(cors::Any);
|
||||||
|
|
||||||
|
let trace_layer = TraceLayer::new_for_http();
|
||||||
|
|
||||||
// build our application with a single route
|
// build our application with a single route
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.merge(Scalar::with_url("/api/docs", ApiDoc::openapi()))
|
.merge(Scalar::with_url("/api/docs", ApiDoc::openapi()))
|
||||||
|
@ -61,7 +66,8 @@ pub async fn run() -> Result<()> {
|
||||||
.nest("/journal", journal::router().with_state(state.clone()))
|
.nest("/journal", journal::router().with_state(state.clone()))
|
||||||
.route("/mail/config", get(get_mail_config))
|
.route("/mail/config", get(get_mail_config))
|
||||||
.route("/mail", get(get_mail))
|
.route("/mail", get(get_mail))
|
||||||
.layer(ServiceBuilder::new().layer(cors))
|
.layer(ServiceBuilder::new().layer(cors_layer))
|
||||||
|
.layer(ServiceBuilder::new().layer(trace_layer))
|
||||||
.with_state(state.clone());
|
.with_state(state.clone());
|
||||||
|
|
||||||
let listener = TcpListener::bind("0.0.0.0:5195").await.into_diagnostic()?;
|
let listener = TcpListener::bind("0.0.0.0:5195").await.into_diagnostic()?;
|
||||||
|
|
|
@ -2,6 +2,7 @@ use miette::Result;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
|
tracing_subscriber::fmt::init();
|
||||||
panorama_daemon::run().await?;
|
panorama_daemon::run().await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,6 @@ pub async fn get_node(
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct UpdateData {
|
pub struct UpdateData {
|
||||||
title: Option<String>,
|
|
||||||
extra_data: Option<ExtraData>,
|
extra_data: Option<ExtraData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue