Add creation date to allow consistent ordering
This commit is contained in:
parent
f030d16d09
commit
375fa7740e
|
@ -22,6 +22,11 @@
|
||||||
"ordinal": 3,
|
"ordinal": 3,
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type_info": "Uuid"
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 4,
|
||||||
|
"name": "created_at",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -35,6 +40,7 @@
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
"ordinal": 3,
|
"ordinal": 3,
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type_info": "Uuid"
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 4,
|
||||||
|
"name": "created_at",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -33,6 +38,7 @@
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
"ordinal": 3,
|
"ordinal": 3,
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type_info": "Uuid"
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 4,
|
||||||
|
"name": "created_at",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -33,6 +38,7 @@
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -17,6 +17,11 @@
|
||||||
"ordinal": 2,
|
"ordinal": 2,
|
||||||
"name": "parent",
|
"name": "parent",
|
||||||
"type_info": "Uuid"
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 3,
|
||||||
|
"name": "created_at",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -27,7 +32,8 @@
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
true
|
true,
|
||||||
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "308962c26250f9312287a3f2f21e5da76e4cf488eedd4704019b4f14b6fbafb2"
|
"hash": "308962c26250f9312287a3f2f21e5da76e4cf488eedd4704019b4f14b6fbafb2"
|
||||||
|
|
|
@ -17,6 +17,11 @@
|
||||||
"ordinal": 2,
|
"ordinal": 2,
|
||||||
"name": "parent",
|
"name": "parent",
|
||||||
"type_info": "Uuid"
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 3,
|
||||||
|
"name": "created_at",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -29,7 +34,8 @@
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
true
|
true,
|
||||||
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "408a171b46d5c615ff846547f463dc0b18360644234fb01b24c4c047bebb3a10"
|
"hash": "408a171b46d5c615ff846547f463dc0b18360644234fb01b24c4c047bebb3a10"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "SELECT * FROM item_classes",
|
"query": "SELECT * FROM items ORDER BY created_at",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
|
@ -17,6 +17,16 @@
|
||||||
"ordinal": 2,
|
"ordinal": 2,
|
||||||
"name": "parent",
|
"name": "parent",
|
||||||
"type_info": "Uuid"
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 3,
|
||||||
|
"name": "class",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 4,
|
||||||
|
"name": "created_at",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -24,9 +34,11 @@
|
||||||
},
|
},
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
true
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "dc197bce5f03ab1ab08391f54f960e63e935172b25e5a6835d51e786fb2f854e"
|
"hash": "58969747bdccae4a2d3ad8d8117aa92283151d67f52fbb22e5d976b1c6a5c367"
|
||||||
}
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "SELECT id FROM item_classes ORDER BY created_at",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": []
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "5cf503740d71431d8b9d256960c0ce194ede48a1c46326315cae9f07347597f6"
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "SELECT * FROM items",
|
"query": "SELECT * FROM item_classes ORDER BY created_at",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
|
@ -20,8 +20,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 3,
|
"ordinal": 3,
|
||||||
"name": "class",
|
"name": "created_at",
|
||||||
"type_info": "Uuid"
|
"type_info": "Timestamptz"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -29,10 +29,10 @@
|
||||||
},
|
},
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
true,
|
false,
|
||||||
true,
|
true,
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "467dcd7fd379750cbf30a190d06dc1b3e61b1bd7ef288fbf6fbedec52c276434"
|
"hash": "6e7b3389c47091d9fc8c7638b401b413f804c6f3e082a818b67ebab0938acb39"
|
||||||
}
|
}
|
|
@ -17,6 +17,11 @@
|
||||||
"ordinal": 2,
|
"ordinal": 2,
|
||||||
"name": "parent",
|
"name": "parent",
|
||||||
"type_info": "Uuid"
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 3,
|
||||||
|
"name": "created_at",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -28,7 +33,8 @@
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
true
|
true,
|
||||||
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "7e2e1460a2c946ba909c50d4cf1beacf50ebf5fbfead379340f9f72614958e78"
|
"hash": "7e2e1460a2c946ba909c50d4cf1beacf50ebf5fbfead379340f9f72614958e78"
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
"ordinal": 3,
|
"ordinal": 3,
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type_info": "Uuid"
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 4,
|
||||||
|
"name": "created_at",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -36,6 +41,7 @@
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
"ordinal": 3,
|
"ordinal": 3,
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type_info": "Uuid"
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 4,
|
||||||
|
"name": "created_at",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -33,6 +38,7 @@
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -17,6 +17,11 @@
|
||||||
"ordinal": 2,
|
"ordinal": 2,
|
||||||
"name": "parent",
|
"name": "parent",
|
||||||
"type_info": "Uuid"
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 3,
|
||||||
|
"name": "created_at",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -27,7 +32,8 @@
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
true
|
true,
|
||||||
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "c552c0a40bc8995cb95726a85f1d0c0b86eb2322035e6a720e2e6d425072a8c1"
|
"hash": "c552c0a40bc8995cb95726a85f1d0c0b86eb2322035e6a720e2e6d425072a8c1"
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
"ordinal": 3,
|
"ordinal": 3,
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type_info": "Uuid"
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 4,
|
||||||
|
"name": "created_at",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -33,6 +38,7 @@
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -660,6 +660,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"powerfmt",
|
"powerfmt",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1126,6 +1127,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"time",
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1953,6 +1955,7 @@ dependencies = [
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"sqlformat",
|
"sqlformat",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"time",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
@ -2037,6 +2040,7 @@ dependencies = [
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"stringprep",
|
"stringprep",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"time",
|
||||||
"tracing",
|
"tracing",
|
||||||
"uuid",
|
"uuid",
|
||||||
"whoami",
|
"whoami",
|
||||||
|
@ -2076,6 +2080,7 @@ dependencies = [
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"stringprep",
|
"stringprep",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"time",
|
||||||
"tracing",
|
"tracing",
|
||||||
"uuid",
|
"uuid",
|
||||||
"whoami",
|
"whoami",
|
||||||
|
@ -2099,6 +2104,7 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"serde",
|
"serde",
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
|
"time",
|
||||||
"tracing",
|
"tracing",
|
||||||
"url",
|
"url",
|
||||||
"urlencoding",
|
"urlencoding",
|
||||||
|
|
|
@ -21,8 +21,9 @@ mime = "0.3.17"
|
||||||
printpdf = "0.7.0"
|
printpdf = "0.7.0"
|
||||||
rust-fontconfig = "0.1.7"
|
rust-fontconfig = "0.1.7"
|
||||||
serde = { version = "1.0.203", features = ["serde_derive"] }
|
serde = { version = "1.0.203", features = ["serde_derive"] }
|
||||||
sqlx = { version = "0.7.4", features = ["runtime-tokio", "postgres", "uuid"] }
|
sqlx = { version = "0.7.4", features = ["runtime-tokio", "postgres", "uuid", "time"] }
|
||||||
thiserror = "1.0.61"
|
thiserror = "1.0.61"
|
||||||
|
time = { version = "0.3.36", features = ["serde"] }
|
||||||
uuid = { version = "1.9.0", features = ["serde", "v4"] }
|
uuid = { version = "1.9.0", features = ["serde", "v4"] }
|
||||||
|
|
||||||
[profile.dev.package.sqlx-macros]
|
[profile.dev.package.sqlx-macros]
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
-- SPDX-FileCopyrightText: 2024 Simon Bruder <simon@sbruder.de>
|
||||||
|
--
|
||||||
|
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
ALTER TABLE items
|
||||||
|
DROP created_at;
|
||||||
|
|
||||||
|
ALTER TABLE item_classes
|
||||||
|
DROP created_at;
|
21
migrations/20240711190709_add_creation_timestamp.up.sql
Normal file
21
migrations/20240711190709_add_creation_timestamp.up.sql
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
-- SPDX-FileCopyrightText: 2024 Simon Bruder <simon@sbruder.de>
|
||||||
|
--
|
||||||
|
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
ALTER TABLE items
|
||||||
|
ADD created_at TIMESTAMP WITH TIME ZONE DEFAULT now();
|
||||||
|
|
||||||
|
UPDATE items
|
||||||
|
SET created_at = now();
|
||||||
|
|
||||||
|
ALTER TABLE items
|
||||||
|
ALTER created_at SET NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE item_classes
|
||||||
|
ADD created_at TIMESTAMP WITH TIME ZONE DEFAULT now();
|
||||||
|
|
||||||
|
UPDATE item_classes
|
||||||
|
SET created_at = now();
|
||||||
|
|
||||||
|
ALTER TABLE item_classes
|
||||||
|
ALTER created_at SET NOT NULL;
|
|
@ -95,6 +95,11 @@ async fn show_item_class(
|
||||||
|
|
||||||
#[get("/item-classes")]
|
#[get("/item-classes")]
|
||||||
async fn list_item_classes(pool: web::Data<PgPool>) -> actix_web::Result<impl Responder> {
|
async fn list_item_classes(pool: web::Data<PgPool>) -> actix_web::Result<impl Responder> {
|
||||||
|
let item_classes_ids = sqlx::query_scalar!("SELECT id FROM item_classes ORDER BY created_at")
|
||||||
|
.fetch_all(pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
let item_classes = manage::item_class::get_all_as_map(&pool)
|
let item_classes = manage::item_class::get_all_as_map(&pool)
|
||||||
.await
|
.await
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
@ -121,7 +126,8 @@ async fn list_item_classes(pool: web::Data<PgPool>) -> actix_web::Result<impl Re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tbody {
|
tbody {
|
||||||
@for item_class in item_classes.values() {
|
@for item_class in item_classes_ids {
|
||||||
|
@let item_class = item_classes.get(&item_class).unwrap();
|
||||||
tr {
|
tr {
|
||||||
td { a href={ "/item-class/" (item_class.id) } { (item_class.name) } }
|
td { a href={ "/item-class/" (item_class.id) } { (item_class.name) } }
|
||||||
td {
|
td {
|
||||||
|
|
|
@ -28,7 +28,9 @@ pub async fn get(pool: &PgPool, id: Uuid) -> Result<Item, sqlx::Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_all(pool: &PgPool) -> Result<Vec<Item>, sqlx::Error> {
|
pub async fn get_all(pool: &PgPool) -> Result<Vec<Item>, sqlx::Error> {
|
||||||
query_as!(Item, "SELECT * FROM items").fetch_all(pool).await
|
query_as!(Item, "SELECT * FROM items ORDER BY created_at")
|
||||||
|
.fetch_all(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_all_as_map(pool: &PgPool) -> Result<HashMap<Uuid, Item>, sqlx::Error> {
|
pub async fn get_all_as_map(pool: &PgPool) -> Result<HashMap<Uuid, Item>, sqlx::Error> {
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub async fn get(pool: &PgPool, id: Uuid) -> Result<ItemClass, sqlx::Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_all(pool: &PgPool) -> Result<Vec<ItemClass>, sqlx::Error> {
|
pub async fn get_all(pool: &PgPool) -> Result<Vec<ItemClass>, sqlx::Error> {
|
||||||
query_as!(ItemClass, "SELECT * FROM item_classes")
|
query_as!(ItemClass, "SELECT * FROM item_classes ORDER BY created_at")
|
||||||
.fetch_all(pool)
|
.fetch_all(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use time::OffsetDateTime;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, sqlx::FromRow)]
|
#[derive(Clone, Debug, Serialize, sqlx::FromRow)]
|
||||||
|
@ -11,6 +12,8 @@ pub struct Item {
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub parent: Option<Uuid>,
|
pub parent: Option<Uuid>,
|
||||||
pub class: Uuid,
|
pub class: Uuid,
|
||||||
|
#[serde(with = "time::serde::iso8601")]
|
||||||
|
pub created_at: OffsetDateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
@ -28,6 +31,8 @@ pub struct ItemClass {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub parent: Option<Uuid>,
|
pub parent: Option<Uuid>,
|
||||||
|
#[serde(with = "time::serde::iso8601")]
|
||||||
|
pub created_at: OffsetDateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
|
Loading…
Reference in a new issue