wip: currently rewriting the project as a full stack application tangled.org/kacaii.dev/sigo
gleam
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

:truck: distribute application in modules

Kacaii 6adb88fe 8f0ba760

+299 -172
+6 -6
src/app/router.gleam
··· 7 7 //// All requests are processed through the web middleware pipeline before routing. 8 8 //// Unmatched routes return a 404 Not Found response. 9 9 10 - import app/routes/get_brigade_members 11 - import app/routes/get_crew_members 12 - import app/routes/get_ocurrences_by_applicant 13 - import app/routes/login 14 - import app/routes/register_new_occurrence 15 - import app/routes/signup 10 + import app/routes/brigade/get_brigade_members 11 + import app/routes/occurrence/register_new_occurrence 12 + import app/routes/user/get_crew_members 13 + import app/routes/user/get_ocurrences_by_applicant 14 + import app/routes/user/login 15 + import app/routes/user/signup 16 16 import app/web.{type Context} 17 17 import gleam/http 18 18 import wisp
+112
src/app/routes/brigade/sql.gleam
··· 1 + //// This module contains the code to run the sql queries defined in 2 + //// `./src/app/routes/brigade/sql`. 3 + //// > 🐿️ This module was generated automatically using v4.4.1 of 4 + //// > the [squirrel package](https://github.com/giacomocavalieri/squirrel). 5 + //// 6 + 7 + import gleam/dynamic/decode 8 + import gleam/option.{type Option} 9 + import pog 10 + import youid/uuid.{type Uuid} 11 + 12 + /// A row you get from running the `count_active_brigades` query 13 + /// defined in `./src/app/routes/brigade/sql/count_active_brigades.sql`. 14 + /// 15 + /// > 🐿️ This type definition was generated automatically using v4.4.1 of the 16 + /// > [squirrel package](https://github.com/giacomocavalieri/squirrel). 17 + /// 18 + pub type CountActiveBrigadesRow { 19 + CountActiveBrigadesRow(count: Int) 20 + } 21 + 22 + /// 󰆙 Counts the number of active brigades in the database. 23 + /// 24 + /// > 🐿️ This function was generated automatically using v4.4.1 of 25 + /// > the [squirrel package](https://github.com/giacomocavalieri/squirrel). 26 + /// 27 + pub fn count_active_brigades( 28 + db: pog.Connection, 29 + ) -> Result(pog.Returned(CountActiveBrigadesRow), pog.QueryError) { 30 + let decoder = { 31 + use count <- decode.field(0, decode.int) 32 + decode.success(CountActiveBrigadesRow(count:)) 33 + } 34 + 35 + "-- 󰆙 Counts the number of active brigades in the database. 36 + SELECT COUNT(id) 37 + FROM public.brigade 38 + WHERE is_active = TRUE; 39 + " 40 + |> pog.query 41 + |> pog.returning(decoder) 42 + |> pog.execute(db) 43 + } 44 + 45 + /// A row you get from running the `get_brigade_members` query 46 + /// defined in `./src/app/routes/brigade/sql/get_brigade_members.sql`. 47 + /// 48 + /// > 🐿️ This type definition was generated automatically using v4.4.1 of the 49 + /// > [squirrel package](https://github.com/giacomocavalieri/squirrel). 50 + /// 51 + pub type GetBrigadeMembersRow { 52 + GetBrigadeMembersRow( 53 + id: Uuid, 54 + full_name: String, 55 + role_name: Option(String), 56 + description: Option(String), 57 + ) 58 + } 59 + 60 + ///  Find all members of a brigade 61 + /// 62 + /// > 🐿️ This function was generated automatically using v4.4.1 of 63 + /// > the [squirrel package](https://github.com/giacomocavalieri/squirrel). 64 + /// 65 + pub fn get_brigade_members( 66 + db: pog.Connection, 67 + arg_1: Uuid, 68 + ) -> Result(pog.Returned(GetBrigadeMembersRow), pog.QueryError) { 69 + let decoder = { 70 + use id <- decode.field(0, uuid_decoder()) 71 + use full_name <- decode.field(1, decode.string) 72 + use role_name <- decode.field(2, decode.optional(decode.string)) 73 + use description <- decode.field(3, decode.optional(decode.string)) 74 + decode.success(GetBrigadeMembersRow( 75 + id:, 76 + full_name:, 77 + role_name:, 78 + description:, 79 + )) 80 + } 81 + 82 + "--  Find all members of a brigade 83 + SELECT 84 + u.id, 85 + u.full_name, 86 + r.role_name, 87 + r.description 88 + FROM public.user_account AS u 89 + LEFT JOIN 90 + public.user_role AS r 91 + ON u.role_id = r.id 92 + INNER JOIN 93 + public.query_brigade_members_id($1) AS brigade_members (id) 94 + ON u.id = brigade_members.id; 95 + " 96 + |> pog.query 97 + |> pog.parameter(pog.text(uuid.to_string(arg_1))) 98 + |> pog.returning(decoder) 99 + |> pog.execute(db) 100 + } 101 + 102 + // --- Encoding/decoding utils ------------------------------------------------- 103 + 104 + /// A decoder to decode `Uuid`s coming from a Postgres query. 105 + /// 106 + fn uuid_decoder() { 107 + use bit_array <- decode.then(decode.bit_array) 108 + case uuid.from_bit_array(bit_array) { 109 + Ok(uuid) -> decode.success(uuid) 110 + Error(_) -> decode.failure(uuid.v7(), "Uuid") 111 + } 112 + }
+4
src/app/routes/brigade/sql/count_active_brigades.sql
··· 1 + -- 󰆙 Counts the number of active brigades in the database. 2 + SELECT COUNT(id) 3 + FROM public.brigade 4 + WHERE is_active = TRUE;
+25
src/app/routes/dashboard.gleam
··· 1 + import app/routes/occurrence.{type Occurrence, Occurrence} 2 + import app/routes/occurrence/count_active_occurrences 3 + import app/web.{type Context} 4 + import gleam/result 5 + import wisp 6 + 7 + // TODO: Docs 8 + pub fn handle_request( 9 + request request: wisp.Request, 10 + ctx ctx: Context, 11 + ) -> wisp.Response { 12 + let query_result = { 13 + use active_occurrences <- result.try({ 14 + count_active_occurrences.handle_query(ctx:) 15 + }) 16 + todo 17 + } 18 + 19 + todo 20 + } 21 + 22 + // TODO: Docs 23 + pub type DashBoard { 24 + DashBoard(active_occurrences: Int, recent_occurrence: List(Occurrence)) 25 + }
+1 -1
src/app/routes/get_brigade_members.gleam src/app/routes/brigade/get_brigade_members.gleam
··· 3 3 //// It returns a list of members belonging to the specified brigade, including 4 4 //// their id, full name, role, and description. 5 5 6 - import app/sql 6 + import app/routes/brigade/sql 7 7 import app/web.{type Context} 8 8 import gleam/http 9 9 import gleam/json
+1 -1
src/app/routes/get_crew_members.gleam src/app/routes/user/get_crew_members.gleam
··· 1 1 //// Handler for retrieving members from the same brigade as a given user. 2 2 3 - import app/sql 3 + import app/routes/user/sql 4 4 import app/web.{type Context} 5 5 import gleam/http 6 6 import gleam/json
+1 -1
src/app/routes/get_ocurrences_by_applicant.gleam src/app/routes/user/get_ocurrences_by_applicant.gleam
··· 3 3 //// It returns a list of occurrences (incidents/reports) that were submitted 4 4 //// by the specified user, including detailed information about each occurrence. 5 5 6 - import app/sql 6 + import app/routes/user/sql 7 7 import app/web 8 8 import gleam/float 9 9 import gleam/http
+1 -1
src/app/routes/login.gleam src/app/routes/user/login.gleam
··· 2 2 //// 3 3 ////  Uses signed cookies to prevent tampering and logs all login attempts. 4 4 5 - import app/sql 5 + import app/routes/user/sql 6 6 import app/web.{type Context} 7 7 import argus 8 8 import formal/form
+16
src/app/routes/occurrence.gleam
··· 1 + import youid/uuid 2 + 3 + /// Validated occurrence data with all IDs converted to UUIDs, 4 + /// ready for database insertion 5 + pub type Occurrence { 6 + Occurrence( 7 + applicant_id: uuid.Uuid, 8 + category_id: uuid.Uuid, 9 + subcategory_id: uuid.Uuid, 10 + description: String, 11 + location: List(Float), 12 + reference_point: String, 13 + vehicle_code: String, 14 + participants_id: List(uuid.Uuid), 15 + ) 16 + }
+32
src/app/routes/occurrence/count_active_occurrences.gleam
··· 1 + import app/routes/occurrence/sql 2 + import app/web.{type Context} 3 + import gleam/list 4 + import gleam/result 5 + 6 + // TODO: Documentation 7 + pub fn handle_query( 8 + ctx ctx: Context, 9 + ) -> Result(Int, CountActiveOccurrencesError) { 10 + let query_result = { 11 + use returned <- result.try( 12 + sql.count_active_occurrences(ctx.conn) 13 + |> result.replace_error(DataBaseError), 14 + ) 15 + use row <- result.try( 16 + list.first(returned.rows) 17 + |> result.replace_error(DataBaseReturnedEmptyRow), 18 + ) 19 + 20 + Ok(row.count) 21 + } 22 + 23 + case query_result { 24 + Error(err) -> Error(err) 25 + Ok(count) -> Ok(count) 26 + } 27 + } 28 + 29 + pub opaque type CountActiveOccurrencesError { 30 + DataBaseReturnedEmptyRow 31 + DataBaseError 32 + }
+87
src/app/routes/occurrence/sql.gleam
··· 1 + //// This module contains the code to run the sql queries defined in 2 + //// `./src/app/routes/occurrence/sql`. 3 + //// > 🐿️ This module was generated automatically using v4.4.1 of 4 + //// > the [squirrel package](https://github.com/giacomocavalieri/squirrel). 5 + //// 6 + 7 + import gleam/dynamic/decode 8 + import pog 9 + import youid/uuid.{type Uuid} 10 + 11 + /// A row you get from running the `count_active_occurrences` query 12 + /// defined in `./src/app/routes/occurrence/sql/count_active_occurrences.sql`. 13 + /// 14 + /// > 🐿️ This type definition was generated automatically using v4.4.1 of the 15 + /// > [squirrel package](https://github.com/giacomocavalieri/squirrel). 16 + /// 17 + pub type CountActiveOccurrencesRow { 18 + CountActiveOccurrencesRow(count: Int) 19 + } 20 + 21 + /// 󰆙 Counts the number of active occurrences 22 + /// 23 + /// > 🐿️ This function was generated automatically using v4.4.1 of 24 + /// > the [squirrel package](https://github.com/giacomocavalieri/squirrel). 25 + /// 26 + pub fn count_active_occurrences( 27 + db: pog.Connection, 28 + ) -> Result(pog.Returned(CountActiveOccurrencesRow), pog.QueryError) { 29 + let decoder = { 30 + use count <- decode.field(0, decode.int) 31 + decode.success(CountActiveOccurrencesRow(count:)) 32 + } 33 + 34 + "-- 󰆙 Counts the number of active occurrences 35 + SELECT COUNT(oc.id) 36 + FROM public.occurrence AS oc 37 + WHERE oc.resolved_at IS NULL; 38 + " 39 + |> pog.query 40 + |> pog.returning(decoder) 41 + |> pog.execute(db) 42 + } 43 + 44 + ///  Inserts a new occurrence into the database 45 + /// 46 + /// > 🐿️ This function was generated automatically using v4.4.1 of 47 + /// > the [squirrel package](https://github.com/giacomocavalieri/squirrel). 48 + /// 49 + pub fn insert_new_occurence( 50 + db: pog.Connection, 51 + arg_1: Uuid, 52 + arg_2: Uuid, 53 + arg_3: Uuid, 54 + arg_4: String, 55 + arg_5: List(Float), 56 + arg_6: String, 57 + arg_7: String, 58 + arg_8: List(Uuid), 59 + ) -> Result(pog.Returned(Nil), pog.QueryError) { 60 + let decoder = decode.map(decode.dynamic, fn(_) { Nil }) 61 + 62 + "--  Inserts a new occurrence into the database 63 + INSERT INTO public.occurrence ( 64 + applicant_id, 65 + category_id, 66 + subcategory_id, 67 + description, 68 + location, 69 + reference_point, 70 + vehicle_code, 71 + participants_id 72 + ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8); 73 + " 74 + |> pog.query 75 + |> pog.parameter(pog.text(uuid.to_string(arg_1))) 76 + |> pog.parameter(pog.text(uuid.to_string(arg_2))) 77 + |> pog.parameter(pog.text(uuid.to_string(arg_3))) 78 + |> pog.parameter(pog.text(arg_4)) 79 + |> pog.parameter(pog.array(fn(value) { pog.float(value) }, arg_5)) 80 + |> pog.parameter(pog.text(arg_6)) 81 + |> pog.parameter(pog.text(arg_7)) 82 + |> pog.parameter( 83 + pog.array(fn(value) { pog.text(uuid.to_string(value)) }, arg_8), 84 + ) 85 + |> pog.returning(decoder) 86 + |> pog.execute(db) 87 + }
+4
src/app/routes/occurrence/sql/count_active_occurrences.sql
··· 1 + -- 󰆙 Counts the number of active occurrences 2 + SELECT COUNT(oc.id) 3 + FROM public.occurrence AS oc 4 + WHERE oc.resolved_at IS NULL;
+2 -16
src/app/routes/register_new_occurrence.gleam src/app/routes/occurrence/register_new_occurrence.gleam
··· 1 1 //// Processes occurrence registration form data, validates inputs, and creates 2 2 //// a new occurrence record in the database. 3 3 4 - import app/sql 4 + import app/routes/occurrence.{type Occurrence, Occurrence} 5 + import app/routes/occurrence/sql 5 6 import app/web.{type Context} 6 7 import formal/form 7 8 import gleam/list ··· 23 24 reference_point: String, 24 25 vehicle_code: String, 25 26 participants_id: List(String), 26 - ) 27 - } 28 - 29 - /// Validated occurrence data with all IDs converted to UUIDs, 30 - /// ready for database insertion 31 - pub opaque type Occurrence { 32 - Occurrence( 33 - applicant_id: uuid.Uuid, 34 - category_id: uuid.Uuid, 35 - subcategory_id: uuid.Uuid, 36 - description: String, 37 - location: List(Float), 38 - reference_point: String, 39 - vehicle_code: String, 40 - participants_id: List(uuid.Uuid), 41 27 ) 42 28 } 43 29
+1 -1
src/app/routes/signup.gleam src/app/routes/user/signup.gleam
··· 6 6 //// Passwords are hashed using Argon2 before storage and all sensitive 7 7 //// operations are logged for audit purposes. 8 8 9 - import app/sql 9 + import app/routes/user/sql 10 10 import app/web.{type Context} 11 11 import argus 12 12 import formal/form
+6 -141
src/app/sql.gleam src/app/routes/user/sql.gleam
··· 1 1 //// This module contains the code to run the sql queries defined in 2 - //// `./src/app/sql`. 2 + //// `./src/app/routes/user/sql`. 3 3 //// > 🐿️ This module was generated automatically using v4.4.1 of 4 4 //// > the [squirrel package](https://github.com/giacomocavalieri/squirrel). 5 5 //// ··· 10 10 import pog 11 11 import youid/uuid.{type Uuid} 12 12 13 - /// A row you get from running the `count_active_brigades` query 14 - /// defined in `./src/app/sql/count_active_brigades.sql`. 15 - /// 16 - /// > 🐿️ This type definition was generated automatically using v4.4.1 of the 17 - /// > [squirrel package](https://github.com/giacomocavalieri/squirrel). 18 - /// 19 - pub type CountActiveBrigadesRow { 20 - CountActiveBrigadesRow(count: Int) 21 - } 22 - 23 - /// 󰆙 Counts the number of active brigades in the database. 24 - /// 25 - /// > 🐿️ This function was generated automatically using v4.4.1 of 26 - /// > the [squirrel package](https://github.com/giacomocavalieri/squirrel). 27 - /// 28 - pub fn count_active_brigades( 29 - db: pog.Connection, 30 - ) -> Result(pog.Returned(CountActiveBrigadesRow), pog.QueryError) { 31 - let decoder = { 32 - use count <- decode.field(0, decode.int) 33 - decode.success(CountActiveBrigadesRow(count:)) 34 - } 35 - 36 - "-- 󰆙 Counts the number of active brigades in the database. 37 - SELECT COUNT(id) 38 - FROM public.brigade 39 - WHERE is_active = TRUE; 40 - " 41 - |> pog.query 42 - |> pog.returning(decoder) 43 - |> pog.execute(db) 44 - } 45 - 46 - /// A row you get from running the `get_brigade_members` query 47 - /// defined in `./src/app/sql/get_brigade_members.sql`. 48 - /// 49 - /// > 🐿️ This type definition was generated automatically using v4.4.1 of the 50 - /// > [squirrel package](https://github.com/giacomocavalieri/squirrel). 51 - /// 52 - pub type GetBrigadeMembersRow { 53 - GetBrigadeMembersRow( 54 - id: Uuid, 55 - full_name: String, 56 - role_name: Option(String), 57 - description: Option(String), 58 - ) 59 - } 60 - 61 - ///  Find all members of a brigade 62 - /// 63 - /// > 🐿️ This function was generated automatically using v4.4.1 of 64 - /// > the [squirrel package](https://github.com/giacomocavalieri/squirrel). 65 - /// 66 - pub fn get_brigade_members( 67 - db: pog.Connection, 68 - arg_1: Uuid, 69 - ) -> Result(pog.Returned(GetBrigadeMembersRow), pog.QueryError) { 70 - let decoder = { 71 - use id <- decode.field(0, uuid_decoder()) 72 - use full_name <- decode.field(1, decode.string) 73 - use role_name <- decode.field(2, decode.optional(decode.string)) 74 - use description <- decode.field(3, decode.optional(decode.string)) 75 - decode.success(GetBrigadeMembersRow( 76 - id:, 77 - full_name:, 78 - role_name:, 79 - description:, 80 - )) 81 - } 82 - 83 - "--  Find all members of a brigade 84 - SELECT 85 - u.id, 86 - u.full_name, 87 - r.role_name, 88 - r.description 89 - FROM public.user_account AS u 90 - LEFT JOIN 91 - public.user_role AS r 92 - ON u.role_id = r.id 93 - INNER JOIN 94 - public.query_brigade_members_id($1) AS brigade_members (id) 95 - ON u.id = brigade_members.id; 96 - " 97 - |> pog.query 98 - |> pog.parameter(pog.text(uuid.to_string(arg_1))) 99 - |> pog.returning(decoder) 100 - |> pog.execute(db) 101 - } 102 - 103 13 /// A row you get from running the `get_crew_members` query 104 - /// defined in `./src/app/sql/get_crew_members.sql`. 14 + /// defined in `./src/app/routes/user/sql/get_crew_members.sql`. 105 15 /// 106 16 /// > 🐿️ This type definition was generated automatically using v4.4.1 of the 107 17 /// > [squirrel package](https://github.com/giacomocavalieri/squirrel). ··· 155 65 } 156 66 157 67 /// A row you get from running the `get_login_token` query 158 - /// defined in `./src/app/sql/get_login_token.sql`. 68 + /// defined in `./src/app/routes/user/sql/get_login_token.sql`. 159 69 /// 160 70 /// > 🐿️ This type definition was generated automatically using v4.4.1 of the 161 71 /// > [squirrel package](https://github.com/giacomocavalieri/squirrel). ··· 195 105 } 196 106 197 107 /// A row you get from running the `get_occurences_by_applicant` query 198 - /// defined in `./src/app/sql/get_occurences_by_applicant.sql`. 108 + /// defined in `./src/app/routes/user/sql/get_occurences_by_applicant.sql`. 199 109 /// 200 110 /// > 🐿️ This type definition was generated automatically using v4.4.1 of the 201 111 /// > [squirrel package](https://github.com/giacomocavalieri/squirrel). ··· 270 180 } 271 181 272 182 /// A row you get from running the `get_user_id_by_registration` query 273 - /// defined in `./src/app/sql/get_user_id_by_registration.sql`. 183 + /// defined in `./src/app/routes/user/sql/get_user_id_by_registration.sql`. 274 184 /// 275 185 /// > 🐿️ This type definition was generated automatically using v4.4.1 of the 276 186 /// > [squirrel package](https://github.com/giacomocavalieri/squirrel). ··· 305 215 } 306 216 307 217 /// A row you get from running the `get_user_name` query 308 - /// defined in `./src/app/sql/get_user_name.sql`. 218 + /// defined in `./src/app/routes/user/sql/get_user_name.sql`. 309 219 /// 310 220 /// > 🐿️ This type definition was generated automatically using v4.4.1 of the 311 221 /// > [squirrel package](https://github.com/giacomocavalieri/squirrel). ··· 335 245 " 336 246 |> pog.query 337 247 |> pog.parameter(pog.text(uuid.to_string(arg_1))) 338 - |> pog.returning(decoder) 339 - |> pog.execute(db) 340 - } 341 - 342 - ///  Inserts a new occurrence into the database 343 - /// 344 - /// > 🐿️ This function was generated automatically using v4.4.1 of 345 - /// > the [squirrel package](https://github.com/giacomocavalieri/squirrel). 346 - /// 347 - pub fn insert_new_occurence( 348 - db: pog.Connection, 349 - arg_1: Uuid, 350 - arg_2: Uuid, 351 - arg_3: Uuid, 352 - arg_4: String, 353 - arg_5: List(Float), 354 - arg_6: String, 355 - arg_7: String, 356 - arg_8: List(Uuid), 357 - ) -> Result(pog.Returned(Nil), pog.QueryError) { 358 - let decoder = decode.map(decode.dynamic, fn(_) { Nil }) 359 - 360 - "--  Inserts a new occurrence into the database 361 - INSERT INTO public.occurrence ( 362 - applicant_id, 363 - category_id, 364 - subcategory_id, 365 - description, 366 - location, 367 - reference_point, 368 - vehicle_code, 369 - participants_id 370 - ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8); 371 - " 372 - |> pog.query 373 - |> pog.parameter(pog.text(uuid.to_string(arg_1))) 374 - |> pog.parameter(pog.text(uuid.to_string(arg_2))) 375 - |> pog.parameter(pog.text(uuid.to_string(arg_3))) 376 - |> pog.parameter(pog.text(arg_4)) 377 - |> pog.parameter(pog.array(fn(value) { pog.float(value) }, arg_5)) 378 - |> pog.parameter(pog.text(arg_6)) 379 - |> pog.parameter(pog.text(arg_7)) 380 - |> pog.parameter( 381 - pog.array(fn(value) { pog.text(uuid.to_string(value)) }, arg_8), 382 - ) 383 248 |> pog.returning(decoder) 384 249 |> pog.execute(db) 385 250 }
-4
src/app/sql/count_active_brigades.sql
··· 1 - -- 󰆙 Counts the number of active brigades in the database. 2 - SELECT COUNT(id) 3 - FROM public.brigade 4 - WHERE is_active = TRUE;
src/app/sql/get_brigade_members.sql src/app/routes/brigade/sql/get_brigade_members.sql
src/app/sql/get_crew_members.sql src/app/routes/user/sql/get_crew_members.sql
src/app/sql/get_login_token.sql src/app/routes/user/sql/get_login_token.sql
src/app/sql/get_occurences_by_applicant.sql src/app/routes/user/sql/get_occurences_by_applicant.sql
src/app/sql/get_user_id_by_registration.sql src/app/routes/user/sql/get_user_id_by_registration.sql
src/app/sql/get_user_name.sql src/app/routes/user/sql/get_user_name.sql
src/app/sql/insert_new_occurence.sql src/app/routes/occurrence/sql/insert_new_occurence.sql
src/app/sql/insert_new_user.sql src/app/routes/user/sql/insert_new_user.sql