Compare commits
4 commits
35230b6c37
...
1d831585bd
Author | SHA1 | Date | |
---|---|---|---|
Simon Bruder | 1d831585bd | ||
Simon Bruder | a72d5b40e2 | ||
Simon Bruder | 1f6298af4a | ||
Simon Bruder | 5b3dd34312 |
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
@ -25,6 +23,7 @@ jobs:
|
||||||
- name: Build
|
- name: Build
|
||||||
run: nix build -L .#li7y .#li7y-oci
|
run: nix build -L .#li7y .#li7y-oci
|
||||||
- name: Push OCI image
|
- name: Push OCI image
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
run: |
|
run: |
|
||||||
nix build .#li7y-oci
|
nix build .#li7y-oci
|
||||||
podman image load -i ./result
|
podman image load -i ./result
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "SELECT items.id, items.name, item_classes.name AS \"class_name\"\n FROM items\n JOIN item_classes\n ON items.class = item_classes.id\n WHERE items.original_packaging = $1",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "name",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 2,
|
||||||
|
"name": "class_name",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "02438c29c249ce2b446d15a41d07c40ce73946e62744a486cbbac256c4a4cf55"
|
||||||
|
}
|
|
@ -1,64 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "SELECT * FROM items WHERE parent = $1",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "name",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "parent",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "class",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "created_at",
|
|
||||||
"type_info": "Timestamptz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 5,
|
|
||||||
"name": "short_id",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 6,
|
|
||||||
"name": "original_packaging",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 7,
|
|
||||||
"name": "description",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "2e9619ce6db1047e2f5447c4925f28fd05f18706f70220b6ebb7354d2a0a9e3b"
|
|
||||||
}
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "SELECT id AS \"id?\", to_char(short_id, '000000') AS \"short_id?\"\n FROM items\n WHERE id = ANY ($1)",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id?",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "short_id?",
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"UuidArray"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "460f15b3c5ec2774c237fc581166bf44ecdb0b6145f8abba155478643a474125"
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "SELECT items.id, items.name, item_classes.name AS \"class_name\"\n FROM items\n JOIN item_classes\n ON items.class = item_classes.id\n WHERE items.class = $1",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "name",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 2,
|
||||||
|
"name": "class_name",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "482df01f0509cc8ec18ffe1caea8f65f11c170b67424e35697540ae12e577227"
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "SELECT id, name FROM item_classes WHERE parent = $1",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "name",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "4ed0c3101202abc920d81ee6acdaff9ed698f585df5e798d1f42206042e31a1b"
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "INSERT INTO items (name, parent, class, original_packaging, description)\n VALUES ($1, $2, $3, $4, $5)\n RETURNING id",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Varchar",
|
||||||
|
"Uuid",
|
||||||
|
"Uuid",
|
||||||
|
"Uuid",
|
||||||
|
"Varchar"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "53be3ef02ba8b3deb3a74b184a4eb93e01fd0983c19aff3fca67bdc0afab4f37"
|
||||||
|
}
|
|
@ -1,62 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "SELECT * FROM items ORDER BY created_at",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "name",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "parent",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "class",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "created_at",
|
|
||||||
"type_info": "Timestamptz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 5,
|
|
||||||
"name": "short_id",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 6,
|
|
||||||
"name": "original_packaging",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 7,
|
|
||||||
"name": "description",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": []
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "58969747bdccae4a2d3ad8d8117aa92283151d67f52fbb22e5d976b1c6a5c367"
|
|
||||||
}
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "\n WITH RECURSIVE cte AS (\n SELECT\n id,\n ARRAY[]::UUID[] AS parents,\n ARRAY[]::VARCHAR[] AS parent_names,\n ARRAY[]::VARCHAR[] AS parent_class_names\n FROM items\n WHERE parent IS NULL\n\n UNION\n\n SELECT\n items.id,\n cte.parents || items.parent,\n cte.parent_names || items.name,\n cte.parent_class_names || item_classes.name\n FROM items\n JOIN cte\n ON items.parent = cte.id\n JOIN item_classes\n ON items.class = item_classes.id\n )\n SELECT\n cte.id AS \"id!\",\n items.name,\n items.class,\n item_classes.name AS \"class_name\",\n cte.parents AS \"parents!\",\n cte.parent_names AS \"parent_names!: Vec<Option<String>>\",\n cte.parent_class_names AS \"parent_class_names!\"\n FROM cte\n JOIN items\n ON cte.id = items.id\n JOIN item_classes\n ON items.class = item_classes.id\n ORDER BY items.created_at\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id!",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "name",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 2,
|
||||||
|
"name": "class",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 3,
|
||||||
|
"name": "class_name",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 4,
|
||||||
|
"name": "parents!",
|
||||||
|
"type_info": "UuidArray"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 5,
|
||||||
|
"name": "parent_names!: Vec<Option<String>>",
|
||||||
|
"type_info": "VarcharArray"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 6,
|
||||||
|
"name": "parent_class_names!",
|
||||||
|
"type_info": "VarcharArray"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": []
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "5dac9aa215abdc07cda1f4d46db4bcafec45b6264efcb8a175580a71e48c7421"
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "UPDATE items\n SET name = $2, parent = $3, class = $4, original_packaging = $5, description = $6\n WHERE id = $1",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid",
|
||||||
|
"Varchar",
|
||||||
|
"Uuid",
|
||||||
|
"Uuid",
|
||||||
|
"Uuid",
|
||||||
|
"Varchar"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "6737f54ceb18b9b744bac838801edbbdfe2cbf68a6346f93c072d47f5add9e46"
|
||||||
|
}
|
|
@ -1,48 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "INSERT INTO item_classes (name, parent, description) VALUES ($1, $2, $3) RETURNING *",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "name",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "parent",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "created_at",
|
|
||||||
"type_info": "Timestamptz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "description",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Varchar",
|
|
||||||
"Uuid",
|
|
||||||
"Varchar"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "68d93c71840f87d5f5bb14b4d7fc34edd6be47cd1706b3612a332bbfd4bb54b4"
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "SELECT type as \"type!\" FROM\n (SELECT id, 'item' AS \"type\" FROM items\n UNION ALL\n SELECT id, 'item_class' AS \"type\" FROM item_classes) id_mapping\n WHERE id = $1",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "type!",
|
|
||||||
"type_info": "Text"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
null
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "6dd8b63f4aaefbc1ab5d5a9bae2338a7275ba56a9b17278fd886175c3a27b0dd"
|
|
||||||
}
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "SELECT type as \"type!\"\n FROM (SELECT id, 'item' AS \"type\" FROM items\n UNION ALL\n SELECT id, 'item_class' AS \"type\" FROM item_classes) id_mapping\n WHERE id = $1",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "type!",
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "719aff68ead7ada499158fec5e9f8f3c3841a4424da04aee0136c7e4f8df79e7"
|
||||||
|
}
|
|
@ -1,64 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "SELECT * FROM items WHERE id = ANY ($1)",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "name",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "parent",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "class",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "created_at",
|
|
||||||
"type_info": "Timestamptz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 5,
|
|
||||||
"name": "short_id",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 6,
|
|
||||||
"name": "original_packaging",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 7,
|
|
||||||
"name": "description",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"UuidArray"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "79d8bfe2ed76ee550cdc31f282f598749d931af69a80d24f4575a4bc2c740f3b"
|
|
||||||
}
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "SELECT items.id, items.name, item_classes.name AS \"class_name\"\n FROM items\n JOIN item_classes\n ON items.class = item_classes.id",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "name",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 2,
|
||||||
|
"name": "class_name",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": []
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "7b3f478c9b217e09043daeca5dc574381493e559860258f4f6bffb12825b1ed7"
|
||||||
|
}
|
|
@ -1,64 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "SELECT * FROM items WHERE short_id = $1",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "name",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "parent",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "class",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "created_at",
|
|
||||||
"type_info": "Timestamptz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 5,
|
|
||||||
"name": "short_id",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 6,
|
|
||||||
"name": "original_packaging",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 7,
|
|
||||||
"name": "description",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int4"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "7eeb752c8b00ac4000104f0254186f1f9fdb076e8f8b98f10fc1b981cfe8038c"
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "UPDATE items SET name = $2, parent = $3, class = $4, original_packaging = $5, description = $6 WHERE id = $1 RETURNING *",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "name",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "parent",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "class",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "created_at",
|
|
||||||
"type_info": "Timestamptz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 5,
|
|
||||||
"name": "short_id",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 6,
|
|
||||||
"name": "original_packaging",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 7,
|
|
||||||
"name": "description",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid",
|
|
||||||
"Varchar",
|
|
||||||
"Uuid",
|
|
||||||
"Uuid",
|
|
||||||
"Uuid",
|
|
||||||
"Varchar"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "82df5c0633a655d376b8a91e9f11981cfee40fd04cb4e3552cc5f4ebf4ed0572"
|
|
||||||
}
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "UPDATE item_classes\n SET name = $2, parent = $3, description = $4\n WHERE id = $1",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid",
|
||||||
|
"Varchar",
|
||||||
|
"Uuid",
|
||||||
|
"Varchar"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "835261895368c22af5780c4e4b69b518f5cb6936e3e4ea23c200b13787a401e1"
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "INSERT INTO item_classes (name, parent, description)\n VALUES ($1, $2, $3)\n RETURNING id",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Varchar",
|
||||||
|
"Uuid",
|
||||||
|
"Varchar"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "83fe5e57b2c7db1fdfbf05749646ac6ebe71d81057cd865c5f946d6ddb62b552"
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "SELECT * FROM item_classes WHERE parent = $1",
|
"query": "SELECT\n class.id,\n class.name,\n class.description,\n class.parent,\n parent.name AS \"parent_name?\"\n FROM item_classes AS \"class\"\n LEFT JOIN item_classes AS \"parent\"\n ON class.parent = parent.id\n WHERE class.id = $1",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
|
@ -15,17 +15,17 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 2,
|
"ordinal": 2,
|
||||||
|
"name": "description",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 3,
|
||||||
"name": "parent",
|
"name": "parent",
|
||||||
"type_info": "Uuid"
|
"type_info": "Uuid"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "created_at",
|
|
||||||
"type_info": "Timestamptz"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"ordinal": 4,
|
"ordinal": 4,
|
||||||
"name": "description",
|
"name": "parent_name?",
|
||||||
"type_info": "Varchar"
|
"type_info": "Varchar"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -37,10 +37,10 @@
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
true,
|
|
||||||
false,
|
false,
|
||||||
|
true,
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "c552c0a40bc8995cb95726a85f1d0c0b86eb2322035e6a720e2e6d425072a8c1"
|
"hash": "84b4620db57dd9b963e09153c3de5938b3959ae41744098c4e9565404abf09ae"
|
||||||
}
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "INSERT INTO items (name, parent, class, original_packaging, description)\n SELECT * FROM UNNEST($1::VARCHAR[], $2::UUID[], $3::UUID[], $4::UUID[], $5::VARCHAR[])\n RETURNING id",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"VarcharArray",
|
||||||
|
"UuidArray",
|
||||||
|
"UuidArray",
|
||||||
|
"UuidArray",
|
||||||
|
"VarcharArray"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "857bbaea0fa73c37679d927aa627ee841c5b89c86af12f32493ba05c0f0ead91"
|
||||||
|
}
|
|
@ -1,64 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "SELECT items.*\n FROM items\n INNER JOIN\n unnest((SELECT parents FROM item_tree WHERE id = $1))\n WITH ORDINALITY AS parents(id, n)\n ON items.id = parents.id\n ORDER BY parents.n;",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "name",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "parent",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "class",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "created_at",
|
|
||||||
"type_info": "Timestamptz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 5,
|
|
||||||
"name": "short_id",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 6,
|
|
||||||
"name": "original_packaging",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 7,
|
|
||||||
"name": "description",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "9286b6ee0c08b8446ede68b890b8bf3208b55b51433ec92b4e7a452929a81945"
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "SELECT * FROM items WHERE class = $1",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "name",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "parent",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "class",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "created_at",
|
|
||||||
"type_info": "Timestamptz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 5,
|
|
||||||
"name": "short_id",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 6,
|
|
||||||
"name": "original_packaging",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 7,
|
|
||||||
"name": "description",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "94958a3a57c3178e6b0de5723b1fbc5433e972b5522b367098afe6cb90a30bf2"
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "SELECT unnest(parents) as \"parents!\" FROM item_tree WHERE id = $1",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "parents!",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
null
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "97d6a7ee24e75dc5a9dc41a581e1013767fe36575c28574733c5ab5cbf557fb5"
|
|
||||||
}
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "SELECT\n items.id,\n items.short_id,\n items.name,\n items.class,\n item_classes.name AS \"class_name\",\n items.original_packaging,\n op.name AS \"original_packaging_name?\",\n op_class.name AS \"original_packaging_class_name?\",\n items.description\n FROM items\n JOIN item_classes\n ON items.class = item_classes.id\n LEFT JOIN items AS \"op\"\n ON items.original_packaging = op.id\n LEFT JOIN item_classes AS \"op_class\"\n ON op.class = op_class.id\n WHERE items.id = $1",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "short_id",
|
||||||
|
"type_info": "Int4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 2,
|
||||||
|
"name": "name",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 3,
|
||||||
|
"name": "class",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 4,
|
||||||
|
"name": "class_name",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 5,
|
||||||
|
"name": "original_packaging",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 6,
|
||||||
|
"name": "original_packaging_name?",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 7,
|
||||||
|
"name": "original_packaging_class_name?",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 8,
|
||||||
|
"name": "description",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "9c1a1e9c33539f6ec4800c9e8fc8ce3b65f49c34ad848321dc1b151c21cb0043"
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "SELECT items.id, items.name, item_classes.name AS \"class_name\"\n FROM items\n JOIN item_classes\n ON items.class = item_classes.id\n WHERE items.parent = $1",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "name",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 2,
|
||||||
|
"name": "class_name",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "9e1704d0b60906061460e2c972fccf5d87b053857c161651360e5a8fdd80e397"
|
||||||
|
}
|
|
@ -1,26 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "SELECT id as \"id!\", parents as \"parents!\" FROM item_tree",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id!",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "parents!",
|
|
||||||
"type_info": "UuidArray"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": []
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
true,
|
|
||||||
true
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "a6f646089b4424deffc0b1a454bcfa2f2a497180e2517a937471f81a1f9c5538"
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "INSERT INTO items (name, parent, class, original_packaging, description)\n SELECT * FROM UNNEST($1::VARCHAR[], $2::UUID[], $3::UUID[], $4::UUID[], $5::VARCHAR[])\n RETURNING *",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "name",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "parent",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "class",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "created_at",
|
|
||||||
"type_info": "Timestamptz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 5,
|
|
||||||
"name": "short_id",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 6,
|
|
||||||
"name": "original_packaging",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 7,
|
|
||||||
"name": "description",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"VarcharArray",
|
|
||||||
"UuidArray",
|
|
||||||
"UuidArray",
|
|
||||||
"UuidArray",
|
|
||||||
"VarcharArray"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "b54d323092a1dc2e34d3882a06b3cd119362d0baf5effbbd09f969ee31f385ef"
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "INSERT INTO items (name, parent, class, original_packaging, description) VALUES ($1, $2, $3, $4, $5) RETURNING *",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "name",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "parent",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "class",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "created_at",
|
|
||||||
"type_info": "Timestamptz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 5,
|
|
||||||
"name": "short_id",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 6,
|
|
||||||
"name": "original_packaging",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 7,
|
|
||||||
"name": "description",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Varchar",
|
|
||||||
"Uuid",
|
|
||||||
"Uuid",
|
|
||||||
"Uuid",
|
|
||||||
"Varchar"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "b80bb07ab582b0705b5c0370066730edf887d66a4196a0834c59f0df9f9314d3"
|
|
||||||
}
|
|
|
@ -1,45 +1,35 @@
|
||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "SELECT * FROM items WHERE id = $1",
|
"query": "SELECT\n items.name,\n items.parent,\n items.class,\n item_classes.name AS \"class_name\",\n items.original_packaging,\n items.description\n FROM items\n JOIN item_classes\n ON items.class = item_classes.id\n WHERE items.id = $1",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
"ordinal": 0,
|
"ordinal": 0,
|
||||||
"name": "id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "name",
|
"name": "name",
|
||||||
"type_info": "Varchar"
|
"type_info": "Varchar"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 2,
|
"ordinal": 1,
|
||||||
"name": "parent",
|
"name": "parent",
|
||||||
"type_info": "Uuid"
|
"type_info": "Uuid"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 3,
|
"ordinal": 2,
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type_info": "Uuid"
|
"type_info": "Uuid"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 3,
|
||||||
|
"name": "class_name",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 4,
|
"ordinal": 4,
|
||||||
"name": "created_at",
|
|
||||||
"type_info": "Timestamptz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 5,
|
|
||||||
"name": "short_id",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 6,
|
|
||||||
"name": "original_packaging",
|
"name": "original_packaging",
|
||||||
"type_info": "Uuid"
|
"type_info": "Uuid"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 7,
|
"ordinal": 5,
|
||||||
"name": "description",
|
"name": "description",
|
||||||
"type_info": "Varchar"
|
"type_info": "Varchar"
|
||||||
}
|
}
|
||||||
|
@ -50,15 +40,13 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
|
||||||
true,
|
true,
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "1e9045f52c002a19b815351fee1c7ee7520478ff4f5886b4523fb0dc4df0e204"
|
"hash": "c49b88eda9a62743783bc894f01bb6198594f94a3e0856abde0efdb4e49dbab8"
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "SELECT * FROM item_classes ORDER BY created_at",
|
"query": "SELECT class.id, class.name, class.parent, parent.name AS \"parent_name?\"\n FROM item_classes AS \"class\"\n LEFT JOIN item_classes AS \"parent\"\n ON class.parent = parent.id\n ORDER BY class.created_at\n ",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
|
@ -20,12 +20,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 3,
|
"ordinal": 3,
|
||||||
"name": "created_at",
|
"name": "parent_name?",
|
||||||
"type_info": "Timestamptz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "description",
|
|
||||||
"type_info": "Varchar"
|
"type_info": "Varchar"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -36,9 +31,8 @@
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
false,
|
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "6e7b3389c47091d9fc8c7638b401b413f804c6f3e082a818b67ebab0938acb39"
|
"hash": "c7e35dee5f56da8da3c083e191f396b95917b15768ebe0250ce7840391036616"
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "SELECT id FROM item_classes ORDER BY created_at",
|
"query": "SELECT id FROM items WHERE short_id = $1",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
|
@ -10,11 +10,13 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Left": []
|
"Left": [
|
||||||
|
"Int4"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "5cf503740d71431d8b9d256960c0ce194ede48a1c46326315cae9f07347597f6"
|
"hash": "cfce4ef19a3e0a3a0582d3c7d266b952397a017b33c351c5a33f1daa78ab908a"
|
||||||
}
|
}
|
|
@ -1,49 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "UPDATE item_classes SET name = $2, parent = $3, description = $4 WHERE id = $1 RETURNING *",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "name",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "parent",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "created_at",
|
|
||||||
"type_info": "Timestamptz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "description",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid",
|
|
||||||
"Varchar",
|
|
||||||
"Uuid",
|
|
||||||
"Varchar"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "e0129afa95f896d79f772fb177a8f9229dfbbfd289039db7b733c7d1d050f4bf"
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "SELECT * FROM items WHERE original_packaging = $1",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "name",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "parent",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "class",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "created_at",
|
|
||||||
"type_info": "Timestamptz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 5,
|
|
||||||
"name": "short_id",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 6,
|
|
||||||
"name": "original_packaging",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 7,
|
|
||||||
"name": "description",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "efe2258db42b60f732d562d106842b19308d9a558703b02e758f60e7d8644d00"
|
|
||||||
}
|
|
|
@ -1,30 +1,20 @@
|
||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "SELECT * FROM item_classes WHERE id = $1",
|
"query": "SELECT name, parent, description FROM item_classes WHERE id = $1",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
"ordinal": 0,
|
"ordinal": 0,
|
||||||
"name": "id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "name",
|
"name": "name",
|
||||||
"type_info": "Varchar"
|
"type_info": "Varchar"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 2,
|
"ordinal": 1,
|
||||||
"name": "parent",
|
"name": "parent",
|
||||||
"type_info": "Uuid"
|
"type_info": "Uuid"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 3,
|
"ordinal": 2,
|
||||||
"name": "created_at",
|
|
||||||
"type_info": "Timestamptz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "description",
|
"name": "description",
|
||||||
"type_info": "Varchar"
|
"type_info": "Varchar"
|
||||||
}
|
}
|
||||||
|
@ -35,12 +25,10 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
false,
|
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "308962c26250f9312287a3f2f21e5da76e4cf488eedd4704019b4f14b6fbafb2"
|
"hash": "f446c6ab881c166102f3b20056e0709be6fbcfc596063878c0bad9df00037dbe"
|
||||||
}
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "SELECT id, name FROM item_classes",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "name",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": []
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "fc5e536bddb5d76021164ae4f5a6b0ad52d1ae047fd004f1359be7122facf8e7"
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "SELECT items.id, items.name, item_classes.name AS \"class_name\"\n FROM items\n JOIN unnest((SELECT parents FROM item_tree WHERE id = $1))\n WITH ORDINALITY AS parents(id, n)\n ON items.id = parents.id\n JOIN item_classes\n ON items.class = item_classes.id\n ORDER BY parents.n",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "name",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 2,
|
||||||
|
"name": "class_name",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "ff39480d9395b357d71e9af3eb37fa308f4df6a0ca6442fa7f9bbda1e34ffbbe"
|
||||||
|
}
|
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -1113,6 +1113,15 @@ version = "1.70.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
|
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.11"
|
version = "1.0.11"
|
||||||
|
@ -1165,6 +1174,7 @@ dependencies = [
|
||||||
"enum-iterator",
|
"enum-iterator",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"itertools",
|
||||||
"log",
|
"log",
|
||||||
"maud",
|
"maud",
|
||||||
"mime",
|
"mime",
|
||||||
|
|
|
@ -19,6 +19,7 @@ datamatrix = "0.3.1"
|
||||||
enum-iterator = "2.1.0"
|
enum-iterator = "2.1.0"
|
||||||
env_logger = "0.11.3"
|
env_logger = "0.11.3"
|
||||||
futures-util = "0.3.30"
|
futures-util = "0.3.30"
|
||||||
|
itertools = "0.13.0"
|
||||||
log = "0.4.21"
|
log = "0.4.21"
|
||||||
maud = { version = "0.26.0", features = ["actix-web"] }
|
maud = { version = "0.26.0", features = ["actix-web"] }
|
||||||
mime = "0.3.17"
|
mime = "0.3.17"
|
||||||
|
|
106
flake.lock
106
flake.lock
|
@ -34,10 +34,31 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"git-hooks": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": "flake-compat",
|
||||||
|
"gitignore": "gitignore",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"nixpkgs-stable": "nixpkgs-stable"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1721042469,
|
||||||
|
"narHash": "sha256-6FPUl7HVtvRHCCBQne7Ylp4p+dpP3P/OYuzjztZ4s70=",
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "git-hooks.nix",
|
||||||
|
"rev": "f451c19376071a90d8c58ab1a953c6e9840527fd",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "git-hooks.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"gitignore": {
|
"gitignore": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"pre-commit-hooks",
|
"git-hooks",
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -57,7 +78,7 @@
|
||||||
},
|
},
|
||||||
"naersk": {
|
"naersk": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1718727675,
|
"lastModified": 1718727675,
|
||||||
|
@ -74,6 +95,38 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1719082008,
|
||||||
|
"narHash": "sha256-jHJSUH619zBQ6WdC21fFAlDxHErKVDJ5fpN0Hgx4sjs=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "9693852a2070b398ee123a329e68f0dab5526681",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs-stable": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1720386169,
|
||||||
|
"narHash": "sha256-NGKVY4PjzwAa4upkGtAMz1npHGoRzWotlSnVlqI40mo=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "194846768975b7ad2c4988bdb82572c00222c0d7",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-24.05",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 0,
|
"lastModified": 0,
|
||||||
"narHash": "sha256-F/TKWETwB5RaR8owkPPi+SPJh83AQsm6KrQAlJ8v/uA=",
|
"narHash": "sha256-F/TKWETwB5RaR8owkPPi+SPJh83AQsm6KrQAlJ8v/uA=",
|
||||||
|
@ -85,23 +138,7 @@
|
||||||
"type": "indirect"
|
"type": "indirect"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-stable": {
|
"nixpkgs_3": {
|
||||||
"locked": {
|
|
||||||
"lastModified": 1718447546,
|
|
||||||
"narHash": "sha256-JHuXsrC9pr4kA4n7LuuPfWFJUVlDBVJ1TXDVpHEuUgM=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "842253bf992c3a7157b67600c2857193f126563a",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-23.11",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs_2": {
|
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1719075281,
|
"lastModified": 1719075281,
|
||||||
"narHash": "sha256-CyyxvOwFf12I91PBWz43iGT1kjsf5oi6ax7CrvaMyAo=",
|
"narHash": "sha256-CyyxvOwFf12I91PBWz43iGT1kjsf5oi6ax7CrvaMyAo=",
|
||||||
|
@ -117,7 +154,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_3": {
|
"nixpkgs_4": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1718428119,
|
"lastModified": 1718428119,
|
||||||
"narHash": "sha256-WdWDpNaq6u1IPtxtYHHWpl5BmabtpmLnMAx0RdJ/vo8=",
|
"narHash": "sha256-WdWDpNaq6u1IPtxtYHHWpl5BmabtpmLnMAx0RdJ/vo8=",
|
||||||
|
@ -133,41 +170,18 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pre-commit-hooks": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": "flake-compat",
|
|
||||||
"gitignore": "gitignore",
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"nixpkgs-stable": "nixpkgs-stable"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1719249328,
|
|
||||||
"narHash": "sha256-Bit5QIBnDuQyF+rXz5lGbm4EyOKAAkWpgh+htXzNOs0=",
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "pre-commit-hooks.nix",
|
|
||||||
"rev": "cfb96902abfdb986e68a8d09ffa5c363376c973e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "pre-commit-hooks.nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
|
"git-hooks": "git-hooks",
|
||||||
"naersk": "naersk",
|
"naersk": "naersk",
|
||||||
"nixpkgs": "nixpkgs_2",
|
"nixpkgs": "nixpkgs_3",
|
||||||
"pre-commit-hooks": "pre-commit-hooks",
|
|
||||||
"rust-overlay": "rust-overlay"
|
"rust-overlay": "rust-overlay"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rust-overlay": {
|
"rust-overlay": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs_3"
|
"nixpkgs": "nixpkgs_4"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1719195554,
|
"lastModified": 1719195554,
|
||||||
|
|
|
@ -12,12 +12,10 @@
|
||||||
|
|
||||||
naersk.url = "github:nix-community/naersk";
|
naersk.url = "github:nix-community/naersk";
|
||||||
|
|
||||||
pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix";
|
git-hooks.url = "github:cachix/git-hooks.nix";
|
||||||
pre-commit-hooks.inputs.flake-utils.follows = "flake-utils";
|
|
||||||
pre-commit-hooks.inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, flake-utils, nixpkgs, rust-overlay, naersk, pre-commit-hooks }: flake-utils.lib.eachDefaultSystem (system:
|
outputs = { self, flake-utils, nixpkgs, rust-overlay, naersk, git-hooks }: flake-utils.lib.eachDefaultSystem (system:
|
||||||
let
|
let
|
||||||
pkgs = import nixpkgs {
|
pkgs = import nixpkgs {
|
||||||
inherit system;
|
inherit system;
|
||||||
|
@ -35,7 +33,7 @@
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
checks = {
|
checks = {
|
||||||
pre-commit-check = pre-commit-hooks.lib.${system}.run {
|
pre-commit-check = git-hooks.lib.${system}.run {
|
||||||
src = self;
|
src = self;
|
||||||
hooks = {
|
hooks = {
|
||||||
cargo-check = {
|
cargo-check = {
|
||||||
|
|
|
@ -8,12 +8,10 @@ use actix_identity::Identity;
|
||||||
use actix_web::{error, get, post, web, HttpRequest, Responder};
|
use actix_web::{error, get, post, web, HttpRequest, Responder};
|
||||||
use maud::html;
|
use maud::html;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use sqlx::PgPool;
|
use sqlx::{query_scalar, PgPool};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::frontend::templates::{self, datalist, forms, helpers::PageActionGroup, TemplateConfig};
|
use crate::frontend::templates::{self, datalist, forms, helpers::PageActionGroup, TemplateConfig};
|
||||||
use crate::manage;
|
|
||||||
use crate::models::*;
|
|
||||||
|
|
||||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.service(get).service(post);
|
cfg.service(get).service(post);
|
||||||
|
@ -130,51 +128,64 @@ async fn post(
|
||||||
user: Identity,
|
user: Identity,
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<impl Responder> {
|
||||||
let data = data.into_inner();
|
let data = data.into_inner();
|
||||||
let new_item = NewItem {
|
|
||||||
name: data.name,
|
|
||||||
class: data.class,
|
|
||||||
parent: data.parent,
|
|
||||||
original_packaging: data.original_packaging,
|
|
||||||
description: data.description,
|
|
||||||
};
|
|
||||||
if data.quantity == 1 {
|
if data.quantity == 1 {
|
||||||
let item = manage::item::add(&pool, new_item)
|
query_scalar!(
|
||||||
.await
|
"INSERT INTO items (name, parent, class, original_packaging, description)
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
VALUES ($1, $2, $3, $4, $5)
|
||||||
Ok(
|
RETURNING id",
|
||||||
web::Redirect::to("/item/".to_owned() + &item.id.to_string())
|
data.name,
|
||||||
|
data.parent,
|
||||||
|
data.class,
|
||||||
|
data.original_packaging,
|
||||||
|
data.description
|
||||||
|
)
|
||||||
|
.fetch_one(pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(error::ErrorInternalServerError)
|
||||||
|
.map(|id| {
|
||||||
|
web::Redirect::to("/item/".to_owned() + &id.to_string())
|
||||||
.see_other()
|
.see_other()
|
||||||
.respond_to(&req)
|
.respond_to(&req)
|
||||||
.map_into_boxed_body(),
|
.map_into_boxed_body()
|
||||||
)
|
})
|
||||||
} else {
|
} else {
|
||||||
let items = manage::item::add_multiple(&pool, new_item, data.quantity)
|
query_scalar!(
|
||||||
.await
|
"INSERT INTO items (name, parent, class, original_packaging, description)
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
SELECT * FROM UNNEST($1::VARCHAR[], $2::UUID[], $3::UUID[], $4::UUID[], $5::VARCHAR[])
|
||||||
Ok(templates::base(
|
RETURNING id",
|
||||||
TemplateConfig {
|
&vec![data.name; data.quantity] as &[Option<String>],
|
||||||
path: "/items/add",
|
&vec![data.parent; data.quantity] as &[Option<Uuid>],
|
||||||
title: Some("Added Items"),
|
&vec![data.class; data.quantity],
|
||||||
page_title: Some(Box::new("Added Items")),
|
&vec![data.original_packaging; data.quantity] as &[Option<Uuid>],
|
||||||
page_actions: vec![PageActionGroup::generate_labels(
|
&vec![data.description; data.quantity]
|
||||||
&items.iter().map(|i| i.id).collect::<Vec<Uuid>>(),
|
)
|
||||||
)],
|
.fetch_all(pool.as_ref())
|
||||||
user: Some(user),
|
.await
|
||||||
..Default::default()
|
.map_err(error::ErrorInternalServerError)
|
||||||
},
|
.map(|ids| {
|
||||||
html! {
|
templates::base(
|
||||||
ul {
|
TemplateConfig {
|
||||||
@for item in items {
|
path: "/items/add",
|
||||||
li {
|
title: Some("Added Items"),
|
||||||
a href={ "/item/" (item.id) } { (item.id) }
|
page_title: Some(Box::new("Added Items")),
|
||||||
|
page_actions: vec![PageActionGroup::generate_labels(&ids)],
|
||||||
|
user: Some(user),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
html! {
|
||||||
|
ul {
|
||||||
|
@for id in &ids {
|
||||||
|
li {
|
||||||
|
a href={ "/item/" (id) } { (id) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
a href="/items" { "Back to all items" }
|
a href="/items" { "Back to all items" }
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.respond_to(&req)
|
.respond_to(&req)
|
||||||
.map_into_boxed_body())
|
.map_into_boxed_body()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,9 @@
|
||||||
|
|
||||||
use actix_identity::Identity;
|
use actix_identity::Identity;
|
||||||
use actix_web::{error, post, web, Responder};
|
use actix_web::{error, post, web, Responder};
|
||||||
use sqlx::PgPool;
|
use sqlx::{query, PgPool};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::manage;
|
|
||||||
|
|
||||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.service(post);
|
cfg.service(post);
|
||||||
}
|
}
|
||||||
|
@ -21,7 +19,8 @@ async fn post(
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<impl Responder> {
|
||||||
let id = path.into_inner();
|
let id = path.into_inner();
|
||||||
|
|
||||||
manage::item::delete(&pool, id)
|
query!("DELETE FROM items WHERE id = $1", id)
|
||||||
|
.execute(pool.as_ref())
|
||||||
.await
|
.await
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
|
|
|
@ -7,17 +7,25 @@ use std::fmt::Display;
|
||||||
use actix_identity::Identity;
|
use actix_identity::Identity;
|
||||||
use actix_web::{error, get, post, web, Responder};
|
use actix_web::{error, get, post, web, Responder};
|
||||||
use maud::html;
|
use maud::html;
|
||||||
use sqlx::PgPool;
|
use serde::Deserialize;
|
||||||
|
use sqlx::{query, PgPool};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::frontend::templates::{self, datalist, forms, helpers::ItemName, TemplateConfig};
|
use crate::frontend::templates::{self, datalist, forms, helpers::ItemName, TemplateConfig};
|
||||||
use crate::manage;
|
|
||||||
use crate::models::*;
|
|
||||||
|
|
||||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.service(get).service(post);
|
cfg.service(get).service(post);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct ItemEditForm {
|
||||||
|
name: Option<String>,
|
||||||
|
parent: Option<Uuid>,
|
||||||
|
class: Uuid,
|
||||||
|
original_packaging: Option<Uuid>,
|
||||||
|
description: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/item/{id}/edit")]
|
#[get("/item/{id}/edit")]
|
||||||
async fn get(
|
async fn get(
|
||||||
pool: web::Data<PgPool>,
|
pool: web::Data<PgPool>,
|
||||||
|
@ -26,13 +34,35 @@ async fn get(
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<impl Responder> {
|
||||||
let id = path.into_inner();
|
let id = path.into_inner();
|
||||||
|
|
||||||
let item = manage::item::get(&pool, id)
|
let (item_name, form) = query!(
|
||||||
.await
|
r#"SELECT
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
items.name,
|
||||||
|
items.parent,
|
||||||
let item_class = manage::item_class::get(&pool, item.class)
|
items.class,
|
||||||
.await
|
item_classes.name AS "class_name",
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
items.original_packaging,
|
||||||
|
items.description
|
||||||
|
FROM items
|
||||||
|
JOIN item_classes
|
||||||
|
ON items.class = item_classes.id
|
||||||
|
WHERE items.id = $1"#,
|
||||||
|
id
|
||||||
|
)
|
||||||
|
.map(|row| {
|
||||||
|
(
|
||||||
|
ItemName::new(row.name.as_ref(), &row.class_name),
|
||||||
|
ItemEditForm {
|
||||||
|
name: row.name,
|
||||||
|
parent: row.parent,
|
||||||
|
class: row.class,
|
||||||
|
original_packaging: row.original_packaging,
|
||||||
|
description: row.description,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.fetch_one(pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
let datalist_items = datalist::items(&pool)
|
let datalist_items = datalist::items(&pool)
|
||||||
.await
|
.await
|
||||||
|
@ -42,13 +72,12 @@ async fn get(
|
||||||
.await
|
.await
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
let item_name = ItemName::new(item.name.as_ref(), &item_class.name);
|
|
||||||
let mut title = item_name.to_string();
|
let mut title = item_name.to_string();
|
||||||
title.push_str(" – Edit Item");
|
title.push_str(" – Edit Item");
|
||||||
|
|
||||||
Ok(templates::base(
|
Ok(templates::base(
|
||||||
TemplateConfig {
|
TemplateConfig {
|
||||||
path: &format!("/item/{}/edit", item.id),
|
path: &format!("/item/{}/edit", id),
|
||||||
title: Some(&title),
|
title: Some(&title),
|
||||||
page_title: Some(Box::new(item_name.clone())),
|
page_title: Some(Box::new(item_name.clone())),
|
||||||
datalists: vec![&datalist_items, &datalist_item_classes],
|
datalists: vec![&datalist_items, &datalist_item_classes],
|
||||||
|
@ -63,7 +92,7 @@ async fn get(
|
||||||
title: "UUID",
|
title: "UUID",
|
||||||
required: true,
|
required: true,
|
||||||
disabled: true,
|
disabled: true,
|
||||||
value: Some(&item.id),
|
value: Some(&id),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
(forms::InputGroup {
|
(forms::InputGroup {
|
||||||
|
@ -71,8 +100,8 @@ async fn get(
|
||||||
name: "name",
|
name: "name",
|
||||||
title: "Name",
|
title: "Name",
|
||||||
optional: true,
|
optional: true,
|
||||||
disabled: item.name.is_none(),
|
disabled: form.name.is_none(),
|
||||||
value: item.name.as_ref().map(|s| s as &dyn Display),
|
value: form.name.as_ref().map(|s| s as &dyn Display),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
(forms::InputGroup {
|
(forms::InputGroup {
|
||||||
|
@ -80,7 +109,7 @@ async fn get(
|
||||||
name: "class",
|
name: "class",
|
||||||
title: "Class",
|
title: "Class",
|
||||||
required: true,
|
required: true,
|
||||||
value: Some(&item.class),
|
value: Some(&form.class),
|
||||||
datalist: Some(&datalist_item_classes),
|
datalist: Some(&datalist_item_classes),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
|
@ -89,8 +118,8 @@ async fn get(
|
||||||
name: "parent",
|
name: "parent",
|
||||||
title: "Parent",
|
title: "Parent",
|
||||||
optional: true,
|
optional: true,
|
||||||
value: item.parent.as_ref().map(|id| id as &dyn Display),
|
value: form.parent.as_ref().map(|id| id as &dyn Display),
|
||||||
disabled: item.parent.is_none(),
|
disabled: form.parent.is_none(),
|
||||||
datalist: Some(&datalist_items),
|
datalist: Some(&datalist_items),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
|
@ -99,8 +128,8 @@ async fn get(
|
||||||
name: "original_packaging",
|
name: "original_packaging",
|
||||||
title: "Original Packaging",
|
title: "Original Packaging",
|
||||||
optional: true,
|
optional: true,
|
||||||
value: item.original_packaging.as_ref().map(|id| id as &dyn Display),
|
value: form.original_packaging.as_ref().map(|id| id as &dyn Display),
|
||||||
disabled: item.original_packaging.is_none(),
|
disabled: form.original_packaging.is_none(),
|
||||||
datalist: Some(&datalist_items),
|
datalist: Some(&datalist_items),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
|
@ -108,7 +137,7 @@ async fn get(
|
||||||
r#type: forms::InputType::Textarea,
|
r#type: forms::InputType::Textarea,
|
||||||
name: "description",
|
name: "description",
|
||||||
title: "Description ",
|
title: "Description ",
|
||||||
value: Some(&item.description),
|
value: Some(&form.description),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -122,14 +151,25 @@ async fn get(
|
||||||
async fn post(
|
async fn post(
|
||||||
pool: web::Data<PgPool>,
|
pool: web::Data<PgPool>,
|
||||||
path: web::Path<Uuid>,
|
path: web::Path<Uuid>,
|
||||||
data: web::Form<NewItem>,
|
data: web::Form<ItemEditForm>,
|
||||||
_user: Identity,
|
_user: Identity,
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<impl Responder> {
|
||||||
let id = path.into_inner();
|
let id = path.into_inner();
|
||||||
|
|
||||||
let item = manage::item::update(&pool, id, data.into_inner())
|
query!(
|
||||||
.await
|
"UPDATE items
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
SET name = $2, parent = $3, class = $4, original_packaging = $5, description = $6
|
||||||
|
WHERE id = $1",
|
||||||
|
id,
|
||||||
|
data.name,
|
||||||
|
data.parent,
|
||||||
|
data.class,
|
||||||
|
data.original_packaging,
|
||||||
|
data.description
|
||||||
|
)
|
||||||
|
.execute(pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
Ok(web::Redirect::to("/item/".to_owned() + &item.id.to_string()).see_other())
|
Ok(web::Redirect::to("/item/".to_owned() + &id.to_string()).see_other())
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,10 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use actix_identity::Identity;
|
use actix_identity::Identity;
|
||||||
use actix_web::{error, get, web, Responder};
|
use actix_web::{error, get, web, Responder};
|
||||||
use maud::html;
|
use maud::html;
|
||||||
use sqlx::PgPool;
|
use sqlx::{query, PgPool};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::frontend::templates::{
|
use crate::frontend::templates::{
|
||||||
|
@ -15,44 +13,73 @@ use crate::frontend::templates::{
|
||||||
helpers::{Colour, ItemName, ItemPreview, PageAction, PageActionGroup, PageActionMethod},
|
helpers::{Colour, ItemName, ItemPreview, PageAction, PageActionGroup, PageActionMethod},
|
||||||
TemplateConfig,
|
TemplateConfig,
|
||||||
};
|
};
|
||||||
use crate::manage;
|
|
||||||
use crate::models::*;
|
|
||||||
|
|
||||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.service(get);
|
cfg.service(get);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ItemListEntry {
|
||||||
|
id: Uuid,
|
||||||
|
name: ItemName,
|
||||||
|
class: Uuid,
|
||||||
|
class_name: String,
|
||||||
|
parents: Vec<ItemPreview>,
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/items")]
|
#[get("/items")]
|
||||||
async fn get(pool: web::Data<PgPool>, user: Identity) -> actix_web::Result<impl Responder> {
|
async fn get(pool: web::Data<PgPool>, user: Identity) -> actix_web::Result<impl Responder> {
|
||||||
let item_list = manage::item::get_all(&pool)
|
let items = query!(
|
||||||
.await
|
r#"
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
WITH RECURSIVE cte AS (
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
ARRAY[]::UUID[] AS parents,
|
||||||
|
ARRAY[]::VARCHAR[] AS parent_names,
|
||||||
|
ARRAY[]::VARCHAR[] AS parent_class_names
|
||||||
|
FROM items
|
||||||
|
WHERE parent IS NULL
|
||||||
|
|
||||||
let items = manage::item::get_all_as_map(&pool)
|
UNION
|
||||||
.await
|
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
|
||||||
|
|
||||||
let item_classes = manage::item_class::get_all_as_map(&pool)
|
SELECT
|
||||||
.await
|
items.id,
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
cte.parents || items.parent,
|
||||||
|
cte.parent_names || items.name,
|
||||||
let item_tree = manage::item::get_all_parents(&pool)
|
cte.parent_class_names || item_classes.name
|
||||||
.await
|
FROM items
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
JOIN cte
|
||||||
|
ON items.parent = cte.id
|
||||||
// TODO: remove clone (should be possible without it)
|
JOIN item_classes
|
||||||
let item_parents: HashMap<Uuid, Vec<Item>> = item_tree
|
ON items.class = item_classes.id
|
||||||
.iter()
|
)
|
||||||
.map(|(id, parent_ids)| {
|
SELECT
|
||||||
(
|
cte.id AS "id!",
|
||||||
*id,
|
items.name,
|
||||||
parent_ids
|
items.class,
|
||||||
.iter()
|
item_classes.name AS "class_name",
|
||||||
.map(|parent_id| items.get(parent_id).unwrap().clone())
|
cte.parents AS "parents!",
|
||||||
.collect(),
|
cte.parent_names AS "parent_names!: Vec<Option<String>>",
|
||||||
)
|
cte.parent_class_names AS "parent_class_names!"
|
||||||
})
|
FROM cte
|
||||||
.collect();
|
JOIN items
|
||||||
|
ON cte.id = items.id
|
||||||
|
JOIN item_classes
|
||||||
|
ON items.class = item_classes.id
|
||||||
|
ORDER BY items.created_at
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
.map(|row| ItemListEntry {
|
||||||
|
id: row.id,
|
||||||
|
name: ItemName::new(row.name.as_ref(), &row.class_name),
|
||||||
|
class: row.class,
|
||||||
|
class_name: row.class_name,
|
||||||
|
parents: itertools::izip!(row.parents, row.parent_names, row.parent_class_names)
|
||||||
|
.map(|(id, name, class_name)| ItemPreview::from_parts(id, name.as_ref(), &class_name))
|
||||||
|
.collect(),
|
||||||
|
})
|
||||||
|
.fetch_all(pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
Ok(templates::base(
|
Ok(templates::base(
|
||||||
TemplateConfig {
|
TemplateConfig {
|
||||||
|
@ -82,24 +109,11 @@ async fn get(pool: web::Data<PgPool>, user: Identity) -> actix_web::Result<impl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tbody {
|
tbody {
|
||||||
@for item in item_list {
|
@for item in items {
|
||||||
@let class = item_classes.get(&item.class).unwrap();
|
|
||||||
@let parents = item_parents.get(&item.id).unwrap();
|
|
||||||
tr {
|
tr {
|
||||||
td {
|
td { (ItemPreview::new(item.id, item.name.clone().terse())) }
|
||||||
(ItemPreview::new(item.id, ItemName::new(item.name.as_ref(), &class.name).terse()))
|
td { a href={ "/item-class/" (item.class) } { (item.class_name) } }
|
||||||
}
|
td { (templates::helpers::parents_breadcrumb(item.name, &item.parents, false)) }
|
||||||
td { a href={ "/item-class/" (class.id) } { (class.name) } }
|
|
||||||
td {
|
|
||||||
(templates::helpers::parents_breadcrumb(
|
|
||||||
ItemName::new(
|
|
||||||
item.name.as_ref(),
|
|
||||||
&class.name
|
|
||||||
),
|
|
||||||
&parents.iter().map(|parent| ItemPreview::from_parts(parent.id, parent.name.as_ref(), &item_classes.get(&parent.class).unwrap().name)).collect::<Vec<ItemPreview>>(),
|
|
||||||
false
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
use actix_identity::Identity;
|
use actix_identity::Identity;
|
||||||
use actix_web::{error, get, web, Responder};
|
use actix_web::{error, get, web, Responder};
|
||||||
use maud::html;
|
use maud::html;
|
||||||
use sqlx::PgPool;
|
use sqlx::{query, PgPool};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::frontend::templates::{
|
use crate::frontend::templates::{
|
||||||
|
@ -13,12 +13,21 @@ use crate::frontend::templates::{
|
||||||
helpers::{Colour, ItemName, ItemPreview, PageAction, PageActionGroup, PageActionMethod},
|
helpers::{Colour, ItemName, ItemPreview, PageAction, PageActionGroup, PageActionMethod},
|
||||||
TemplateConfig,
|
TemplateConfig,
|
||||||
};
|
};
|
||||||
use crate::manage;
|
|
||||||
|
|
||||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.service(get);
|
cfg.service(get);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ItemDetails {
|
||||||
|
id: Uuid,
|
||||||
|
short_id: i32,
|
||||||
|
name: ItemName,
|
||||||
|
class: Uuid,
|
||||||
|
class_name: String,
|
||||||
|
original_packaging: Option<ItemPreview>,
|
||||||
|
description: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/item/{id}")]
|
#[get("/item/{id}")]
|
||||||
async fn get(
|
async fn get(
|
||||||
pool: web::Data<PgPool>,
|
pool: web::Data<PgPool>,
|
||||||
|
@ -27,46 +36,96 @@ async fn get(
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<impl Responder> {
|
||||||
let id = path.into_inner();
|
let id = path.into_inner();
|
||||||
|
|
||||||
let item = manage::item::get(&pool, id)
|
let item = query!(
|
||||||
.await
|
r#"SELECT
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
items.id,
|
||||||
|
items.short_id,
|
||||||
|
items.name,
|
||||||
|
items.class,
|
||||||
|
item_classes.name AS "class_name",
|
||||||
|
items.original_packaging,
|
||||||
|
op.name AS "original_packaging_name?",
|
||||||
|
op_class.name AS "original_packaging_class_name?",
|
||||||
|
items.description
|
||||||
|
FROM items
|
||||||
|
JOIN item_classes
|
||||||
|
ON items.class = item_classes.id
|
||||||
|
LEFT JOIN items AS "op"
|
||||||
|
ON items.original_packaging = op.id
|
||||||
|
LEFT JOIN item_classes AS "op_class"
|
||||||
|
ON op.class = op_class.id
|
||||||
|
WHERE items.id = $1"#,
|
||||||
|
id
|
||||||
|
)
|
||||||
|
.map(|row| ItemDetails {
|
||||||
|
id: row.id,
|
||||||
|
short_id: row.short_id,
|
||||||
|
name: ItemName::new(row.name.as_ref(), &row.class_name),
|
||||||
|
class: row.class,
|
||||||
|
class_name: row.class_name,
|
||||||
|
original_packaging: row.original_packaging.map(|id| {
|
||||||
|
ItemPreview::from_parts(
|
||||||
|
id,
|
||||||
|
row.original_packaging_name.as_ref(),
|
||||||
|
&row.original_packaging_class_name.unwrap(),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
description: row.description,
|
||||||
|
})
|
||||||
|
.fetch_one(pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
let item_classes = manage::item_class::get_all_as_map(&pool)
|
let parents = query!(
|
||||||
.await
|
r#"SELECT items.id, items.name, item_classes.name AS "class_name"
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
FROM items
|
||||||
|
JOIN unnest((SELECT parents FROM item_tree WHERE id = $1))
|
||||||
|
WITH ORDINALITY AS parents(id, n)
|
||||||
|
ON items.id = parents.id
|
||||||
|
JOIN item_classes
|
||||||
|
ON items.class = item_classes.id
|
||||||
|
ORDER BY parents.n"#,
|
||||||
|
id
|
||||||
|
)
|
||||||
|
.map(|row| ItemPreview::from_parts(row.id, row.name.as_ref(), &row.class_name))
|
||||||
|
.fetch_all(pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
let parents = manage::item::get_parents_details(&pool, item.id)
|
let children = query!(
|
||||||
.await
|
r#"SELECT items.id, items.name, item_classes.name AS "class_name"
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
FROM items
|
||||||
|
JOIN item_classes
|
||||||
|
ON items.class = item_classes.id
|
||||||
|
WHERE items.parent = $1"#,
|
||||||
|
id
|
||||||
|
)
|
||||||
|
.map(|row| ItemPreview::from_parts(row.id, row.name.as_ref(), &row.class_name))
|
||||||
|
.fetch_all(pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
let children = manage::item::get_children(&pool, item.id)
|
let original_packaging_of = query!(
|
||||||
.await
|
r#"SELECT items.id, items.name, item_classes.name AS "class_name"
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
FROM items
|
||||||
|
JOIN item_classes
|
||||||
|
ON items.class = item_classes.id
|
||||||
|
WHERE items.original_packaging = $1"#,
|
||||||
|
id
|
||||||
|
)
|
||||||
|
.map(|row| ItemPreview::from_parts(row.id, row.name.as_ref(), &row.class_name))
|
||||||
|
.fetch_all(pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
let original_packaging = match item.original_packaging {
|
let mut title = item.name.to_string();
|
||||||
Some(id) => Some(
|
|
||||||
manage::item::get(&pool, id)
|
|
||||||
.await
|
|
||||||
.map_err(error::ErrorInternalServerError)?,
|
|
||||||
),
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let original_packaging_of = manage::item::original_packaging_contents(&pool, id)
|
|
||||||
.await
|
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
|
||||||
|
|
||||||
let item_class = item_classes.get(&item.class).unwrap();
|
|
||||||
|
|
||||||
let item_name = ItemName::new(item.name.as_ref(), &item_class.name);
|
|
||||||
let mut title = item_name.to_string();
|
|
||||||
title.push_str(" – Item Details");
|
title.push_str(" – Item Details");
|
||||||
|
|
||||||
Ok(templates::base(
|
Ok(templates::base(
|
||||||
TemplateConfig {
|
TemplateConfig {
|
||||||
path: &format!("/item/{}", item.id),
|
path: &format!("/item/{}", item.id),
|
||||||
title: Some(&title),
|
title: Some(&title),
|
||||||
page_title: Some(Box::new(item_name.clone())),
|
page_title: Some(Box::new(item.name.clone())),
|
||||||
page_actions: vec![
|
page_actions: vec![
|
||||||
(PageActionGroup::Button {
|
(PageActionGroup::Button {
|
||||||
action: PageAction {
|
action: PageAction {
|
||||||
|
@ -109,32 +168,21 @@ async fn get(
|
||||||
}
|
}
|
||||||
tr {
|
tr {
|
||||||
th { "Name" }
|
th { "Name" }
|
||||||
td { (item_name.clone().terse()) }
|
td { (item.name.clone().terse()) }
|
||||||
}
|
}
|
||||||
tr {
|
tr {
|
||||||
th { "Class" }
|
th { "Class" }
|
||||||
td { a href={ "/item-class/" (item.class) } { (item_class.name) } }
|
td { a href={ "/item-class/" (item.class) } { (item.class_name) } }
|
||||||
}
|
}
|
||||||
tr {
|
tr {
|
||||||
th { "Parents" }
|
th { "Parents" }
|
||||||
td {
|
td { (templates::helpers::parents_breadcrumb(item.name, &parents, true)) }
|
||||||
(templates::helpers::parents_breadcrumb(
|
|
||||||
ItemName::new(
|
|
||||||
item.name.as_ref(),
|
|
||||||
&item_class.name
|
|
||||||
),
|
|
||||||
&parents.iter().map(|parent| ItemPreview::from_parts(parent.id, parent.name.as_ref(), &item_classes.get(&parent.class).unwrap().name)).collect::<Vec<ItemPreview>>(),
|
|
||||||
true
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
tr {
|
tr {
|
||||||
th { "Original Packaging" }
|
th { "Original Packaging" }
|
||||||
td {
|
td {
|
||||||
@if let Some(original_packaging) = original_packaging {
|
@if let Some(original_packaging) = item.original_packaging {
|
||||||
a
|
(original_packaging)
|
||||||
href={ "/item/" (original_packaging.id) }
|
|
||||||
{ (ItemName::new(original_packaging.name.as_ref(), &item_classes.get(&original_packaging.class).unwrap().name)) }
|
|
||||||
} @else {
|
} @else {
|
||||||
"-"
|
"-"
|
||||||
}
|
}
|
||||||
|
@ -153,16 +201,14 @@ async fn get(
|
||||||
}
|
}
|
||||||
div {
|
div {
|
||||||
(PageActionGroup::generate_labels(
|
(PageActionGroup::generate_labels(
|
||||||
&children.iter().map(|i| i.id).collect::<Vec<Uuid>>(),
|
&children.iter().map(|ip| ip.id).collect::<Vec<Uuid>>(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
@for child in children {
|
@for child in children {
|
||||||
li {
|
li { (child) }
|
||||||
(ItemPreview::from_parts(child.id, child.name.as_ref(), &item_classes.get(&child.class).unwrap().name))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,9 +218,7 @@ async fn get(
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
@for item in original_packaging_of {
|
@for item in original_packaging_of {
|
||||||
li {
|
li { (item) }
|
||||||
(ItemPreview::from_parts(item.id, item.name.as_ref(), &item_classes.get(&item.class).unwrap().name))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,10 @@ use actix_identity::Identity;
|
||||||
use actix_web::{error, get, post, web, Responder};
|
use actix_web::{error, get, post, web, Responder};
|
||||||
use maud::html;
|
use maud::html;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use sqlx::PgPool;
|
use sqlx::{query_scalar, PgPool};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::frontend::templates::{self, datalist, forms, TemplateConfig};
|
use crate::frontend::templates::{self, datalist, forms, TemplateConfig};
|
||||||
use crate::manage;
|
|
||||||
use crate::models::*;
|
|
||||||
|
|
||||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.service(get).service(post);
|
cfg.service(get).service(post);
|
||||||
|
@ -93,15 +91,18 @@ async fn post(
|
||||||
_user: Identity,
|
_user: Identity,
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<impl Responder> {
|
||||||
let data = data.into_inner();
|
let data = data.into_inner();
|
||||||
let item = manage::item_class::add(
|
|
||||||
&pool,
|
let id = query_scalar!(
|
||||||
NewItemClass {
|
"INSERT INTO item_classes (name, parent, description)
|
||||||
name: data.name,
|
VALUES ($1, $2, $3)
|
||||||
parent: data.parent,
|
RETURNING id",
|
||||||
description: data.description,
|
data.name,
|
||||||
},
|
data.parent,
|
||||||
|
data.description
|
||||||
)
|
)
|
||||||
|
.fetch_one(pool.as_ref())
|
||||||
.await
|
.await
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
Ok(web::Redirect::to("/item-class/".to_owned() + &item.id.to_string()).see_other())
|
|
||||||
|
Ok(web::Redirect::to("/item-class/".to_owned() + &id.to_string()).see_other())
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,9 @@
|
||||||
|
|
||||||
use actix_identity::Identity;
|
use actix_identity::Identity;
|
||||||
use actix_web::{error, post, web, Responder};
|
use actix_web::{error, post, web, Responder};
|
||||||
use sqlx::PgPool;
|
use sqlx::{query, PgPool};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::manage;
|
|
||||||
|
|
||||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.service(post);
|
cfg.service(post);
|
||||||
}
|
}
|
||||||
|
@ -21,7 +19,8 @@ async fn post(
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<impl Responder> {
|
||||||
let id = path.into_inner();
|
let id = path.into_inner();
|
||||||
|
|
||||||
manage::item_class::delete(&pool, id)
|
query!("DELETE FROM item_classes WHERE id = $1", id)
|
||||||
|
.execute(pool.as_ref())
|
||||||
.await
|
.await
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
|
|
|
@ -7,17 +7,23 @@ use std::fmt::Display;
|
||||||
use actix_identity::Identity;
|
use actix_identity::Identity;
|
||||||
use actix_web::{error, get, post, web, Responder};
|
use actix_web::{error, get, post, web, Responder};
|
||||||
use maud::html;
|
use maud::html;
|
||||||
use sqlx::PgPool;
|
use serde::Deserialize;
|
||||||
|
use sqlx::{query, query_as, PgPool};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::frontend::templates::{self, datalist, forms, TemplateConfig};
|
use crate::frontend::templates::{self, datalist, forms, TemplateConfig};
|
||||||
use crate::manage;
|
|
||||||
use crate::models::*;
|
|
||||||
|
|
||||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.service(get).service(post);
|
cfg.service(get).service(post);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct ItemClassEditForm {
|
||||||
|
name: String,
|
||||||
|
parent: Option<Uuid>,
|
||||||
|
description: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/item-class/{id}/edit")]
|
#[get("/item-class/{id}/edit")]
|
||||||
async fn get(
|
async fn get(
|
||||||
pool: web::Data<PgPool>,
|
pool: web::Data<PgPool>,
|
||||||
|
@ -26,22 +32,27 @@ async fn get(
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<impl Responder> {
|
||||||
let id = path.into_inner();
|
let id = path.into_inner();
|
||||||
|
|
||||||
let item_class = manage::item_class::get(&pool, id)
|
let form = query_as!(
|
||||||
.await
|
ItemClassEditForm,
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
"SELECT name, parent, description FROM item_classes WHERE id = $1",
|
||||||
|
id
|
||||||
|
)
|
||||||
|
.fetch_one(pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
let datalist_item_classes = datalist::item_classes(&pool)
|
let datalist_item_classes = datalist::item_classes(&pool)
|
||||||
.await
|
.await
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
let mut title = item_class.name.clone();
|
let mut title = form.name.clone();
|
||||||
title.push_str(" – Item Details");
|
title.push_str(" – Item Details");
|
||||||
|
|
||||||
Ok(templates::base(
|
Ok(templates::base(
|
||||||
TemplateConfig {
|
TemplateConfig {
|
||||||
path: &format!("/items-class/{}/add", id),
|
path: &format!("/items-class/{}/add", id),
|
||||||
title: Some(&title),
|
title: Some(&title),
|
||||||
page_title: Some(Box::new(item_class.name.clone())),
|
page_title: Some(Box::new(form.name.clone())),
|
||||||
datalists: vec![&datalist_item_classes],
|
datalists: vec![&datalist_item_classes],
|
||||||
user: Some(user),
|
user: Some(user),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -54,7 +65,7 @@ async fn get(
|
||||||
title: "UUID",
|
title: "UUID",
|
||||||
disabled: true,
|
disabled: true,
|
||||||
required: true,
|
required: true,
|
||||||
value: Some(&item_class.id),
|
value: Some(&id),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
(forms::InputGroup {
|
(forms::InputGroup {
|
||||||
|
@ -62,7 +73,7 @@ async fn get(
|
||||||
name: "name",
|
name: "name",
|
||||||
title: "Name",
|
title: "Name",
|
||||||
required: true,
|
required: true,
|
||||||
value: Some(&item_class.name),
|
value: Some(&form.name),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
(forms::InputGroup {
|
(forms::InputGroup {
|
||||||
|
@ -70,8 +81,8 @@ async fn get(
|
||||||
name: "parent",
|
name: "parent",
|
||||||
title: "Parent",
|
title: "Parent",
|
||||||
optional: true,
|
optional: true,
|
||||||
disabled: item_class.parent.is_none(),
|
disabled: form.parent.is_none(),
|
||||||
value: item_class.parent.as_ref().map(|id| id as &dyn Display),
|
value: form.parent.as_ref().map(|id| id as &dyn Display),
|
||||||
datalist: Some(&datalist_item_classes),
|
datalist: Some(&datalist_item_classes),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
|
@ -79,7 +90,7 @@ async fn get(
|
||||||
r#type: forms::InputType::Textarea,
|
r#type: forms::InputType::Textarea,
|
||||||
name: "description",
|
name: "description",
|
||||||
title: "Description ",
|
title: "Description ",
|
||||||
value: Some(&item_class.description),
|
value: Some(&form.description),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -93,14 +104,23 @@ async fn get(
|
||||||
async fn post(
|
async fn post(
|
||||||
pool: web::Data<PgPool>,
|
pool: web::Data<PgPool>,
|
||||||
path: web::Path<Uuid>,
|
path: web::Path<Uuid>,
|
||||||
data: web::Form<NewItemClass>,
|
data: web::Form<ItemClassEditForm>,
|
||||||
_user: Identity,
|
_user: Identity,
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<impl Responder> {
|
||||||
let id = path.into_inner();
|
let id = path.into_inner();
|
||||||
|
|
||||||
let item_class = manage::item_class::update(&pool, id, data.into_inner())
|
query!(
|
||||||
.await
|
"UPDATE item_classes
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
SET name = $2, parent = $3, description = $4
|
||||||
|
WHERE id = $1",
|
||||||
|
id,
|
||||||
|
data.name,
|
||||||
|
data.parent,
|
||||||
|
data.description
|
||||||
|
)
|
||||||
|
.execute(pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
Ok(web::Redirect::to("/item-class/".to_owned() + &item_class.id.to_string()).see_other())
|
Ok(web::Redirect::to("/item-class/".to_owned() + &id.to_string()).see_other())
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,29 +5,45 @@
|
||||||
use actix_identity::Identity;
|
use actix_identity::Identity;
|
||||||
use actix_web::{error, get, web, Responder};
|
use actix_web::{error, get, web, Responder};
|
||||||
use maud::html;
|
use maud::html;
|
||||||
use sqlx::PgPool;
|
use sqlx::{query, PgPool};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::frontend::templates::{
|
use crate::frontend::templates::{
|
||||||
self,
|
self,
|
||||||
helpers::{Colour, PageAction, PageActionGroup, PageActionMethod},
|
helpers::{Colour, ItemClassPreview, PageAction, PageActionGroup, PageActionMethod},
|
||||||
TemplateConfig,
|
TemplateConfig,
|
||||||
};
|
};
|
||||||
use crate::manage;
|
|
||||||
|
|
||||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.service(get);
|
cfg.service(get);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ItemClassListEntry {
|
||||||
|
id: Uuid,
|
||||||
|
name: String,
|
||||||
|
parent: Option<ItemClassPreview>,
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/item-classes")]
|
#[get("/item-classes")]
|
||||||
async fn get(pool: web::Data<PgPool>, user: Identity) -> actix_web::Result<impl Responder> {
|
async fn get(pool: web::Data<PgPool>, user: Identity) -> actix_web::Result<impl Responder> {
|
||||||
let item_classes_ids = sqlx::query_scalar!("SELECT id FROM item_classes ORDER BY created_at")
|
let item_classes = query!(
|
||||||
.fetch_all(pool.as_ref())
|
r#"SELECT class.id, class.name, class.parent, parent.name AS "parent_name?"
|
||||||
.await
|
FROM item_classes AS "class"
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
LEFT JOIN item_classes AS "parent"
|
||||||
|
ON class.parent = parent.id
|
||||||
let item_classes = manage::item_class::get_all_as_map(&pool)
|
ORDER BY class.created_at
|
||||||
.await
|
"#
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
)
|
||||||
|
.map(|row| ItemClassListEntry {
|
||||||
|
id: row.id,
|
||||||
|
name: row.name,
|
||||||
|
parent: row
|
||||||
|
.parent
|
||||||
|
.map(|id| ItemClassPreview::new(id, row.parent_name.unwrap())),
|
||||||
|
})
|
||||||
|
.fetch_all(pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
Ok(templates::base(
|
Ok(templates::base(
|
||||||
TemplateConfig {
|
TemplateConfig {
|
||||||
|
@ -56,14 +72,12 @@ async fn get(pool: web::Data<PgPool>, user: Identity) -> actix_web::Result<impl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tbody {
|
tbody {
|
||||||
@for item_class in item_classes_ids {
|
@for item_class in item_classes {
|
||||||
@let item_class = item_classes.get(&item_class).unwrap();
|
|
||||||
tr {
|
tr {
|
||||||
td { a href={ "/item-class/" (item_class.id) } { (item_class.name) } }
|
td { (ItemClassPreview::new(item_class.id, item_class.name)) }
|
||||||
td {
|
td {
|
||||||
@if let Some(parent) = item_class.parent {
|
@if let Some(parent) = item_class.parent {
|
||||||
@let parent = item_classes.get(&parent).unwrap();
|
(parent)
|
||||||
a href={ "/item-class/" (parent.id) } { (parent.name) }
|
|
||||||
} @else {
|
} @else {
|
||||||
"-"
|
"-"
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,20 +5,28 @@
|
||||||
use actix_identity::Identity;
|
use actix_identity::Identity;
|
||||||
use actix_web::{error, get, web, Responder};
|
use actix_web::{error, get, web, Responder};
|
||||||
use maud::html;
|
use maud::html;
|
||||||
use sqlx::PgPool;
|
use sqlx::{query, query_as, PgPool};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::frontend::templates::{
|
use crate::frontend::templates::{
|
||||||
self,
|
self,
|
||||||
helpers::{Colour, ItemName, ItemPreview, PageAction, PageActionGroup, PageActionMethod},
|
helpers::{
|
||||||
|
Colour, ItemClassPreview, ItemPreview, PageAction, PageActionGroup, PageActionMethod,
|
||||||
|
},
|
||||||
TemplateConfig,
|
TemplateConfig,
|
||||||
};
|
};
|
||||||
use crate::manage;
|
|
||||||
|
|
||||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.service(get);
|
cfg.service(get);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ItemClassDetails {
|
||||||
|
id: Uuid,
|
||||||
|
name: String,
|
||||||
|
description: String,
|
||||||
|
parent: Option<ItemClassPreview>,
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/item-class/{id}")]
|
#[get("/item-class/{id}")]
|
||||||
async fn get(
|
async fn get(
|
||||||
pool: web::Data<PgPool>,
|
pool: web::Data<PgPool>,
|
||||||
|
@ -27,26 +35,52 @@ async fn get(
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<impl Responder> {
|
||||||
let id = path.into_inner();
|
let id = path.into_inner();
|
||||||
|
|
||||||
let item_class = manage::item_class::get(&pool, id)
|
let item_class = query!(
|
||||||
.await
|
r#"SELECT
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
class.id,
|
||||||
|
class.name,
|
||||||
|
class.description,
|
||||||
|
class.parent,
|
||||||
|
parent.name AS "parent_name?"
|
||||||
|
FROM item_classes AS "class"
|
||||||
|
LEFT JOIN item_classes AS "parent"
|
||||||
|
ON class.parent = parent.id
|
||||||
|
WHERE class.id = $1"#,
|
||||||
|
id
|
||||||
|
)
|
||||||
|
.map(|row| ItemClassDetails {
|
||||||
|
id: row.id,
|
||||||
|
name: row.name,
|
||||||
|
description: row.description,
|
||||||
|
parent: row
|
||||||
|
.parent
|
||||||
|
.map(|id| ItemClassPreview::new(id, row.parent_name.unwrap())),
|
||||||
|
})
|
||||||
|
.fetch_one(pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
// TODO: Once async closures are stable, use map_or on item_class.parent instead
|
let children = query_as!(
|
||||||
let parent = match item_class.parent {
|
ItemClassPreview,
|
||||||
Some(id) => manage::item_class::get(&pool, id)
|
"SELECT id, name FROM item_classes WHERE parent = $1",
|
||||||
.await
|
id
|
||||||
.map(Some)
|
)
|
||||||
.map_err(error::ErrorInternalServerError)?,
|
.fetch_all(pool.as_ref())
|
||||||
None => None,
|
.await
|
||||||
};
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
let children = manage::item_class::children(&pool, id)
|
let items = query!(
|
||||||
.await
|
r#"SELECT items.id, items.name, item_classes.name AS "class_name"
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
FROM items
|
||||||
|
JOIN item_classes
|
||||||
let items = manage::item_class::items(&pool, id)
|
ON items.class = item_classes.id
|
||||||
.await
|
WHERE items.class = $1"#,
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
id
|
||||||
|
)
|
||||||
|
.map(|row| ItemPreview::from_parts(row.id, row.name.as_ref(), &row.class_name))
|
||||||
|
.fetch_all(pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
let mut title = item_class.name.clone();
|
let mut title = item_class.name.clone();
|
||||||
title.push_str(" – Item Details");
|
title.push_str(" – Item Details");
|
||||||
|
@ -107,10 +141,10 @@ async fn get(
|
||||||
th { "Name" }
|
th { "Name" }
|
||||||
td { (item_class.name) }
|
td { (item_class.name) }
|
||||||
}
|
}
|
||||||
@if let Some(parent) = parent {
|
@if let Some(parent) = item_class.parent {
|
||||||
tr {
|
tr {
|
||||||
th { "Parent" }
|
th { "Parent" }
|
||||||
td { a href={ "/item-class/" (parent.id) } { (parent.name) } }
|
td { (parent) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tr {
|
tr {
|
||||||
|
@ -124,9 +158,7 @@ async fn get(
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
@for child in children {
|
@for child in children {
|
||||||
li {
|
li { (child) }
|
||||||
a href={ "/item-class/" (child.id) } { (child.name) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,9 +177,7 @@ async fn get(
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
@for item in items {
|
@for item in items {
|
||||||
li {
|
li { (item) }
|
||||||
(ItemPreview::new(item.id, ItemName::new(item.name.as_ref(), &item_class.name).terse()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,16 +5,19 @@
|
||||||
use actix_identity::Identity;
|
use actix_identity::Identity;
|
||||||
use actix_web::{error, get, web, Responder};
|
use actix_web::{error, get, web, Responder};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use sqlx::PgPool;
|
use sqlx::{query, query_scalar, PgPool};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::manage;
|
|
||||||
use crate::models::EntityType;
|
|
||||||
|
|
||||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.service(get);
|
cfg.service(get);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub enum EntityType {
|
||||||
|
Item,
|
||||||
|
ItemClass,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct JumpData {
|
struct JumpData {
|
||||||
id: String,
|
id: String,
|
||||||
|
@ -29,15 +32,29 @@ async fn get(
|
||||||
let mut id = data.id.clone();
|
let mut id = data.id.clone();
|
||||||
|
|
||||||
let entity_type = if let Ok(id) = Uuid::parse_str(&id) {
|
let entity_type = if let Ok(id) = Uuid::parse_str(&id) {
|
||||||
manage::query_entity_type(&pool, id)
|
query!(
|
||||||
.await
|
r#"SELECT type as "type!"
|
||||||
.map_err(error::ErrorInternalServerError)?
|
FROM (SELECT id, 'item' AS "type" FROM items
|
||||||
|
UNION ALL
|
||||||
|
SELECT id, 'item_class' AS "type" FROM item_classes) id_mapping
|
||||||
|
WHERE id = $1"#,
|
||||||
|
id
|
||||||
|
)
|
||||||
|
.map(|row| match row.r#type.as_str() {
|
||||||
|
"item" => EntityType::Item,
|
||||||
|
"item_class" => EntityType::ItemClass,
|
||||||
|
_ => unreachable!("database returned impossible type"),
|
||||||
|
})
|
||||||
|
.fetch_optional(pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(error::ErrorInternalServerError)?
|
||||||
} else if let Ok(short_id) = id.parse::<i32>() {
|
} else if let Ok(short_id) = id.parse::<i32>() {
|
||||||
if let Ok(item) = manage::item::get_by_short_id(&pool, short_id)
|
if let Ok(id_) = query_scalar!("SELECT id FROM items WHERE short_id = $1", short_id)
|
||||||
|
.fetch_one(pool.as_ref())
|
||||||
.await
|
.await
|
||||||
.map_err(error::ErrorInternalServerError)
|
.map_err(error::ErrorInternalServerError)
|
||||||
{
|
{
|
||||||
id = item.id.to_string();
|
id = id_.to_string();
|
||||||
Some(EntityType::Item)
|
Some(EntityType::Item)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -7,12 +7,12 @@ use actix_web::{error, get, post, web, Responder};
|
||||||
use maud::html;
|
use maud::html;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_variant::to_variant_name;
|
use serde_variant::to_variant_name;
|
||||||
use sqlx::PgPool;
|
use sqlx::{query, PgPool};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::templates::{self, datalist, helpers::ItemName, TemplateConfig};
|
use super::templates::{self, datalist, TemplateConfig};
|
||||||
|
use crate::frontend::templates::helpers::ItemPreview;
|
||||||
use crate::label::{Label, LabelPreset};
|
use crate::label::{Label, LabelPreset};
|
||||||
use crate::manage;
|
|
||||||
|
|
||||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.service(generate_post)
|
cfg.service(generate_post)
|
||||||
|
@ -35,11 +35,9 @@ async fn generate(pool: &PgPool, params: GenerateParams) -> actix_web::Result<im
|
||||||
.collect::<Result<Vec<Uuid>, uuid::Error>>()
|
.collect::<Result<Vec<Uuid>, uuid::Error>>()
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
let items = manage::item::get_multiple(pool, &ids)
|
Label::for_items(pool, &ids, params.preset.clone().into())
|
||||||
.await
|
.await
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
.map_err(error::ErrorInternalServerError)
|
||||||
|
|
||||||
Ok(Label::for_items(&items, params.preset.clone().into()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/labels/generate")]
|
#[post("/labels/generate")]
|
||||||
|
@ -62,13 +60,16 @@ async fn generate_get(
|
||||||
|
|
||||||
#[get("/labels")]
|
#[get("/labels")]
|
||||||
async fn form(pool: web::Data<PgPool>, user: Identity) -> actix_web::Result<impl Responder> {
|
async fn form(pool: web::Data<PgPool>, user: Identity) -> actix_web::Result<impl Responder> {
|
||||||
let items = manage::item::get_all(&pool)
|
let items = query!(
|
||||||
.await
|
r#"SELECT items.id, items.name, item_classes.name AS "class_name"
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
FROM items
|
||||||
|
JOIN item_classes
|
||||||
let item_classes = manage::item_class::get_all_as_map(&pool)
|
ON items.class = item_classes.id"#
|
||||||
.await
|
)
|
||||||
.map_err(error::ErrorInternalServerError)?;
|
.map(|row| ItemPreview::from_parts(row.id, row.name.as_ref(), &row.class_name))
|
||||||
|
.fetch_all(pool.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
let datalist_items = datalist::items(&pool)
|
let datalist_items = datalist::items(&pool)
|
||||||
.await
|
.await
|
||||||
|
@ -120,8 +121,7 @@ async fn form(pool: web::Data<PgPool>, user: Identity) -> actix_web::Result<impl
|
||||||
label .form-label for="ids-multiselect" { "Items" }
|
label .form-label for="ids-multiselect" { "Items" }
|
||||||
select #ids-multiselect .form-select multiple size="15" {
|
select #ids-multiselect .form-select multiple size="15" {
|
||||||
@for item in items {
|
@for item in items {
|
||||||
@let item_name = ItemName::new(item.name.as_ref(), &item_classes.get(&item.class).unwrap().name);
|
option value={ (item.id) } { (item.name) " (" (item.id) ")" }
|
||||||
option value={ (item.id) } { (item_name.to_string()) " (" (item.id) ")" }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,9 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
use maud::{html, Markup, Render};
|
use maud::{html, Markup, Render};
|
||||||
use sqlx::PgPool;
|
use sqlx::{query, PgPool};
|
||||||
|
|
||||||
use super::helpers::ItemName;
|
use super::helpers::ItemName;
|
||||||
use crate::manage;
|
|
||||||
|
|
||||||
pub struct Datalist {
|
pub struct Datalist {
|
||||||
name: String,
|
name: String,
|
||||||
|
@ -44,23 +43,23 @@ impl Render for DatalistOption {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn items(pool: &PgPool) -> Result<Datalist, sqlx::Error> {
|
pub async fn items(pool: &PgPool) -> Result<Datalist, sqlx::Error> {
|
||||||
let items = manage::item::get_all(pool).await?;
|
|
||||||
|
|
||||||
let item_classes = manage::item_class::get_all_as_map(pool).await?;
|
|
||||||
|
|
||||||
Ok(Datalist {
|
Ok(Datalist {
|
||||||
name: "items".to_string(),
|
name: "items".to_string(),
|
||||||
link_prefix: Some("/item/".to_string()),
|
link_prefix: Some("/item/".to_string()),
|
||||||
options: items
|
options: query!(
|
||||||
.iter()
|
r#"SELECT items.id, items.name, item_classes.name AS "class_name"
|
||||||
.map(|i| DatalistOption {
|
FROM items
|
||||||
value: i.id.to_string(),
|
JOIN item_classes
|
||||||
text: Box::new(ItemName::new(
|
ON items.class = item_classes.id"#
|
||||||
i.name.as_ref(),
|
)
|
||||||
&item_classes.get(&i.class).unwrap().name,
|
.fetch_all(pool)
|
||||||
)),
|
.await?
|
||||||
})
|
.into_iter()
|
||||||
.collect(),
|
.map(|row| DatalistOption {
|
||||||
|
value: row.id.to_string(),
|
||||||
|
text: Box::new(ItemName::new(row.name.as_ref(), &row.class_name)),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,12 +67,13 @@ pub async fn item_classes(pool: &PgPool) -> Result<Datalist, sqlx::Error> {
|
||||||
Ok(Datalist {
|
Ok(Datalist {
|
||||||
name: "item-classes".to_string(),
|
name: "item-classes".to_string(),
|
||||||
link_prefix: Some("/item-class/".to_string()),
|
link_prefix: Some("/item-class/".to_string()),
|
||||||
options: manage::item_class::get_all(pool)
|
options: query!("SELECT id, name FROM item_classes")
|
||||||
|
.fetch_all(pool)
|
||||||
.await?
|
.await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|ic| DatalistOption {
|
.map(|row| DatalistOption {
|
||||||
value: ic.id.to_string(),
|
value: row.id.to_string(),
|
||||||
text: Box::new(ic.name),
|
text: Box::new(row.name),
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
})
|
})
|
||||||
|
|
|
@ -157,6 +157,25 @@ impl Render for ItemPreview {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ItemClassPreview {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ItemClassPreview {
|
||||||
|
pub fn new(id: Uuid, name: String) -> Self {
|
||||||
|
Self { id, name }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Render for ItemClassPreview {
|
||||||
|
fn render(&self) -> Markup {
|
||||||
|
html! {
|
||||||
|
a href={ "/item-class/" (self.id) } { (self.name) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub enum PageActionMethod {
|
pub enum PageActionMethod {
|
||||||
Get,
|
Get,
|
||||||
Post,
|
Post,
|
||||||
|
|
|
@ -15,7 +15,6 @@ use helpers::*;
|
||||||
const BRANDING: &str = "li7y";
|
const BRANDING: &str = "li7y";
|
||||||
|
|
||||||
const NAVBAR_ITEMS: &[(&str, &str)] = &[
|
const NAVBAR_ITEMS: &[(&str, &str)] = &[
|
||||||
("/", "Home"),
|
|
||||||
("/items", "Items"),
|
("/items", "Items"),
|
||||||
("/item-classes", "Item Classes"),
|
("/item-classes", "Item Classes"),
|
||||||
("/labels", "Labels"),
|
("/labels", "Labels"),
|
||||||
|
|
|
@ -12,10 +12,10 @@ use barcode::{encode_code128, encode_data_matrix};
|
||||||
use pdf::{IndirectFontRef, PdfLayerReference};
|
use pdf::{IndirectFontRef, PdfLayerReference};
|
||||||
use printpdf as pdf;
|
use printpdf as pdf;
|
||||||
use printpdf::{ImageTransform, Mm, PdfDocument, PdfDocumentReference, Pt, Px};
|
use printpdf::{ImageTransform, Mm, PdfDocument, PdfDocumentReference, Pt, Px};
|
||||||
|
use sqlx::{query_as, PgPool};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::models::Item;
|
|
||||||
pub use preset::LabelPreset;
|
pub use preset::LabelPreset;
|
||||||
|
|
||||||
const FONT: Cursor<&[u8]> = Cursor::new(include_bytes!(
|
const FONT: Cursor<&[u8]> = Cursor::new(include_bytes!(
|
||||||
|
@ -247,16 +247,18 @@ impl Label {
|
||||||
Ok(doc.ok_or(Error::NoPages)?.save_to_bytes()?)
|
Ok(doc.ok_or(Error::NoPages)?.save_to_bytes()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_items(items: &[Item], config: LabelConfig) -> Self {
|
pub async fn for_items(pool: &PgPool, ids: &[Uuid], config: LabelConfig) -> sqlx::Result<Self> {
|
||||||
Label {
|
Ok(Label {
|
||||||
pages: items
|
pages: query_as!(
|
||||||
.iter()
|
LabelPage,
|
||||||
.map(|item| LabelPage {
|
r#"SELECT id AS "id?", to_char(short_id, '000000') AS "short_id?"
|
||||||
id: Some(item.id),
|
FROM items
|
||||||
short_id: Some(format!("{:06}", item.short_id)),
|
WHERE id = ANY ($1)"#,
|
||||||
})
|
ids
|
||||||
.collect(),
|
)
|
||||||
|
.fetch_all(pool)
|
||||||
|
.await?,
|
||||||
config,
|
config,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,4 @@
|
||||||
|
|
||||||
pub mod frontend;
|
pub mod frontend;
|
||||||
pub mod label;
|
pub mod label;
|
||||||
pub mod manage;
|
|
||||||
pub mod middleware;
|
pub mod middleware;
|
||||||
pub mod models;
|
|
||||||
|
|
|
@ -1,155 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2024 Simon Bruder <simon@sbruder.de>
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use sqlx::{query, query_as, query_scalar, PgPool};
|
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
use crate::models::{Item, NewItem};
|
|
||||||
|
|
||||||
pub async fn add(pool: &PgPool, new_item: NewItem) -> Result<Item, sqlx::Error> {
|
|
||||||
query_as!(
|
|
||||||
Item,
|
|
||||||
"INSERT INTO items (name, parent, class, original_packaging, description) VALUES ($1, $2, $3, $4, $5) RETURNING *",
|
|
||||||
new_item.name,
|
|
||||||
new_item.parent,
|
|
||||||
new_item.class,
|
|
||||||
new_item.original_packaging,
|
|
||||||
new_item.description
|
|
||||||
)
|
|
||||||
.fetch_one(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn add_multiple(
|
|
||||||
pool: &PgPool,
|
|
||||||
new_item: NewItem,
|
|
||||||
quantity: usize,
|
|
||||||
) -> Result<Vec<Item>, sqlx::Error> {
|
|
||||||
query_as!(
|
|
||||||
Item,
|
|
||||||
r#"INSERT INTO items (name, parent, class, original_packaging, description)
|
|
||||||
SELECT * FROM UNNEST($1::VARCHAR[], $2::UUID[], $3::UUID[], $4::UUID[], $5::VARCHAR[])
|
|
||||||
RETURNING *"#,
|
|
||||||
&vec![new_item.name; quantity] as &[Option<String>],
|
|
||||||
&vec![new_item.parent; quantity] as &[Option<Uuid>],
|
|
||||||
&vec![new_item.class; quantity],
|
|
||||||
&vec![new_item.original_packaging; quantity] as &[Option<Uuid>],
|
|
||||||
&vec![new_item.description; quantity]
|
|
||||||
)
|
|
||||||
.fetch_all(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get(pool: &PgPool, id: Uuid) -> Result<Item, sqlx::Error> {
|
|
||||||
query_as!(Item, "SELECT * FROM items WHERE id = $1", id)
|
|
||||||
.fetch_one(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_by_short_id(pool: &PgPool, short_id: i32) -> Result<Item, sqlx::Error> {
|
|
||||||
query_as!(Item, "SELECT * FROM items WHERE short_id = $1", short_id)
|
|
||||||
.fetch_one(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_all(pool: &PgPool) -> Result<Vec<Item>, sqlx::Error> {
|
|
||||||
query_as!(Item, "SELECT * FROM items ORDER BY created_at")
|
|
||||||
.fetch_all(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_multiple(pool: &PgPool, ids: &[Uuid]) -> Result<Vec<Item>, sqlx::Error> {
|
|
||||||
query_as!(Item, "SELECT * FROM items WHERE id = ANY ($1)", ids)
|
|
||||||
.fetch_all(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_all_as_map(pool: &PgPool) -> Result<HashMap<Uuid, Item>, sqlx::Error> {
|
|
||||||
Ok(get_all(pool)
|
|
||||||
.await?
|
|
||||||
.into_iter()
|
|
||||||
.map(|i| (i.id, i))
|
|
||||||
.collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn update(pool: &PgPool, id: Uuid, modified_item: NewItem) -> Result<Item, sqlx::Error> {
|
|
||||||
query_as!(
|
|
||||||
Item,
|
|
||||||
"UPDATE items SET name = $2, parent = $3, class = $4, original_packaging = $5, description = $6 WHERE id = $1 RETURNING *",
|
|
||||||
id,
|
|
||||||
modified_item.name,
|
|
||||||
modified_item.parent,
|
|
||||||
modified_item.class,
|
|
||||||
modified_item.original_packaging,
|
|
||||||
modified_item.description
|
|
||||||
)
|
|
||||||
.fetch_one(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn delete(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> {
|
|
||||||
let res = query!("DELETE FROM items WHERE id = $1", id)
|
|
||||||
.execute(pool)
|
|
||||||
.await?;
|
|
||||||
assert_eq!(res.rows_affected(), 1);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_parents(pool: &PgPool, id: Uuid) -> Result<Vec<Uuid>, sqlx::Error> {
|
|
||||||
// force nullable is required for all columns in views
|
|
||||||
query_scalar!(
|
|
||||||
r#"SELECT unnest(parents) as "parents!" FROM item_tree WHERE id = $1"#,
|
|
||||||
id
|
|
||||||
)
|
|
||||||
.fetch_all(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_all_parents(pool: &PgPool) -> Result<HashMap<Uuid, Vec<Uuid>>, sqlx::Error> {
|
|
||||||
let mut parents = HashMap::new();
|
|
||||||
for row in query!(r#"SELECT id as "id!", parents as "parents!" FROM item_tree"#)
|
|
||||||
.fetch_all(pool)
|
|
||||||
.await?
|
|
||||||
{
|
|
||||||
parents.insert(row.id, row.parents);
|
|
||||||
}
|
|
||||||
Ok(parents)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_parents_details(pool: &PgPool, id: Uuid) -> Result<Vec<Item>, sqlx::Error> {
|
|
||||||
query_as!(
|
|
||||||
Item,
|
|
||||||
"SELECT items.*
|
|
||||||
FROM items
|
|
||||||
INNER JOIN
|
|
||||||
unnest((SELECT parents FROM item_tree WHERE id = $1))
|
|
||||||
WITH ORDINALITY AS parents(id, n)
|
|
||||||
ON items.id = parents.id
|
|
||||||
ORDER BY parents.n;",
|
|
||||||
id
|
|
||||||
)
|
|
||||||
.fetch_all(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_children(pool: &PgPool, id: Uuid) -> Result<Vec<Item>, sqlx::Error> {
|
|
||||||
query_as!(Item, "SELECT * FROM items WHERE parent = $1", id)
|
|
||||||
.fetch_all(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn original_packaging_contents(
|
|
||||||
pool: &PgPool,
|
|
||||||
id: Uuid,
|
|
||||||
) -> Result<Vec<Item>, sqlx::Error> {
|
|
||||||
query_as!(
|
|
||||||
Item,
|
|
||||||
"SELECT * FROM items WHERE original_packaging = $1",
|
|
||||||
id
|
|
||||||
)
|
|
||||||
.fetch_all(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2024 Simon Bruder <simon@sbruder.de>
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use sqlx::{query, query_as, PgPool};
|
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
use crate::models::{Item, ItemClass, NewItemClass};
|
|
||||||
|
|
||||||
pub async fn add(pool: &PgPool, new_item_class: NewItemClass) -> Result<ItemClass, sqlx::Error> {
|
|
||||||
query_as!(
|
|
||||||
ItemClass,
|
|
||||||
"INSERT INTO item_classes (name, parent, description) VALUES ($1, $2, $3) RETURNING *",
|
|
||||||
new_item_class.name,
|
|
||||||
new_item_class.parent,
|
|
||||||
new_item_class.description
|
|
||||||
)
|
|
||||||
.fetch_one(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get(pool: &PgPool, id: Uuid) -> Result<ItemClass, sqlx::Error> {
|
|
||||||
query_as!(ItemClass, "SELECT * FROM item_classes WHERE id = $1", id)
|
|
||||||
.fetch_one(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_all(pool: &PgPool) -> Result<Vec<ItemClass>, sqlx::Error> {
|
|
||||||
query_as!(ItemClass, "SELECT * FROM item_classes ORDER BY created_at")
|
|
||||||
.fetch_all(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_all_as_map(pool: &PgPool) -> Result<HashMap<Uuid, ItemClass>, sqlx::Error> {
|
|
||||||
Ok(get_all(pool)
|
|
||||||
.await?
|
|
||||||
.into_iter()
|
|
||||||
.map(|ic| (ic.id, ic))
|
|
||||||
.collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn update(
|
|
||||||
pool: &PgPool,
|
|
||||||
id: Uuid,
|
|
||||||
modified_item_class: NewItemClass,
|
|
||||||
) -> Result<ItemClass, sqlx::Error> {
|
|
||||||
query_as!(
|
|
||||||
ItemClass,
|
|
||||||
"UPDATE item_classes SET name = $2, parent = $3, description = $4 WHERE id = $1 RETURNING *",
|
|
||||||
id,
|
|
||||||
modified_item_class.name,
|
|
||||||
modified_item_class.parent,
|
|
||||||
modified_item_class.description
|
|
||||||
)
|
|
||||||
.fetch_one(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn items(pool: &PgPool, id: Uuid) -> Result<Vec<Item>, sqlx::Error> {
|
|
||||||
query_as!(Item, "SELECT * FROM items WHERE class = $1", id)
|
|
||||||
.fetch_all(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn delete(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> {
|
|
||||||
let res = query!("DELETE FROM item_classes WHERE id = $1", id)
|
|
||||||
.execute(pool)
|
|
||||||
.await?;
|
|
||||||
assert_eq!(res.rows_affected(), 1);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn children(pool: &PgPool, id: Uuid) -> Result<Vec<ItemClass>, sqlx::Error> {
|
|
||||||
query_as!(
|
|
||||||
ItemClass,
|
|
||||||
"SELECT * FROM item_classes WHERE parent = $1",
|
|
||||||
id
|
|
||||||
)
|
|
||||||
.fetch_all(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2024 Simon Bruder <simon@sbruder.de>
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
|
|
||||||
pub mod item;
|
|
||||||
pub mod item_class;
|
|
||||||
|
|
||||||
use sqlx::{query, PgPool};
|
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
use crate::models::EntityType;
|
|
||||||
|
|
||||||
pub async fn query_entity_type(pool: &PgPool, id: Uuid) -> Result<Option<EntityType>, sqlx::Error> {
|
|
||||||
Ok(query!(
|
|
||||||
r#"SELECT type as "type!" FROM
|
|
||||||
(SELECT id, 'item' AS "type" FROM items
|
|
||||||
UNION ALL
|
|
||||||
SELECT id, 'item_class' AS "type" FROM item_classes) id_mapping
|
|
||||||
WHERE id = $1"#,
|
|
||||||
id
|
|
||||||
)
|
|
||||||
.fetch_optional(pool)
|
|
||||||
.await?
|
|
||||||
.map(|row| match row.r#type.as_str() {
|
|
||||||
"item" => EntityType::Item,
|
|
||||||
"item_class" => EntityType::ItemClass,
|
|
||||||
_ => unreachable!("database returned impossible type"),
|
|
||||||
}))
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2024 Simon Bruder <simon@sbruder.de>
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use time::OffsetDateTime;
|
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub enum EntityType {
|
|
||||||
Item,
|
|
||||||
ItemClass,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, sqlx::FromRow)]
|
|
||||||
pub struct Item {
|
|
||||||
pub id: Uuid,
|
|
||||||
pub name: Option<String>,
|
|
||||||
pub parent: Option<Uuid>,
|
|
||||||
pub class: Uuid,
|
|
||||||
#[serde(with = "time::serde::iso8601")]
|
|
||||||
pub created_at: OffsetDateTime,
|
|
||||||
pub short_id: i32,
|
|
||||||
pub original_packaging: Option<Uuid>,
|
|
||||||
pub description: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
pub struct NewItem {
|
|
||||||
#[serde(default)]
|
|
||||||
pub name: Option<String>,
|
|
||||||
#[serde(default)]
|
|
||||||
pub parent: Option<Uuid>,
|
|
||||||
pub class: Uuid,
|
|
||||||
pub original_packaging: Option<Uuid>,
|
|
||||||
pub description: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize)]
|
|
||||||
pub struct ItemClass {
|
|
||||||
pub id: Uuid,
|
|
||||||
pub name: String,
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub parent: Option<Uuid>,
|
|
||||||
#[serde(with = "time::serde::iso8601")]
|
|
||||||
pub created_at: OffsetDateTime,
|
|
||||||
pub description: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
pub struct NewItemClass {
|
|
||||||
pub name: String,
|
|
||||||
#[serde(default)]
|
|
||||||
pub parent: Option<Uuid>,
|
|
||||||
pub description: String,
|
|
||||||
}
|
|
Loading…
Reference in a new issue