use migration::{Migrator, MigratorTrait};
use ui_rs::ui;
-use entity::{collection, note, profile};
+use entity::{collection, note, notecontent, profile};
use entity::profile::Entity as Profile;
use entity::collection::{create_notebook_hierarchy, CollectionType, Entity as Collection, Node};
use entity::note::{Entity as Note};
+use entity::notecontent::{Entity as NoteContent};
pub struct Backend {
rt: Arc<Runtime>,
let _ = self.tx.send(cmd);
}
- pub fn save_note<F>(&self, note: entity::note::ActiveModel, callback: F)
- where F: FnOnce(Result<note::ActiveModel, DbErr>) + Send + 'static {
+ pub fn get_note_content<F>(&self, note_id: i32, callback: F)
+ where F: FnOnce(Result<Option<notecontent::Model>, DbErr>) + Send + 'static {
let backend = self.backend.clone();
let cmd = Box::pin(async move {
- let result = note.save(&backend.db).await;
+ let result = NoteContent::find()
+ .filter(notecontent::Column::NoteId.eq(note_id))
+ .order_by_id_asc().one(&backend.db).await;
callback(result);
});
let _ = self.tx.send(cmd);
}
+
+ pub fn save_note<F>(&self, note: note::ActiveModel, content: Option<notecontent::ActiveModel>, callback: F)
+ where F: FnOnce(Result<(i32, i32), DbErr>) + Send + 'static {
+ let backend = self.backend.clone();
+ let cmd = Box::pin(async move {
+ let result = if note.note_id.is_set() {
+ note.update(&backend.db).await
+ } else {
+ note.insert(&backend.db).await
+ };
+
+ match result {
+ Ok(note) => {
+ let note_id = note.note_id;
+ if let Some(content) = content {
+ let result2 = if content.id.is_set() {
+ content.update(&backend.db).await
+ } else {
+ content.insert(&backend.db).await
+ };
+
+ match result2 {
+ Ok(ctn) => {
+ callback(Ok((note_id, ctn.id)));
+ }
+ Err(e) => {
+ callback(Err(e));
+ }
+ }
+ } else {
+ callback(Ok((note_id, 0)));
+ }
+ },
+ Err(e) => {
+ callback(Err(e));
+ }
+ }
+ });
+ let _ = self.tx.send(cmd);
+ }
}
#[derive(UiModel, Default)]
pub struct Note {
pub note_id: i32,
+ pub content_id: i32,
pub kind: NoteType,
pub created: DateTimeWithTimeZone,
impl Note {
pub fn init_from_model(&mut self, model: &entity::note::Model) {
self.note_id = model.note_id;
- self.text.set(model.content.as_str());
let tab = match model.kind {
NoteType::PlainTextNote => NoteTypeTabView::TextArea,
};
self.note_type.set(tab as i64);
}
+
+ pub fn init_content(&mut self, content: &entity::notecontent::Model) {
+ self.content_id = content.id;
+ self.text.set(content.content.as_str());
+ }
pub fn save(&self, collection_id: i32, backend: &BackendHandle) {
let content = self.text.get();
None => "Note".to_string()
};
+ let note_id = if self.note_id == 0 { NotSet } else { Set(self.note_id) };
+
let note = entity::note::ActiveModel {
- note_id: if self.note_id == 0 { NotSet } else { Set(self.note_id) },
+ note_id: note_id.clone(),
collection_id: Set(collection_id),
kind: Set(self.kind.clone()),
title: Set(title),
- content: Set(content),
lastmodified: Set(Utc::now().into()),
created: if self.note_id == 0 { Set(Utc::now().into()) } else { NotSet }
};
- backend.save_note(note, |result|{
+ let notecontent = entity::notecontent::ActiveModel {
+ id: if self.content_id == 0 { NotSet } else { Set(self.content_id) },
+ note_id: note_id,
+ content: Set(content),
+ };
+
+ backend.save_note(note, Some(notecontent), |result|{
match result {
- Ok(model) => {
+ Ok(_model) => {
println!("Note saved");
},
Err(error) => {
let note_proxy = current.doc_proxy();
let backend = self.backend.clone();
let collection_id = self.collection_id;
- note_proxy.call_mainthread(move |doc, note|{
+ note_proxy.call_mainthread(move |_doc, note|{
note.save(collection_id, &backend);
});
}
n.init_from_model(¬e);
+
+ let proxy = d.doc_proxy();
+ self.backend.get_note_content(note.note_id, move|result|{
+ proxy.call_mainthread(|doc, note|{
+ match result {
+ Ok(content) => {
+ if let Some(content) = content {
+ note.init_content(&content);
+ } else {
+ println!("note {}: no content", note.note_id);
+ }
+ },
+ Err(e) => {
+ println!("Cannot get note content: {}", e);
+ }
+ }
+ });
+ });
});
// Attach the new note
}
}
-pub fn note_getvalue<'a>(elm: &Note, col: i32, _row: i32) -> ListValue<'a> {
+pub fn notelist_getvalue<'a>(elm: &Note, col: i32, _row: i32) -> ListValue<'a> {
match col {
0 => ListValue::String(elm.title.clone()),
1 => ListValue::String(elm.lastmodified.to_string()),
use entity::note::Model as Note;
use crate::backend::{BackendHandle, BroadcastMessage};
use crate::newnotebook::new_notebook_dialog;
-use crate::notebook::{note_getvalue, Notebook};
+use crate::notebook::{notelist_getvalue, Notebook};
#[derive(UiModel)]
pub struct MainWindow {
notebooks: UiSourceList<Collection>
}
-impl Drop for MainWindow {
- fn drop(&mut self) {
- println!("MainWindow dropped!");
- }
-}
#[ui_actions]
impl MainWindow {
.varname("notes")
.model(&model)
.fill(true)
- .getvalue(note_getvalue)
+ .getvalue(notelist_getvalue)
.onselection_action("note_selected")
.create();
});
mod prelude;
pub mod profile;
pub mod collection;
-pub mod note;
\ No newline at end of file
+pub mod note;
+pub mod notecontent;
\ No newline at end of file
use sea_orm::entity::prelude::*;
+#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "note")]
pub struct Model {
pub kind: NoteType,
pub title: String,
- pub content: String,
pub lastmodified: DateTimeWithTimeZone,
pub created: DateTimeWithTimeZone,
+
+ #[sea_orm(has_one)]
+ pub content: HasOne<crate::notecontent::Entity>
}
#[derive(EnumIter, DeriveActiveEnum, Clone, Debug, PartialEq, Default)]
MDTextNote = 1,
}
-#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
-pub enum Relation {}
-
impl ActiveModelBehavior for ActiveModel {}
--- /dev/null
+use sea_orm::entity::prelude::*;
+
+use sea_orm::{ActiveModelBehavior, DeriveEntityModel, DeriveRelation, EnumIter};
+
+#[sea_orm::model]
+#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
+#[sea_orm(table_name = "note_content")]
+pub struct Model {
+ #[sea_orm(primary_key)]
+ pub id: i32,
+
+ #[sea_orm(unique)]
+ pub note_id: i32,
+
+ pub content: String,
+
+ #[sea_orm(belongs_to, from = "note_id", to = "note_id")]
+ pub note: HasOne<crate::note::Entity>
+}
+
+impl ActiveModelBehavior for ActiveModel {}
.col(integer("collection_id"))
.col(integer("kind"))
.col(string("title"))
- .col(string_null("content"))
.col(timestamp_with_time_zone("lastmodified"))
.col(timestamp_with_time_zone("created"))
.to_owned()
- ).await
+ ).await?;
+
+ manager
+ .create_table(
+ Table::create()
+ .table("note_content")
+ .if_not_exists()
+ .col(integer("id").primary_key())
+ .col(integer("note_id").unique_key())
+ .col(string("content"))
+ .foreign_key(
+ ForeignKey::create()
+ .name("fk-note_content-note")
+ .from("note_content", "note_id")
+ .to("note", "note_id")
+ .on_delete(ForeignKeyAction::Cascade),
+ )
+ .to_owned(),
+ )
+ .await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
+ manager
+ .drop_table(Table::drop().table("note_content").to_owned()).await?;
manager
.drop_table(Table::drop().table("note").to_owned()).await?;
manager
cxListClear(ctx->states);
cxListClear(ctx->state_widgets);
cxListClear(ctx->action_bindings);
+ uic_context_detach_all(ctx);
}
void uic_context_destroy(UiContext *ctx, void *document) {