-
-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
398 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Databases | ||
|
||
## Examples | ||
- [sea-orm](./sea-orm/README.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
[package] | ||
name = "sea-orm-example" | ||
version = "0.1.0" | ||
edition.workspace = true | ||
publish = false | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
viz = { workspace = true, features = ["serve"] } | ||
serde.workspace = true | ||
|
||
tokio = { workspace = true, features = [ "rt-multi-thread", "macros" ] } | ||
sea-orm = { version = "0.12.7", features = ["runtime-tokio-rustls", "sqlx-sqlite"] } | ||
|
||
[lints] | ||
workspace = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Viz SeaOrm example | ||
|
||
UI inspired by: https://github.com/HapticX/happyx/blob/master/examples/todo/README.md | ||
|
||
## USAGE | ||
sqlite use `in-memory`` mode,every time run the app, content reset! | ||
```base | ||
carog run | ||
``` | ||
|
||
## FUNCTION IMPL | ||
|
||
- [x] list | ||
- [x] create | ||
- [x] update | ||
- [ ] delete | ||
|
||
## SCREENSHOT | ||
|
||
![SeaOrm Demo](./sea-orm-demo.gif) | ||
|
||
## FAQ | ||
- libsqlite3 error: you need install libsqlite3 for your system | ||
|
||
- sea-orm doc: https://www.sea-ql.org/sea-orm-tutorial/ch01-00-build-backend-getting-started.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<script src="https://cdn.tailwindcss.com"></script> | ||
<title>Viz SeaOrm Todo Demo</title> | ||
</head> | ||
|
||
<body> | ||
<div class="flex justify-center items-center w-screen h-screen bg-gray-100"> | ||
<div class="flex flex-col gap-4 px-8 py-4 bg-white rounded-2xl drop-shadow-xl"> | ||
<div class="flex justify-between gap-2 items-center"> | ||
<input id="input" maxlength="20" placeholder="Enter task..." type="text" | ||
class="rounded-full bg-gray-100 px-4 py-2 outline-0 border-0"> | ||
<button | ||
class="flex text-xl font-semibold w-10 h-10 justify-center items-center rounded-full cursor-pointer bg-green-300" | ||
id="submit">+</button> | ||
</div> | ||
|
||
<div id="todo-container" class="flex flex-col gap-2"> | ||
</div> | ||
</div> | ||
</div> | ||
</body> | ||
<script> | ||
|
||
var checked_tpl = ` | ||
<div | ||
class="flex gap-2 bg-green-400 rounded-xl px-4 py-2 w-full cursor-pointer select-none transition-all"> | ||
<div class="flex justify-center items-center w-6 h-6 rounded-md outline outline-1 outline-black"> | ||
✔ | ||
</div> | ||
</div> | ||
`; | ||
var unchecked_tpl = ` | ||
<div | ||
class="flex gap-2 bg-red-400 rounded-xl px-4 py-2 w-full cursor-pointer select-none transition-all"> | ||
<div class="flex justify-center items-center w-6 h-6 rounded-md outline outline-1 outline-black"> | ||
❌ | ||
</div> | ||
</div> | ||
` | ||
|
||
var template = { | ||
update: (todos) => { | ||
var todo_container = document.getElementById("todo-container") | ||
todo_container.innerHTML = ""; | ||
todos.forEach(todo => { | ||
if (todo['completed']) { | ||
template.create_div(todo, checked_tpl, todo_container); | ||
} else { | ||
template.create_div(todo, unchecked_tpl, todo_container); | ||
|
||
} | ||
}); | ||
}, | ||
create_div: (todo, html, parent) => { | ||
var div = document.createElement("div"); | ||
div.setAttribute("id", todo['id']); | ||
div.innerHTML = html; | ||
parent.appendChild(div); | ||
var child = document.createElement("div") | ||
child.classList = "flex-1" | ||
child.innerHTML = ` | ||
${todo['text']} | ||
` | ||
|
||
var close_div = document.createElement("div"); | ||
close_div.classList = "text-xs rounded-full bg-gray-100 p-1" | ||
close_div.innerHTML = "❌"; | ||
close_div.addEventListener("click", (event) => { | ||
event.stopPropagation(); | ||
event.preventDefault(); | ||
service.delete(todo['id']); | ||
|
||
}) | ||
var new_el = document.getElementById(todo['id']); | ||
new_el.getElementsByTagName("div")[0] | ||
.appendChild(child); | ||
|
||
new_el.getElementsByTagName("div")[0].appendChild(close_div) | ||
new_el.addEventListener("click", () => { | ||
todo['completed'] = !todo['completed']; | ||
service.update(todo); | ||
}) | ||
} | ||
|
||
} | ||
|
||
var service = { | ||
load: () => { | ||
fetch("/todos") | ||
.then(response => response.json()) | ||
.then(json => { | ||
template.update(json); | ||
}) | ||
.catch(err => console.log('Request Failed', err)); | ||
}, | ||
create: (task) => { | ||
fetch("/todos", { method: "POST", headers: { "Content-Type": "application/json; charset=utf-8" }, body: JSON.stringify(task) }) | ||
.then(response => response.json()) | ||
.then(json => { | ||
service.load(); | ||
}) | ||
.catch(err => console.log('Request Failed', err)); | ||
}, | ||
update: (task) => { | ||
fetch(`/todos/${task['id']}`, { method: "PUT", headers: { "Content-Type": "application/json; charset=utf-8" }, body: JSON.stringify(task) }) | ||
.then(response => response.json()) | ||
.then(json => { | ||
service.load(); | ||
}) | ||
.catch(err => console.log('Request Failed', err)); | ||
}, | ||
delete: (id) => { | ||
fetch(`/todos/${id}`, { method: "DELETE", headers: { "Content-Type": "application/json; charset=utf-8" } }) | ||
.then(response => response.json()) | ||
.then(json => { | ||
service.load(); | ||
}) | ||
.catch(err => console.log('Request Failed', err)); | ||
} | ||
} | ||
document.addEventListener("DOMContentLoaded", () => { | ||
service.load(); | ||
var input = document.getElementById("input"); | ||
|
||
var create_task = () => { | ||
var text = input.value; | ||
if (!text) { | ||
alert("task is empty"); | ||
return; | ||
|
||
} | ||
service.create({ "text": text, "completed": false }); | ||
input.value = "" | ||
} | ||
input.addEventListener("keypress", () => { | ||
if (event.key === "Enter") { | ||
event.preventDefault(); | ||
create_task(); | ||
} | ||
}) | ||
|
||
document.getElementById("submit").addEventListener("click", () => { | ||
create_task() | ||
|
||
}) | ||
}) | ||
</script> | ||
|
||
</html> |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
//! web api mod | ||
use crate::entities::todo::{ActiveModel, Entity as todoEntity, Model as Todo}; | ||
|
||
use sea_orm::{ | ||
ActiveModelTrait, ActiveValue::NotSet, DatabaseConnection, EntityTrait, Set, TryIntoModel, | ||
}; | ||
use viz::{ | ||
types::{Json, Params, State}, | ||
IntoResponse, Request, RequestExt, Response, ResponseExt, Result, | ||
}; | ||
|
||
/// list todos | ||
/// # Errors | ||
/// - `viz::Error` | ||
pub async fn list(mut req: Request) -> Result<Response> { | ||
let State(db) = req.extract::<State<DatabaseConnection>>().await?; | ||
let todos = todoEntity::find() | ||
.all(&db) | ||
.await | ||
.map_err(|err| err.to_string().into_error())?; | ||
Ok(Response::json(todos)?) | ||
} | ||
|
||
/// create todos | ||
/// # Errors | ||
/// - `viz::Error` | ||
pub async fn create(mut req: Request) -> Result<Response> { | ||
let (State(db), Json(todo)) = req | ||
.extract::<(State<DatabaseConnection>, Json<Todo>)>() | ||
.await?; | ||
|
||
let mut todo_am: ActiveModel = todo.into(); | ||
todo_am.id = NotSet; | ||
let result = todo_am | ||
.insert(&db) | ||
.await | ||
.map_err(|err| err.to_string().into_error())?; | ||
let todo_new: Todo = result | ||
.try_into_model() | ||
.map_err(|err| err.to_string().into_error())?; | ||
Ok(Response::json(todo_new)?) | ||
} | ||
|
||
/// update todos | ||
/// PUT /todos/:id | ||
/// # Errors | ||
/// - `viz::Error` | ||
pub async fn update(mut req: Request) -> Result<Response> { | ||
let (State(db), Params(id), Json(todo)) = req | ||
.extract::<(State<DatabaseConnection>, Params<i32>, Json<Todo>)>() | ||
.await?; | ||
let mut todo_am: ActiveModel = todo.clone().into(); | ||
todo_am.id = Set(id); | ||
todo_am.completed = Set(todo.completed); | ||
let model = todo_am | ||
.update(&db) | ||
.await | ||
.map_err(|err| err.to_string().into_error())?; | ||
|
||
Ok(Response::json(model)?) | ||
} | ||
|
||
/// delete todos | ||
/// DELETE /todos/:id | ||
/// # Errors | ||
/// - `viz::Error` | ||
pub async fn delete(mut req: Request) -> Result<Response> { | ||
let (State(db), Params(id)) = req | ||
.extract::<(State<DatabaseConnection>, Params<i32>)>() | ||
.await?; | ||
let delete_result = todoEntity::delete_by_id(id) | ||
.exec(&db) | ||
.await | ||
.map_err(|err| err.to_string().into_error())?; | ||
let rows_affected = delete_result.rows_affected; | ||
Ok(Response::json(rows_affected)?) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
//! db module , init sqlite db | ||
use crate::entities::todo::Entity; | ||
use sea_orm::{ | ||
sea_query::{ColumnDef, SqliteQueryBuilder, Table, TableCreateStatement}, | ||
ConnectionTrait, Database, DatabaseConnection, DbBackend, Schema, | ||
}; | ||
|
||
/// | ||
/// # Errors | ||
/// - `DbErr` | ||
pub async fn init_db() -> Result<DatabaseConnection, Box<dyn std::error::Error>> { | ||
let db = Database::connect("sqlite::memory:").await?; | ||
setup_schema(&db).await; | ||
Ok(db) | ||
} | ||
|
||
/// setup sqlite schema | ||
async fn setup_schema(db: &DatabaseConnection) { | ||
// Setup Schema helper | ||
let schema = Schema::new(DbBackend::Sqlite); | ||
|
||
// Derive from Entity | ||
let stmt: TableCreateStatement = schema.create_table_from_entity(Entity); | ||
|
||
// Or setup manually | ||
assert_eq!( | ||
stmt.build(SqliteQueryBuilder), | ||
Table::create() | ||
.table(Entity) | ||
.col( | ||
ColumnDef::new(<Entity as sea_orm::EntityTrait>::Column::Id) | ||
.primary_key() | ||
.auto_increment() | ||
.integer() | ||
.not_null() | ||
) | ||
.col( | ||
ColumnDef::new(<Entity as sea_orm::EntityTrait>::Column::Text) | ||
.text() | ||
.not_null() | ||
) | ||
.col( | ||
ColumnDef::new(<Entity as sea_orm::EntityTrait>::Column::Completed) | ||
.boolean() | ||
.not_null() | ||
) | ||
//... | ||
.build(SqliteQueryBuilder) | ||
); | ||
|
||
// Execute create table statement | ||
let _ = db.execute(db.get_database_backend().build(&stmt)).await; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
//! sea-orm entities mod | ||
pub mod todo; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
//! todo model | ||
use sea_orm::entity::prelude::*; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
/// | ||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Deserialize, Serialize)] | ||
#[sea_orm(table_name = "todos")] | ||
pub struct Model { | ||
/// | ||
#[sea_orm(primary_key)] | ||
#[serde[skip_deserializing]] | ||
pub id: i32, | ||
/// | ||
pub text: String, | ||
/// | ||
pub completed: bool, | ||
} | ||
/// | ||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] | ||
pub enum Relation {} | ||
|
||
impl ActiveModelBehavior for ActiveModel {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#![deny(warnings)] | ||
//! `SeaOrm` example for Viz framework. | ||
pub mod api; | ||
pub mod db; | ||
pub mod entities; |
Oops, something went wrong.