add: movie input, refactor things, and fix vscode config
This commit is contained in:
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"rust-analyzer.cargo.features": ["ssr"]
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ leptos_axum = { version = "0.7.0", optional = true }
|
|||||||
leptos_meta = { version = "0.7.0" }
|
leptos_meta = { version = "0.7.0" }
|
||||||
tokio = { version = "1", features = ["rt-multi-thread"], optional = true }
|
tokio = { version = "1", features = ["rt-multi-thread"], optional = true }
|
||||||
wasm-bindgen = { version = "=0.2.100", optional = true }
|
wasm-bindgen = { version = "=0.2.100", optional = true }
|
||||||
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
hydrate = [
|
hydrate = [
|
||||||
|
|||||||
35
src/app.rs
35
src/app.rs
@@ -1,9 +1,12 @@
|
|||||||
use leptos::{prelude::*, task::spawn_local};
|
use leptos::prelude::*;
|
||||||
use leptos_meta::{provide_meta_context, MetaTags, Stylesheet, Title};
|
use leptos_meta::{provide_meta_context, MetaTags, Stylesheet, Title};
|
||||||
use leptos_router::{
|
use leptos_router::{
|
||||||
components::{Route, Router, Routes},
|
components::{Route, Router, Routes},
|
||||||
StaticSegment,
|
StaticSegment,
|
||||||
};
|
};
|
||||||
|
use movies::Movies;
|
||||||
|
|
||||||
|
mod movies;
|
||||||
|
|
||||||
pub fn shell(options: LeptosOptions) -> impl IntoView {
|
pub fn shell(options: LeptosOptions) -> impl IntoView {
|
||||||
view! {
|
view! {
|
||||||
@@ -25,21 +28,18 @@ pub fn shell(options: LeptosOptions) -> impl IntoView {
|
|||||||
|
|
||||||
#[server]
|
#[server]
|
||||||
pub async fn load_counter() -> Result<usize, ServerFnError> {
|
pub async fn load_counter() -> Result<usize, ServerFnError> {
|
||||||
use tokio::sync::Mutex;
|
use crate::common::Context;
|
||||||
use std::sync::Arc;
|
let data = use_context::<Context>().unwrap();
|
||||||
let data = use_context::<Arc<Mutex<usize>>>().unwrap();
|
let data = data.counter.lock().await;
|
||||||
let mut data = data.lock().await;
|
|
||||||
Ok(*data)
|
Ok(*data)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[server]
|
#[server]
|
||||||
pub async fn increment_counter() -> Result<usize, ServerFnError> {
|
pub async fn increment_counter() -> Result<usize, ServerFnError> {
|
||||||
use tokio::sync::Mutex;
|
use crate::common::Context;
|
||||||
use std::sync::Arc;
|
let data = use_context::<Context>().unwrap();
|
||||||
let data = use_context::<Arc<Mutex<usize>>>().unwrap();
|
let mut data = data.counter.lock().await;
|
||||||
let mut data = data.lock().await;
|
|
||||||
*data += 1;
|
*data += 1;
|
||||||
println!("Counter {}", *data);
|
|
||||||
Ok(*data)
|
Ok(*data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,12 +72,8 @@ pub fn App() -> impl IntoView {
|
|||||||
fn HomePage() -> impl IntoView {
|
fn HomePage() -> impl IntoView {
|
||||||
let increment_counter = ServerAction::<IncrementCounter>::new();
|
let increment_counter = ServerAction::<IncrementCounter>::new();
|
||||||
let counts = Resource::new(
|
let counts = Resource::new(
|
||||||
move || {
|
move || (increment_counter.version().get(),),
|
||||||
(
|
move |_| load_counter(),
|
||||||
increment_counter.version().get(),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
move |_| load_counter()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let existing_counter = move || {
|
let existing_counter = move || {
|
||||||
@@ -87,12 +83,13 @@ fn HomePage() -> impl IntoView {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let onclick = move |ev| {
|
let onclick = move |_| {
|
||||||
increment_counter.dispatch(IncrementCounter{});
|
increment_counter.dispatch(IncrementCounter {});
|
||||||
};
|
};
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<h1>"Welcome to Leptos!"</h1>
|
<h1>"Welcome to Wiseau movie picker"</h1>
|
||||||
|
<Movies></Movies>
|
||||||
<button on:click=onclick>"Click Me: "
|
<button on:click=onclick>"Click Me: "
|
||||||
<Transition fallback=move || view! { <p>"Loading..."</p> }>
|
<Transition fallback=move || view! { <p>"Loading..."</p> }>
|
||||||
{existing_counter}
|
{existing_counter}
|
||||||
|
|||||||
52
src/app/movies.rs
Normal file
52
src/app/movies.rs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
use leptos::prelude::*;
|
||||||
|
|
||||||
|
use crate::model::Movie;
|
||||||
|
|
||||||
|
#[server]
|
||||||
|
pub async fn load_movies() -> Result<Vec<Movie>, ServerFnError> {
|
||||||
|
use crate::common::Context;
|
||||||
|
let data = use_context::<Context>().unwrap();
|
||||||
|
let movies = data.movies.lock().await.clone();
|
||||||
|
Ok(movies)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[server]
|
||||||
|
pub async fn add_movie(name: String) -> Result<(), ServerFnError> {
|
||||||
|
use crate::common::Context;
|
||||||
|
let data = use_context::<Context>().unwrap();
|
||||||
|
let mut data = data.movies.lock().await;
|
||||||
|
data.push(Movie::new(&name));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Renders the home page of your application.
|
||||||
|
#[component]
|
||||||
|
pub fn Movies() -> impl IntoView {
|
||||||
|
let add_movie = ServerMultiAction::<AddMovie>::new();
|
||||||
|
let movies_resource =
|
||||||
|
Resource::new(move || (add_movie.version().get(),), move |_| load_movies());
|
||||||
|
let movies = move || {
|
||||||
|
Suspend::new(async move {
|
||||||
|
let movies = movies_resource.await.unwrap();
|
||||||
|
view! {
|
||||||
|
<ul>
|
||||||
|
{movies.into_iter().map(move |movie| {
|
||||||
|
view! {
|
||||||
|
<li>{movie.name}</li>
|
||||||
|
}
|
||||||
|
}).collect::<Vec<_>>()}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
view! {
|
||||||
|
<h2>"Movies"</h2>
|
||||||
|
<MultiActionForm action=add_movie>
|
||||||
|
<label>"Add a movie" <input type="text" name="name"/></label>
|
||||||
|
<input type="submit" value="Add"/>
|
||||||
|
</MultiActionForm>
|
||||||
|
<Transition fallback=move || view! { <p>"Loading..."</p> }>
|
||||||
|
{movies}
|
||||||
|
</Transition>
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/common.rs
Normal file
23
src/common.rs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
|
use crate::model::Movie;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Context {
|
||||||
|
pub counter: Arc<Mutex<usize>>,
|
||||||
|
pub movies: Arc<Mutex<Vec<Movie>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Context {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let movies = vec![
|
||||||
|
Movie::new("Hackers"),
|
||||||
|
Movie::new("Princess Bridge"),
|
||||||
|
];
|
||||||
|
Self {
|
||||||
|
counter: Arc::new(Mutex::new(0)),
|
||||||
|
movies: Arc::new(Mutex::new(movies)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
pub mod app;
|
pub mod app;
|
||||||
|
pub mod model;
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
pub mod common;
|
||||||
|
|
||||||
#[cfg(feature = "hydrate")]
|
#[cfg(feature = "hydrate")]
|
||||||
#[wasm_bindgen::prelude::wasm_bindgen]
|
#[wasm_bindgen::prelude::wasm_bindgen]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
use wiseau::common;
|
||||||
|
|
||||||
//#[cfg(feature = "ssr")]
|
//#[cfg(feature = "ssr")]
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
use std::sync::Arc;
|
|
||||||
use tokio::sync::Mutex;
|
|
||||||
use axum::Router;
|
use axum::Router;
|
||||||
use leptos::logging::log;
|
use leptos::logging::log;
|
||||||
use leptos::prelude::*;
|
use leptos::prelude::*;
|
||||||
@@ -15,13 +15,13 @@ async fn main() {
|
|||||||
// Generate the list of routes in your Leptos App
|
// Generate the list of routes in your Leptos App
|
||||||
let routes = generate_route_list(App);
|
let routes = generate_route_list(App);
|
||||||
|
|
||||||
let counter: Arc<Mutex<usize>> = Arc::new(Mutex::new(0));
|
let context = common::Context::new();
|
||||||
|
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.leptos_routes_with_context(
|
.leptos_routes_with_context(
|
||||||
&leptos_options,
|
&leptos_options,
|
||||||
routes,
|
routes,
|
||||||
move || provide_context(counter.clone()),
|
move || provide_context(context.clone()),
|
||||||
{
|
{
|
||||||
let leptos_options = leptos_options.clone();
|
let leptos_options = leptos_options.clone();
|
||||||
move || shell(leptos_options.clone())
|
move || shell(leptos_options.clone())
|
||||||
|
|||||||
16
src/model.rs
Normal file
16
src/model.rs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Movie {
|
||||||
|
pub name: String,
|
||||||
|
pub imdb_url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Movie {
|
||||||
|
pub fn new(name: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
imdb_url: String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user