@@ -9,9 +9,14 @@ use tower_http::services::ServeDir;
9
9
use std:: sync:: Arc ;
10
10
11
11
use askama:: Template ;
12
+ use chrono:: NaiveDateTime ;
12
13
use itertools:: Itertools ;
13
14
use kip_sql:: db:: { Database , DatabaseError } ;
15
+ use kip_sql:: implement_from_tuple;
14
16
use kip_sql:: storage:: kip:: KipStorage ;
17
+ use kip_sql:: types:: value:: DataValue ;
18
+ use kip_sql:: types:: tuple:: Tuple ;
19
+ use kip_sql:: types:: LogicalType ;
15
20
16
21
pub ( crate ) const BANNER : & str = "
17
22
█████ ████ ███ ███████████ ████
@@ -32,7 +37,7 @@ pub(crate) const BANNER: &str = "
32
37
#[ template( path = "posts.html" ) ]
33
38
struct PostTemplate < ' a > {
34
39
post_title : & ' a str ,
35
- post_date : & ' a str ,
40
+ post_date : String ,
36
41
post_body : & ' a str ,
37
42
}
38
43
@@ -47,13 +52,31 @@ pub struct IndexTemplate<'a> {
47
52
48
53
// SQL query will return all posts
49
54
// into a Vec<Post>
50
- #[ derive( Debug , Clone ) ]
55
+ #[ derive( Debug , Clone , Default ) ]
51
56
pub struct Post {
52
57
pub post_title : String ,
53
- pub post_date : String ,
58
+ pub post_date : NaiveDateTime ,
54
59
pub post_body : String ,
55
60
}
56
61
62
+ implement_from_tuple ! ( Post , (
63
+ post_title: String => |post: & mut Post , value: DataValue | {
64
+ if let Some ( title) = value. utf8( ) {
65
+ post. post_title = title;
66
+ }
67
+ } ,
68
+ post_date: NaiveDateTime => |post: & mut Post , value: DataValue | {
69
+ if let Some ( date_time) = value. datetime( ) {
70
+ post. post_date = date_time;
71
+ }
72
+ } ,
73
+ post_body: String => |post: & mut Post , value: DataValue | {
74
+ if let Some ( body) = value. utf8( ) {
75
+ post. post_body = body;
76
+ }
77
+ }
78
+ ) ) ;
79
+
57
80
// Our custom Askama filter to replace spaces with dashes in the title
58
81
mod filters {
59
82
@@ -67,14 +90,19 @@ mod filters {
67
90
// Path to extract the query: localhost:4000/post/thispart
68
91
// State that holds a Vec<Post> used to render the post that the query matches
69
92
async fn post ( Path ( query_title) : Path < String > , State ( state) : State < Arc < Database < KipStorage > > > ) -> impl IntoResponse {
70
- let mut template = PostTemplate { post_title : "none" , post_date : "none" , post_body : "none" } ;
93
+ let mut template = PostTemplate { post_title : "none" , post_date : "none" . to_string ( ) , post_body : "none" } ;
71
94
let posts = get_posts ( & state) . await . unwrap ( ) ;
72
95
// if the user's query matches a post title then render a template
73
96
for post in & posts {
74
97
if query_title == post. post_title {
98
+ let post_date = post
99
+ . post_date
100
+ . format ( "%Y-%m-%d %H:%M:%S" )
101
+ . to_string ( ) ;
102
+
75
103
template = PostTemplate {
76
104
post_title : & post. post_title ,
77
- post_date : & post . post_date ,
105
+ post_date,
78
106
post_body : & post. post_body
79
107
} ;
80
108
break ;
@@ -136,12 +164,6 @@ async fn get_posts(kip_sql: &Database<KipStorage>) -> Result<Vec<Post>, Database
136
164
Ok ( kip_sql. run ( "select post_title, post_date, post_body from myposts" )
137
165
. await ?
138
166
. into_iter ( )
139
- . map ( |tuple| {
140
- Post {
141
- post_title : tuple. values [ 0 ] . to_string ( ) ,
142
- post_date : tuple. values [ 1 ] . to_string ( ) ,
143
- post_body : tuple. values [ 2 ] . to_string ( ) ,
144
- }
145
- } )
167
+ . map ( |tuple| Post :: from ( tuple) )
146
168
. collect_vec ( ) )
147
169
}
0 commit comments