Create a projects board display
This commit is contained in:
parent
64e810d360
commit
38dbf10abe
6 changed files with 164 additions and 89 deletions
173
src/db.rs
173
src/db.rs
|
|
@ -1,96 +1,93 @@
|
|||
use crate::project::Project;
|
||||
use rusqlite::{Connection, Result};
|
||||
|
||||
pub struct Database {
|
||||
conn: Connection,
|
||||
fn open_connection() -> Result<Connection> {
|
||||
let conn = Connection::open("projects.db")?;
|
||||
conn.execute_batch(include_str!("schema.sql"))?;
|
||||
Ok(conn)
|
||||
}
|
||||
|
||||
impl Database {
|
||||
pub fn new(path: &str) -> Result<Self> {
|
||||
let conn = Connection::open(path)?;
|
||||
pub fn create_project(title: String) -> Result<i64> {
|
||||
let conn = open_connection()?;
|
||||
let now = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs() as i64;
|
||||
|
||||
conn.execute_batch(include_str!("schema.sql"))?;
|
||||
conn.execute(
|
||||
"INSERT INTO projects (title, created_time, last_modified_time, percentage_completed, archived)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5)",
|
||||
(&title, now, now, 0, 0),
|
||||
)?;
|
||||
|
||||
Ok(Self { conn })
|
||||
}
|
||||
|
||||
pub fn create_project(&self, title: String) -> Result<i64> {
|
||||
let now = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs() as i64;
|
||||
|
||||
self.conn.execute(
|
||||
"INSERT INTO projects (title, created_time, last_modified_time, percentage_completed, archived)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5)",
|
||||
(&title, now, now, 0, 0),
|
||||
)?;
|
||||
|
||||
Ok(self.conn.last_insert_rowid())
|
||||
}
|
||||
|
||||
pub fn update_project_progress(&self, id: i64, percentage: i32) -> Result<()> {
|
||||
let now = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs() as i64;
|
||||
|
||||
self.conn.execute(
|
||||
"UPDATE projects SET percentage_completed = ?1, last_modified_time = ?2 WHERE id = ?3",
|
||||
(percentage, now, id),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn archive_project(&self, id: i64) -> Result<()> {
|
||||
let now = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs() as i64;
|
||||
|
||||
self.conn.execute(
|
||||
"UPDATE projects SET archived = 1, last_modified_time = ?1 WHERE id = ?2",
|
||||
(now, id),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unarchive_project(&self, id: i64) -> Result<()> {
|
||||
let now = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs() as i64;
|
||||
|
||||
self.conn.execute(
|
||||
"UPDATE projects SET archived = 0, last_modified_time = ?1 WHERE id = ?2",
|
||||
(now, id),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn list_all_projects(&self) -> Result<Vec<Project>> {
|
||||
let mut stmt = self.conn.prepare(
|
||||
"SELECT id, title, created_time, last_modified_time, percentage_completed, archived
|
||||
FROM projects
|
||||
ORDER BY last_modified_time DESC",
|
||||
)?;
|
||||
|
||||
let projects = stmt
|
||||
.query_map([], |row| {
|
||||
Ok(Project {
|
||||
id: row.get(0)?,
|
||||
title: row.get(1)?,
|
||||
created_time: row.get(2)?,
|
||||
last_modified_time: row.get(3)?,
|
||||
percentage_completed: row.get(4)?,
|
||||
archived: row.get::<_, i32>(5)? != 0,
|
||||
})
|
||||
})?
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
|
||||
Ok(projects)
|
||||
}
|
||||
Ok(conn.last_insert_rowid())
|
||||
}
|
||||
|
||||
pub fn update_project_progress(id: i64, percentage: i32) -> Result<()> {
|
||||
let conn = open_connection()?;
|
||||
let now = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs() as i64;
|
||||
|
||||
conn.execute(
|
||||
"UPDATE projects SET percentage_completed = ?1, last_modified_time = ?2 WHERE id = ?3",
|
||||
(percentage, now, id),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn archive_project(id: i64) -> Result<()> {
|
||||
let conn = open_connection()?;
|
||||
let now = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs() as i64;
|
||||
|
||||
conn.execute(
|
||||
"UPDATE projects SET archived = 1, last_modified_time = ?1 WHERE id = ?2",
|
||||
(now, id),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unarchive_project(id: i64) -> Result<()> {
|
||||
let conn = open_connection()?;
|
||||
let now = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs() as i64;
|
||||
|
||||
conn.execute(
|
||||
"UPDATE projects SET archived = 0, last_modified_time = ?1 WHERE id = ?2",
|
||||
(now, id),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn list_all_projects() -> Result<Vec<Project>> {
|
||||
let conn = open_connection()?;
|
||||
let mut stmt = conn.prepare(
|
||||
"SELECT id, title, created_time, last_modified_time, percentage_completed, archived
|
||||
FROM projects
|
||||
ORDER BY last_modified_time DESC",
|
||||
)?;
|
||||
|
||||
let projects = stmt
|
||||
.query_map([], |row| {
|
||||
Ok(Project {
|
||||
id: row.get(0)?,
|
||||
title: row.get(1)?,
|
||||
created_time: row.get(2)?,
|
||||
last_modified_time: row.get(3)?,
|
||||
percentage_completed: row.get(4)?,
|
||||
archived: row.get::<_, i32>(5)? != 0,
|
||||
})
|
||||
})?
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
|
||||
Ok(projects)
|
||||
}
|
||||
|
|
|
|||
30
src/main.rs
30
src/main.rs
|
|
@ -1,3 +1,4 @@
|
|||
use maud::{DOCTYPE, html};
|
||||
use rouille::router;
|
||||
|
||||
mod db;
|
||||
|
|
@ -16,6 +17,35 @@ fn main() {
|
|||
let js = include_bytes!("project-card.js");
|
||||
rouille::Response::from_data("application/javascript", js.as_ref())
|
||||
},
|
||||
(GET) ["/projects"] => {
|
||||
let projects = db::list_all_projects().unwrap_or_default();
|
||||
|
||||
let markup = html! {
|
||||
(DOCTYPE)
|
||||
html {
|
||||
head {
|
||||
meta charset="utf-8";
|
||||
meta name="viewport" content="width=device-width, initial-scale=1";
|
||||
link rel="stylesheet" href="/main.css";
|
||||
script src="/project-card.js" {}
|
||||
}
|
||||
body {
|
||||
main {
|
||||
section {
|
||||
@for project in &projects {
|
||||
project-card
|
||||
title=(project.title)
|
||||
percentage=(project.percentage_completed)
|
||||
archived=(project.archived) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
rouille::Response::html(markup.into_string())
|
||||
},
|
||||
_ => rouille::Response::empty_404()
|
||||
)
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue