-
-
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.
Merge branch 'main' into htmlx-example
- Loading branch information
Showing
42 changed files
with
553 additions
and
69 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
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 |
---|---|---|
@@ -1 +1,2 @@ | ||
msrv = "1.64" | ||
# Clippy configuration | ||
# https://doc.rust-lang.org/nightly/clippy/lint_configuration.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,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)?) | ||
} |
Oops, something went wrong.