Merge pull request 'Merge recent UI & Postgres work into main branch' (#4) from postgres into main

Reviewed-on: #4
This commit is contained in:
William Bouzourène 2025-07-24 10:13:00 +00:00
commit 8ddc81289b
51 changed files with 3657 additions and 3144 deletions

View file

@ -3,5 +3,5 @@ DEV_MODE=false
APP_LISTEN_ADDRESS=127.0.0.1 APP_LISTEN_ADDRESS=127.0.0.1
APP_LISTEN_PORT=3000 APP_LISTEN_PORT=3000
APP_BEHIND_PROXY=false APP_BEHIND_PROXY=false
DATABASE_LOCATION=./people.db DATABASE_DSN="host=localhost user=camarades password=camarades dbname=camarades port=5432 sslmode=disable TimeZone=Europe/Zurich"
SESSIONS_LOCATION=./sessions.db SESSIONS_LOCATION=./sessions.db

14
compose.yml Normal file
View file

@ -0,0 +1,14 @@
services:
postgres:
image: postgres:latest
container_name: camarades-postgres
ports:
- "127.0.0.1:5432:5432"
environment:
POSTGRES_USER: camarades
POSTGRES_PASSWORD: camarades
POSTGRES_DB: camarades
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:

View file

@ -68,8 +68,11 @@ func Contacts(c *fiber.Ctx) error {
params.PageSize = 50 params.PageSize = 50
params.PersonType = "contacts" params.PersonType = "contacts"
params.OrderColumn = c.Query("c")
params.OrderDirection = c.Query("o")
var sections []models.Section var sections []models.Section
db.Order("name collate nocase asc").Find(&sections, "contains_contacts = ? AND id IN ?", true, allowedSections) db.Order("name asc").Find(&sections, "contains_contacts = ? AND id IN ?", true, allowedSections)
params.AllowedSections = allowedSections params.AllowedSections = allowedSections
// Security for active contacts // Security for active contacts
@ -100,6 +103,8 @@ func Contacts(c *fiber.Ctx) error {
"SearchJSON": searchJSON, "SearchJSON": searchJSON,
"Sections": sections, "Sections": sections,
"Fields": fields, "Fields": fields,
"OrderCol": params.OrderColumn,
"OrderDir": params.OrderDirection,
}) })
} }
@ -156,7 +161,7 @@ func ContactsExport(c *fiber.Ctx) error {
params.PersonType = "contacts" params.PersonType = "contacts"
var sections []models.Section var sections []models.Section
db.Order("name collate nocase asc").Find(&sections, "contains_members = ? AND id IN ?", true, allowedSections) db.Order("name asc").Find(&sections, "contains_members = ? AND id IN ?", true, allowedSections)
params.AllowedSections = allowedSections params.AllowedSections = allowedSections
// Security for active contacts // Security for active contacts
@ -280,7 +285,7 @@ func ContactsExport(c *fiber.Ctx) error {
} else if field.FieldType == "list" { } else if field.FieldType == "list" {
if field.List.Multi { if field.List != nil && field.List.Multi {
if countMulti == 0 { if countMulti == 0 {
c.Writef("\"") c.Writef("\"")
@ -323,7 +328,7 @@ func ContactShow(c *fiber.Ctx) error {
var person models.Person var person models.Person
result := db.Unscoped().Preload("Section").Find( result := db.Unscoped().Preload("Section").Find(
&person, "id = ? AND is_contact", id, true, &person, "id = ? AND is_contact = ?", id, true,
) )
if result.Error != nil { if result.Error != nil {
@ -416,7 +421,7 @@ func ContactAdd(c *fiber.Ctx) error {
} }
var sections []models.Section var sections []models.Section
db.Order("name collate nocase asc").Find( db.Order("name asc").Find(
&sections, &sections,
"contains_contacts = ?", "contains_contacts = ?",
true, true,
@ -511,7 +516,7 @@ func ContactAdd(c *fiber.Ctx) error {
} }
for _, field := range fields { for _, field := range fields {
if field.List.Multi { if field.List != nil && field.List.Multi {
for _, listItem := range field.List.ListItems { for _, listItem := range field.List.ListItems {
key := fmt.Sprintf("field-%d-%d", field.ID, listItem.ID) key := fmt.Sprintf("field-%d-%d", field.ID, listItem.ID)
value := c.FormValue(key) value := c.FormValue(key)
@ -520,7 +525,7 @@ func ContactAdd(c *fiber.Ctx) error {
var fieldValue models.FieldValue var fieldValue models.FieldValue
fieldValue.FieldID = field.ID fieldValue.FieldID = field.ID
fieldValue.PersonID = person.ID fieldValue.PersonID = person.ID
fieldValue.ListItemID = listItem.ID fieldValue.ListItemID = &listItem.ID
db.Create(&fieldValue) db.Create(&fieldValue)
} }
} }
@ -594,7 +599,8 @@ func ContactAdd(c *fiber.Ctx) error {
var fieldValue models.FieldValue var fieldValue models.FieldValue
fieldValue.FieldID = field.ID fieldValue.FieldID = field.ID
fieldValue.PersonID = person.ID fieldValue.PersonID = person.ID
fieldValue.ListItemID = uint(valueInt) valueUint := uint(valueInt)
fieldValue.ListItemID = &valueUint
db.Create(&fieldValue) db.Create(&fieldValue)
} }
} }
@ -659,7 +665,7 @@ func ContactEdit(c *fiber.Ctx) error {
} }
var sections []models.Section var sections []models.Section
db.Order("name collate nocase asc").Find( db.Order("name asc").Find(
&sections, &sections,
"contains_contacts = ?", "contains_contacts = ?",
true, true,
@ -760,7 +766,7 @@ func ContactEdit(c *fiber.Ctx) error {
field.ID, field.ID,
) )
if field.List.Multi { if field.List != nil && field.List.Multi {
for _, listItem := range field.List.ListItems { for _, listItem := range field.List.ListItems {
key := fmt.Sprintf("field-%d-%d", field.ID, listItem.ID) key := fmt.Sprintf("field-%d-%d", field.ID, listItem.ID)
value := c.FormValue(key) value := c.FormValue(key)
@ -769,7 +775,7 @@ func ContactEdit(c *fiber.Ctx) error {
var fieldValue models.FieldValue var fieldValue models.FieldValue
fieldValue.FieldID = field.ID fieldValue.FieldID = field.ID
fieldValue.PersonID = person.ID fieldValue.PersonID = person.ID
fieldValue.ListItemID = listItem.ID fieldValue.ListItemID = &listItem.ID
db.Create(&fieldValue) db.Create(&fieldValue)
} }
} }
@ -843,7 +849,8 @@ func ContactEdit(c *fiber.Ctx) error {
var fieldValue models.FieldValue var fieldValue models.FieldValue
fieldValue.FieldID = field.ID fieldValue.FieldID = field.ID
fieldValue.PersonID = person.ID fieldValue.PersonID = person.ID
fieldValue.ListItemID = uint(valueInt) valueUint := uint(valueInt)
fieldValue.ListItemID = &valueUint
db.Create(&fieldValue) db.Create(&fieldValue)
} }
} }

View file

@ -110,7 +110,7 @@ func DebugFixFieldsOrder(c *fiber.Ctx) error {
var memberFields []models.Field var memberFields []models.Field
result := db.Order( result := db.Order(
"name collate nocase asc", "name asc",
).Find( ).Find(
&memberFields, "person_type = ?", "member", &memberFields, "person_type = ?", "member",
) )
@ -130,7 +130,7 @@ func DebugFixFieldsOrder(c *fiber.Ctx) error {
var contactFields []models.Field var contactFields []models.Field
result2 := db.Order( result2 := db.Order(
"name collate nocase asc", "name asc",
).Find( ).Find(
&contactFields, "person_type = ?", "contact", &contactFields, "person_type = ?", "contact",
) )

View file

@ -74,7 +74,7 @@ func FieldAdd(c *fiber.Ctx) error {
} }
var lists []models.List var lists []models.List
db.Order("name collate nocase asc").Find(&lists) db.Order("name asc").Find(&lists)
if c.Method() == "POST" { if c.Method() == "POST" {
field.Name = c.FormValue("name") field.Name = c.FormValue("name")
@ -107,7 +107,8 @@ func FieldAdd(c *fiber.Ctx) error {
if err != nil || listID < 1 { if err != nil || listID < 1 {
errors = append(errors, "Liste incorrecte") errors = append(errors, "Liste incorrecte")
} else { } else {
field.ListID = uint(listID) listID2 := uint(listID)
field.ListID = &listID2
} }
} }

View file

@ -1,15 +1,82 @@
package controllers package controllers
import "github.com/gofiber/fiber/v2" import (
"git.readonly.ch/bouzoure/pop-camarades/helpers"
"git.readonly.ch/bouzoure/pop-camarades/models"
"github.com/gofiber/fiber/v2"
)
func Homepage(c *fiber.Ctx) error { func Homepage(c *fiber.Ctx) error {
userid, err := helpers.GetSessionUserId(c)
if err != nil {
return err
}
allowedSectionsMembers, err := helpers.PermissionsGetSections(
userid, "show_member",
)
if err != nil {
return err
}
allowedSectionsContacts, err := helpers.PermissionsGetSections(
userid, "show_contact",
)
if err != nil {
return err
}
db, err := helpers.GetDatabase()
if err != nil {
return err
}
var membersCount int64
var contactsCount int64
db.Find(
&models.Person{},
"is_member = ? AND section_id IN ?",
true, allowedSectionsMembers,
).Count(&membersCount)
db.Find(
&models.Person{},
"is_contact = ? AND section_id IN ?",
true, allowedSectionsContacts,
).Count(&contactsCount)
return c.Render("index", fiber.Map{ return c.Render("index", fiber.Map{
"PageTitle": "Accueil", "PageTitle": "Accueil",
"MembersCount": membersCount,
"ContactsCount": contactsCount,
}) })
} }
func Admin(c *fiber.Ctx) error { func Admin(c *fiber.Ctx) error {
db, err := helpers.GetDatabase()
if err != nil {
return err
}
var sectionsCount int64
var listsCount int64
var fieldsCount int64
var usersCount int64
var rolesCount int64
db.Find(&models.Section{}).Count(&sectionsCount)
db.Find(&models.List{}).Count(&listsCount)
db.Find(&models.Field{}).Count(&fieldsCount)
db.Find(&models.User{}).Count(&usersCount)
db.Find(&models.Role{}).Count(&rolesCount)
return c.Render("admin", fiber.Map{ return c.Render("admin", fiber.Map{
"PageTitle": "Administration", "PageTitle": "Administration",
"SectionsCount": sectionsCount,
"ListsCount": listsCount,
"FieldsCount": fieldsCount,
"UsersCount": usersCount,
"RolesCount": rolesCount,
}) })
} }

View file

@ -17,7 +17,7 @@ func Lists(c *fiber.Ctx) error {
} }
var lists []models.List var lists []models.List
result := db.Order("name collate nocase asc").Find(&lists) result := db.Order("name asc").Find(&lists)
if result.Error != nil && !errors.Is(result.Error, gorm.ErrRecordNotFound) { if result.Error != nil && !errors.Is(result.Error, gorm.ErrRecordNotFound) {
return err return err
@ -54,7 +54,7 @@ func ListShow(c *fiber.Ctx) error {
) )
var listItems []models.ListItem var listItems []models.ListItem
db.Order("value collate nocase asc").Find(&listItems, "list_id = ?", id) db.Order("value asc").Find(&listItems, "list_id = ?", id)
return c.Render("list", fiber.Map{ return c.Render("list", fiber.Map{
"PageTitle": title, "PageTitle": title,

View file

@ -83,8 +83,11 @@ func Members(c *fiber.Ctx) error {
params.PageSize = 50 params.PageSize = 50
params.PersonType = "members" params.PersonType = "members"
params.OrderColumn = c.Query("c")
params.OrderDirection = c.Query("o")
var sections []models.Section var sections []models.Section
db.Order("name collate nocase asc").Find(&sections, "contains_members = ? AND id IN ?", true, allowedSections) db.Order("name asc").Find(&sections, "contains_members = ? AND id IN ?", true, allowedSections)
params.AllowedSections = allowedSections params.AllowedSections = allowedSections
// Security for active contacts // Security for active contacts
@ -115,6 +118,8 @@ func Members(c *fiber.Ctx) error {
"SearchJSON": searchJSON, "SearchJSON": searchJSON,
"Sections": sections, "Sections": sections,
"Fields": fields, "Fields": fields,
"OrderCol": params.OrderColumn,
"OrderDir": params.OrderDirection,
}) })
} }
@ -171,7 +176,7 @@ func MembersExport(c *fiber.Ctx) error {
params.PersonType = "members" params.PersonType = "members"
var sections []models.Section var sections []models.Section
db.Order("name collate nocase asc").Find(&sections, "contains_members = ? AND id IN ?", true, allowedSections) db.Order("name asc").Find(&sections, "contains_members = ? AND id IN ?", true, allowedSections)
params.AllowedSections = allowedSections params.AllowedSections = allowedSections
// Security for active contacts // Security for active contacts
@ -338,7 +343,7 @@ func MemberShow(c *fiber.Ctx) error {
var person models.Person var person models.Person
result := db.Unscoped().Preload("Section").Find( result := db.Unscoped().Preload("Section").Find(
&person, "id = ? AND is_member", id, true, &person, "id = ? AND is_member = ?", id, true,
) )
if result.Error != nil { if result.Error != nil {
@ -431,7 +436,7 @@ func MemberAdd(c *fiber.Ctx) error {
} }
var sections []models.Section var sections []models.Section
db.Order("name collate nocase asc").Find( db.Order("name asc").Find(
&sections, &sections,
"contains_members = ?", "contains_members = ?",
true, true,
@ -526,7 +531,7 @@ func MemberAdd(c *fiber.Ctx) error {
} }
for _, field := range fields { for _, field := range fields {
if field.List.Multi { if field.List != nil && field.List.Multi {
for _, listItem := range field.List.ListItems { for _, listItem := range field.List.ListItems {
key := fmt.Sprintf("field-%d-%d", field.ID, listItem.ID) key := fmt.Sprintf("field-%d-%d", field.ID, listItem.ID)
value := c.FormValue(key) value := c.FormValue(key)
@ -535,7 +540,7 @@ func MemberAdd(c *fiber.Ctx) error {
var fieldValue models.FieldValue var fieldValue models.FieldValue
fieldValue.FieldID = field.ID fieldValue.FieldID = field.ID
fieldValue.PersonID = person.ID fieldValue.PersonID = person.ID
fieldValue.ListItemID = listItem.ID fieldValue.ListItemID = &listItem.ID
db.Create(&fieldValue) db.Create(&fieldValue)
} }
} }
@ -609,7 +614,8 @@ func MemberAdd(c *fiber.Ctx) error {
var fieldValue models.FieldValue var fieldValue models.FieldValue
fieldValue.FieldID = field.ID fieldValue.FieldID = field.ID
fieldValue.PersonID = person.ID fieldValue.PersonID = person.ID
fieldValue.ListItemID = uint(valueInt) valueUint := uint(valueInt)
fieldValue.ListItemID = &valueUint
db.Create(&fieldValue) db.Create(&fieldValue)
} }
} }
@ -674,7 +680,7 @@ func MemberEdit(c *fiber.Ctx) error {
} }
var sections []models.Section var sections []models.Section
db.Order("name collate nocase asc").Find( db.Order("name asc").Find(
&sections, &sections,
"contains_members = ?", "contains_members = ?",
true, true,
@ -775,7 +781,7 @@ func MemberEdit(c *fiber.Ctx) error {
field.ID, field.ID,
) )
if field.List.Multi { if field.List != nil && field.List.Multi {
for _, listItem := range field.List.ListItems { for _, listItem := range field.List.ListItems {
key := fmt.Sprintf("field-%d-%d", field.ID, listItem.ID) key := fmt.Sprintf("field-%d-%d", field.ID, listItem.ID)
value := c.FormValue(key) value := c.FormValue(key)
@ -784,7 +790,7 @@ func MemberEdit(c *fiber.Ctx) error {
var fieldValue models.FieldValue var fieldValue models.FieldValue
fieldValue.FieldID = field.ID fieldValue.FieldID = field.ID
fieldValue.PersonID = person.ID fieldValue.PersonID = person.ID
fieldValue.ListItemID = listItem.ID fieldValue.ListItemID = &listItem.ID
db.Create(&fieldValue) db.Create(&fieldValue)
} }
} }
@ -858,7 +864,8 @@ func MemberEdit(c *fiber.Ctx) error {
var fieldValue models.FieldValue var fieldValue models.FieldValue
fieldValue.FieldID = field.ID fieldValue.FieldID = field.ID
fieldValue.PersonID = person.ID fieldValue.PersonID = person.ID
fieldValue.ListItemID = uint(valueInt) valueUint := uint(valueInt)
fieldValue.ListItemID = &valueUint
db.Create(&fieldValue) db.Create(&fieldValue)
} }
} }

View file

@ -17,7 +17,7 @@ func Roles(c *fiber.Ctx) error {
} }
var roles []models.Role var roles []models.Role
result := db.Order("name collate nocase asc").Find(&roles) result := db.Order("name asc").Find(&roles)
if result.Error != nil && !errors.Is(result.Error, gorm.ErrRecordNotFound) { if result.Error != nil && !errors.Is(result.Error, gorm.ErrRecordNotFound) {
return err return err

View file

@ -18,7 +18,7 @@ func Sections(c *fiber.Ctx) error {
} }
var sections []models.Section var sections []models.Section
result := db.Order("name collate nocase asc").Preload("ParentSection").Find(&sections) result := db.Order("name asc").Preload("ParentSection").Find(&sections)
if result.Error != nil && !errors.Is(result.Error, gorm.ErrRecordNotFound) { if result.Error != nil && !errors.Is(result.Error, gorm.ErrRecordNotFound) {
return err return err
@ -70,8 +70,8 @@ func SectionAdd(c *fiber.Ctx) error {
} }
var sections []models.Section var sections []models.Section
db.Order("name collate nocase asc").Find( db.Order("name asc").Find(
&sections, "id <> ? AND parent_section_id = 0", section.ID, &sections, "id <> ? AND parent_section_id IS NULL", section.ID,
) )
if c.Method() == "POST" { if c.Method() == "POST" {
@ -106,12 +106,12 @@ func SectionAdd(c *fiber.Ctx) error {
section.Name = name section.Name = name
section.ShortName = shortName section.ShortName = shortName
section.ParentSectionID = 0
parentSectionID, err := strconv.ParseUint(parentSection, 10, 0) parentSectionID, err := strconv.ParseUint(parentSection, 10, 0)
if err == nil { if err == nil {
for _, parentSection := range sections { for _, parentSection := range sections {
if parentSection.ID == uint(parentSectionID) { parentSectionID2 := uint(parentSectionID)
section.ParentSectionID = uint(parentSectionID) if parentSection.ID == parentSectionID2 {
section.ParentSectionID = &parentSectionID2
break break
} }
} }
@ -177,8 +177,8 @@ func SectionEdit(c *fiber.Ctx) error {
) )
var sections []models.Section var sections []models.Section
db.Order("name collate nocase asc").Find( db.Order("name asc").Find(
&sections, "id <> ? AND parent_section_id = 0", section.ID, &sections, "id <> ? AND parent_section_id IS NULL", section.ID,
) )
var errors []string var errors []string
@ -200,12 +200,12 @@ func SectionEdit(c *fiber.Ctx) error {
section.Name = name section.Name = name
section.ShortName = shortName section.ShortName = shortName
section.ParentSectionID = 0
parentSectionID, err := strconv.ParseUint(parentSection, 10, 0) parentSectionID, err := strconv.ParseUint(parentSection, 10, 0)
if err == nil { if err == nil {
for _, parentSection := range sections { for _, parentSection := range sections {
if parentSection.ID == uint(parentSectionID) { parentSectionID2 := uint(parentSectionID)
section.ParentSectionID = uint(parentSectionID) if parentSection.ID == parentSectionID2 {
section.ParentSectionID = &parentSectionID2
break break
} }
} }

View file

@ -25,7 +25,7 @@ func Users(c *fiber.Ctx) error {
} }
var users []models.User var users []models.User
result := db.Order("name collate nocase asc").Find(&users) result := db.Order("name asc").Find(&users)
if result.Error != nil && !errors.Is(result.Error, gorm.ErrRecordNotFound) { if result.Error != nil && !errors.Is(result.Error, gorm.ErrRecordNotFound) {
return err return err
@ -62,7 +62,7 @@ func UserShow(c *fiber.Ctx) error {
) )
var userRoles []models.UserRole var userRoles []models.UserRole
db.Joins("Role").Joins("Section").Order("Section__name collate nocase asc").Find( db.Joins("Role").Joins("Section").Order("\"Section\".\"name\" asc").Find(
&userRoles, "user_id = ?", id, &userRoles, "user_id = ?", id,
) )
@ -284,10 +284,10 @@ func UserPermissions(c *fiber.Ctx) error {
) )
var roles []models.Role var roles []models.Role
db.Order("name collate nocase asc").Find(&roles) db.Order("name asc").Find(&roles)
var sections []models.Section var sections []models.Section
db.Order("name collate nocase asc").Find(&sections) db.Order("name asc").Find(&sections)
var errors []string var errors []string
if c.Method() == "POST" { if c.Method() == "POST" {

6
frontend/bootstrap.scss vendored Normal file
View file

@ -0,0 +1,6 @@
$red: #cb0000;
@use "npm:bootstrap/scss/bootstrap.scss" with (
$enable-rounded: false,
$danger: $red
);

View file

@ -1,4 +1,4 @@
@import "npm:bootstrap/dist/css/bootstrap.css"; @import "bootstrap.scss";
@import "npm:bootstrap-icons/font/bootstrap-icons.css"; @import "npm:bootstrap-icons/font/bootstrap-icons.css";
img#header-logo { img#header-logo {
@ -53,3 +53,17 @@ a {
#licenses p { #licenses p {
margin: 0; margin: 0;
} }
.fs-7 {
font-size: .75rem !important;
}
.mw-600 {
max-width: 600px;
}
.mw-900 {
max-width: 900px;
}
.mw-1200 {
max-width: 1200px;
}

48
go.mod
View file

@ -3,32 +3,32 @@ module git.readonly.ch/bouzoure/pop-camarades
go 1.23.4 go 1.23.4
require ( require (
github.com/brianvoe/gofakeit/v7 v7.2.1 github.com/brianvoe/gofakeit/v7 v7.3.0
github.com/charmbracelet/log v0.4.1 github.com/charmbracelet/log v0.4.2
github.com/flosch/pongo2/v6 v6.0.0 github.com/flosch/pongo2/v6 v6.0.0
github.com/glebarez/sqlite v1.11.0 github.com/go-playground/validator/v10 v10.27.0
github.com/go-playground/validator/v10 v10.26.0 github.com/gofiber/fiber/v2 v2.52.8
github.com/gofiber/fiber/v2 v2.52.6
github.com/gofiber/helmet/v2 v2.2.26 github.com/gofiber/helmet/v2 v2.2.26
github.com/gofiber/storage/badger/v2 v2.0.1 github.com/gofiber/storage/badger/v2 v2.0.1
github.com/gofiber/template/django/v3 v3.1.13 github.com/gofiber/template/django/v3 v3.1.14
github.com/golobby/dotenv v1.3.2 github.com/golobby/dotenv v1.3.2
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/pquerna/otp v1.4.0 github.com/pquerna/otp v1.5.0
github.com/yuin/goldmark v1.7.11 github.com/yuin/goldmark v1.7.12
golang.org/x/crypto v0.38.0 golang.org/x/crypto v0.40.0
gorm.io/gorm v1.26.1 gorm.io/driver/postgres v1.6.0
gorm.io/gorm v1.30.0
) )
require ( require (
github.com/andybalholm/brotli v1.1.1 // indirect github.com/andybalholm/brotli v1.2.0 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/boombuler/barcode v1.0.2 // indirect github.com/boombuler/barcode v1.0.2 // indirect
github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/charmbracelet/colorprofile v0.3.1 // indirect github.com/charmbracelet/colorprofile v0.3.1 // indirect
github.com/charmbracelet/lipgloss v1.1.0 // indirect github.com/charmbracelet/lipgloss v1.1.0 // indirect
github.com/charmbracelet/x/ansi v0.9.2 // indirect github.com/charmbracelet/x/ansi v0.9.3 // indirect
github.com/charmbracelet/x/cellbuf v0.0.13 // indirect github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
github.com/charmbracelet/x/term v0.2.1 // indirect github.com/charmbracelet/x/term v0.2.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
@ -36,19 +36,22 @@ require (
github.com/dgraph-io/ristretto v0.2.0 // indirect github.com/dgraph-io/ristretto v0.2.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.9 // indirect github.com/gabriel-vasile/mimetype v1.4.9 // indirect
github.com/glebarez/go-sqlite v1.22.0 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/gofiber/template v1.8.3 // indirect github.com/gofiber/template v1.8.3 // indirect
github.com/gofiber/utils v1.1.0 // indirect github.com/gofiber/utils v1.1.0 // indirect
github.com/gofiber/utils/v2 v2.0.0-beta.8 // indirect github.com/gofiber/utils/v2 v2.0.0-beta.10 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/golang/protobuf v1.5.4 // indirect github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v1.0.0 // indirect github.com/golang/snappy v1.0.0 // indirect
github.com/golobby/cast v1.3.3 // indirect github.com/golobby/cast v1.3.3 // indirect
github.com/google/flatbuffers v25.2.10+incompatible // indirect github.com/google/flatbuffers v25.2.10+incompatible // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.7.5 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/compress v1.18.0 // indirect github.com/klauspost/compress v1.18.0 // indirect
@ -58,22 +61,17 @@ require (
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/muesli/termenv v0.16.0 // indirect github.com/muesli/termenv v0.16.0 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.62.0 // indirect github.com/valyala/fasthttp v1.63.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.opencensus.io v0.24.0 // indirect go.opencensus.io v0.24.0 // indirect
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
golang.org/x/net v0.40.0 // indirect golang.org/x/net v0.42.0 // indirect
golang.org/x/sys v0.33.0 // indirect golang.org/x/sync v0.16.0 // indirect
golang.org/x/text v0.25.0 // indirect golang.org/x/sys v0.34.0 // indirect
golang.org/x/text v0.27.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect google.golang.org/protobuf v1.36.6 // indirect
modernc.org/libc v1.65.4 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.10.0 // indirect
modernc.org/sqlite v1.37.0 // indirect
) )

123
go.sum
View file

@ -2,16 +2,16 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.2 h1:79yrbttoZrLGkL/oOI8hBrUKucwOL0oOjUgEguGMcJ4= github.com/boombuler/barcode v1.0.2 h1:79yrbttoZrLGkL/oOI8hBrUKucwOL0oOjUgEguGMcJ4=
github.com/boombuler/barcode v1.0.2/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.2/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/brianvoe/gofakeit/v7 v7.2.1 h1:AGojgaaCdgq4Adzrd2uWdbGNDyX6MWNhHdQBraNfOHI= github.com/brianvoe/gofakeit/v7 v7.3.0 h1:TWStf7/lLpAjKw+bqwzeORo9jvrxToWEwp9b1J2vApQ=
github.com/brianvoe/gofakeit/v7 v7.2.1/go.mod h1:QXuPeBw164PJCzCUZVmgpgHJ3Llj49jSLVkKPMtxtxA= github.com/brianvoe/gofakeit/v7 v7.3.0/go.mod h1:QXuPeBw164PJCzCUZVmgpgHJ3Llj49jSLVkKPMtxtxA=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
@ -22,10 +22,10 @@ github.com/charmbracelet/colorprofile v0.3.1 h1:k8dTHMd7fgw4bnFd7jXTLZrSU/CQrKnL
github.com/charmbracelet/colorprofile v0.3.1/go.mod h1:/GkGusxNs8VB/RSOh3fu0TJmQ4ICMMPApIIVn0KszZ0= github.com/charmbracelet/colorprofile v0.3.1/go.mod h1:/GkGusxNs8VB/RSOh3fu0TJmQ4ICMMPApIIVn0KszZ0=
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
github.com/charmbracelet/log v0.4.1 h1:6AYnoHKADkghm/vt4neaNEXkxcXLSV2g1rdyFDOpTyk= github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig=
github.com/charmbracelet/log v0.4.1/go.mod h1:pXgyTsqsVu4N9hGdHmQ0xEA4RsXof402LX9ZgiITn2I= github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw=
github.com/charmbracelet/x/ansi v0.9.2 h1:92AGsQmNTRMzuzHEYfCdjQeUzTrgE1vfO5/7fEVoXdY= github.com/charmbracelet/x/ansi v0.9.3 h1:BXt5DHS/MKF+LjuK4huWrC6NCvHtexww7dMayh6GXd0=
github.com/charmbracelet/x/ansi v0.9.2/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= github.com/charmbracelet/x/ansi v0.9.3/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k= github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k=
github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
@ -63,10 +63,6 @@ github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vt
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY= github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok= github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ=
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
@ -75,22 +71,22 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k= github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
github.com/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI= github.com/gofiber/fiber/v2 v2.52.8 h1:xl4jJQ0BV5EJTA2aWiKw/VddRpHrKeZLF0QPUxqn0x4=
github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= github.com/gofiber/fiber/v2 v2.52.8/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
github.com/gofiber/helmet/v2 v2.2.26 h1:KreQVUpCIGppPQ6Yt8qQMaIR4fVXMnvBdsda0dJSsO8= github.com/gofiber/helmet/v2 v2.2.26 h1:KreQVUpCIGppPQ6Yt8qQMaIR4fVXMnvBdsda0dJSsO8=
github.com/gofiber/helmet/v2 v2.2.26/go.mod h1:XE0DF4cgf0M5xIt7qyAK5zOi8jJblhxfSDv9DAmEEQo= github.com/gofiber/helmet/v2 v2.2.26/go.mod h1:XE0DF4cgf0M5xIt7qyAK5zOi8jJblhxfSDv9DAmEEQo=
github.com/gofiber/storage/badger/v2 v2.0.1 h1:iIB5Dh2dypJjdEruYgBf7H4l5a98R5pVKVLk5wbY5bo= github.com/gofiber/storage/badger/v2 v2.0.1 h1:iIB5Dh2dypJjdEruYgBf7H4l5a98R5pVKVLk5wbY5bo=
github.com/gofiber/storage/badger/v2 v2.0.1/go.mod h1:2LA5uR3q4xFVd0oXIZWK+7yzlO2vzLa/D062R7fowFI= github.com/gofiber/storage/badger/v2 v2.0.1/go.mod h1:2LA5uR3q4xFVd0oXIZWK+7yzlO2vzLa/D062R7fowFI=
github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc= github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc=
github.com/gofiber/template v1.8.3/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8= github.com/gofiber/template v1.8.3/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8=
github.com/gofiber/template/django/v3 v3.1.13 h1:9b5VOFUoetOV3axFE7BsLmnZ442Q+h7o9LZPwQ29WEc= github.com/gofiber/template/django/v3 v3.1.14 h1:SvTvs+u5vTZuu1Y2pMUD2NhaGIjBj9FmDA3XD50QBvw=
github.com/gofiber/template/django/v3 v3.1.13/go.mod h1:orkcSnqCO0HGTczIBj9rz77i+EneUMebCqA7bsIWaVA= github.com/gofiber/template/django/v3 v3.1.14/go.mod h1:gP4vH+T1ajZw7yaejqG1dZVdHQkMC/jPoQbmlG812I0=
github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM= github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM=
github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0= github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
github.com/gofiber/utils/v2 v2.0.0-beta.8 h1:ZifwbHZqZO3YJsx1ZhDsWnPjaQ7C0YD20LHt+DQeXOU= github.com/gofiber/utils/v2 v2.0.0-beta.10 h1:yDQgcBKTnZiZ4S0YY+hpTnf5iJYwVaFA2HsOgOesAyY=
github.com/gofiber/utils/v2 v2.0.0-beta.8/go.mod h1:1lCBo9vEF4RFEtTgWntipnaScJZQiM8rrsYycLZ4n9c= github.com/gofiber/utils/v2 v2.0.0-beta.10/go.mod h1:qEZ175nSOkl5xciHmqxwNDsWzwiB39gB8RgU1d3U4mQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@ -130,13 +126,19 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs=
github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
@ -169,8 +171,6 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@ -178,17 +178,17 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg= github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/shamaton/msgpack/v2 v2.2.3 h1:uDOHmxQySlvlUYfQwdjxyybAOzjlQsD1Vjy+4jmO9NM=
github.com/shamaton/msgpack/v2 v2.2.3/go.mod h1:6khjYnkx73f7VQU7wjcFS9DFjs+59naVWJv1TB7qdOI=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
@ -204,6 +204,7 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
@ -212,8 +213,8 @@ github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.62.0 h1:8dKRBX/y2rCzyc6903Zu1+3qN0H/d2MsxPPmVNamiH0= github.com/valyala/fasthttp v1.63.0 h1:DisIL8OjB7ul2d7cBaMRcKTQDYnrGy56R4FCiuDP0Ns=
github.com/valyala/fasthttp v1.62.0/go.mod h1:FCINgr4GKdKqV8Q0xv8b+UxPV+H/O5nNFo3D+r54Htg= github.com/valyala/fasthttp v1.63.0/go.mod h1:REc4IeW+cAEyLrRPa5A81MIjvz0QE1laoTX2EaPHKJM=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
@ -223,8 +224,8 @@ github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZ
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.7.11 h1:ZCxLyDMtz0nT2HFfsYG8WZ47Trip2+JyLysKcMYE5bo= github.com/yuin/goldmark v1.7.12 h1:YwGP/rrea2/CnCtUHgjuolG/PnMxdQtPMO5PvaE2/nY=
github.com/yuin/goldmark v1.7.11/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= github.com/yuin/goldmark v1.7.12/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
@ -232,18 +233,16 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -253,8 +252,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -262,8 +261,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -272,12 +271,12 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@ -286,8 +285,6 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -323,31 +320,9 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/gorm v1.26.1 h1:ghB2gUI9FkS46luZtn6DLZ0f6ooBJ5IbVej2ENFDjRw= gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
gorm.io/gorm v1.26.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s=
modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE=
modernc.org/fileutil v1.3.1 h1:8vq5fe7jdtEvoCf3Zf9Nm0Q05sH6kGx0Op2CPx1wTC8=
modernc.org/fileutil v1.3.1/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/libc v1.65.4 h1:8oVL/29p3e+ZvMv4nE1pryq5p8grHiFsU8bN8Eah/rs=
modernc.org/libc v1.65.4/go.mod h1:MOiGAM9lrMBT9L8xT1nO41qYl5eg9gCp9/kWhz5L7WA=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.10.0 h1:fzumd51yQ1DxcOxSO+S6X7+QTuVU+n8/Aj7swYjFfC4=
modernc.org/memory v1.10.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.37.0 h1:s1TMe7T3Q3ovQiK2Ouz4Jwh7dw4ZDqbebSDTlSJdfjI=
modernc.org/sqlite v1.37.0/go.mod h1:5YiWv+YviqGMuGw4V+PNplcyaJ5v+vQd7TQOgkACoJM=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=

View file

@ -15,7 +15,7 @@ type Config struct {
BehindProxy bool `env:"APP_BEHIND_PROXY"` BehindProxy bool `env:"APP_BEHIND_PROXY"`
} }
Database struct { Database struct {
Location string `env:"DATABASE_LOCATION"` DSN string `env:"DATABASE_DSN"`
} }
Sessions struct { Sessions struct {
Location string `env:"SESSIONS_LOCATION"` Location string `env:"SESSIONS_LOCATION"`

View file

@ -2,7 +2,7 @@ package helpers
import ( import (
"git.readonly.ch/bouzoure/pop-camarades/models" "git.readonly.ch/bouzoure/pop-camarades/models"
"github.com/glebarez/sqlite" "gorm.io/driver/postgres"
"gorm.io/gorm" "gorm.io/gorm"
gormLogger "gorm.io/gorm/logger" gormLogger "gorm.io/gorm/logger"
) )
@ -30,7 +30,7 @@ func GetDatabase() (*gorm.DB, error) {
} }
database, err = gorm.Open( database, err = gorm.Open(
sqlite.Open(config.Database.Location), postgres.Open(config.Database.DSN),
&gormConfig, &gormConfig,
) )
if err != nil { if err != nil {
@ -42,7 +42,8 @@ func GetDatabase() (*gorm.DB, error) {
return database, err return database, err
} }
db.SetMaxOpenConns(1) db.SetMaxIdleConns(10)
db.SetMaxOpenConns(50)
err = database.AutoMigrate( err = database.AutoMigrate(
&models.User{}, &models.User{},

View file

@ -27,6 +27,8 @@ type PeopleSearchParams struct {
PageSize int `json:"-"` PageSize int `json:"-"`
PageNumber int `json:"-"` PageNumber int `json:"-"`
AllowedSections []uint `json:"-"` AllowedSections []uint `json:"-"`
OrderColumn string `json:"-"`
OrderDirection string `json:"-"`
} }
type PeopleSearchResults struct { type PeopleSearchResults struct {
@ -43,16 +45,35 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
return results, nil return results, nil
} }
if strings.EqualFold(params.OrderDirection, "DESC") {
params.OrderDirection = "DESC"
} else {
params.OrderDirection = "ASC"
}
switch strings.ToLower(params.OrderColumn) {
case "address":
params.OrderColumn = "people.address1"
case "npa":
params.OrderColumn = "people.postal_code"
case "section":
params.OrderColumn = "people.section_id"
case "created":
params.OrderColumn = "people.created_at"
case "updated":
params.OrderColumn = "people.updated_at"
default:
params.OrderColumn = "CONCAT(people.last_name, people.first_name)"
}
// SQL qeury for results // SQL qeury for results
sqlQuery := `--sql sqlQuery := `
SELECT people.*, SELECT people.*
sections.name AS Section__name
FROM people FROM people
INNER JOIN sections `
ON people.section_id = sections.id`
// SQL query to count results // SQL query to count results
sqlQueryCount := `--sql sqlQueryCount := `
SELECT people.id SELECT people.id
FROM people FROM people
` `
@ -62,7 +83,7 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
var sqlFilters string var sqlFilters string
// Filter: member or contact // Filter: member or contact
sqlFilters = `--sql sqlFilters = `
WHERE is_member = @is_member WHERE is_member = @is_member
AND is_contact = @is_contact AND is_contact = @is_contact
` `
@ -78,11 +99,11 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
// Filter: name -> first_name + last_name // Filter: name -> first_name + last_name
if len(params.Name) > 0 { if len(params.Name) > 0 {
nameFilter := `--sql nameFilter := `
people.first_name LIKE @name LOWER(people.first_name) LIKE LOWER(@name)
OR people.last_name LIKE @name OR LOWER(people.last_name) LIKE LOWER(@name)
OR CONCAT(people.first_name, ' ', people.last_name) LIKE @name OR LOWER(CONCAT(people.first_name, ' ', people.last_name)) LIKE LOWER(@name)
OR CONCAT(people.last_name, ' ', people.first_name) LIKE @name OR LOWER(CONCAT(people.last_name, ' ', people.first_name)) LIKE LOWER(@name)
` `
sqlParams = append(sqlParams, sql.Named( sqlParams = append(sqlParams, sql.Named(
"name", "name",
@ -92,10 +113,10 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
if strings.Contains(params.Name, " ") { if strings.Contains(params.Name, " ") {
names := strings.Split(params.Name, " ") names := strings.Split(params.Name, " ")
for index, name := range names { for index, name := range names {
nameFilter = fmt.Sprintf(`--sql nameFilter = fmt.Sprintf(`
%s %s
OR people.first_name LIKE @name_%d OR LOWER(people.first_name) LIKE LOWER(@name_%d)
OR people.last_name LIKE @name_%d OR LOWER(people.last_name) LIKE LOWER(@name_%d)
`, nameFilter, index, index) `, nameFilter, index, index)
sqlParams = append(sqlParams, sql.Named( sqlParams = append(sqlParams, sql.Named(
@ -105,7 +126,7 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
} }
} }
sqlFilters = fmt.Sprintf(`--sql sqlFilters = fmt.Sprintf(`
%s %s
AND (%s) AND (%s)
`, sqlFilters, nameFilter) `, sqlFilters, nameFilter)
@ -113,7 +134,7 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
// Filter: section // Filter: section
if params.Section > 0 { if params.Section > 0 {
sqlFilters = fmt.Sprintf(`--sql sqlFilters = fmt.Sprintf(`
%s %s
AND people.section_id = @section AND people.section_id = @section
`, sqlFilters) `, sqlFilters)
@ -122,7 +143,7 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
// Filter: active (only apply if archived is false) // Filter: active (only apply if archived is false)
if params.Active && !params.Archive { if params.Active && !params.Archive {
sqlFilters = fmt.Sprintf(`--sql sqlFilters = fmt.Sprintf(`
%s %s
AND people.deleted_at IS NULL AND people.deleted_at IS NULL
`, sqlFilters) `, sqlFilters)
@ -130,7 +151,7 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
// Filter: archived (only apply if active is false) // Filter: archived (only apply if active is false)
if params.Archive && !params.Active { if params.Archive && !params.Active {
sqlFilters = fmt.Sprintf(`--sql sqlFilters = fmt.Sprintf(`
%s %s
AND people.deleted_at IS NOT NULL AND people.deleted_at IS NOT NULL
`, sqlFilters) `, sqlFilters)
@ -138,7 +159,7 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
// Filter: if both active and archived are turned off, return nothing // Filter: if both active and archived are turned off, return nothing
if !params.Archive && !params.Active { if !params.Archive && !params.Active {
sqlFilters = fmt.Sprintf(`--sql sqlFilters = fmt.Sprintf(`
%s %s
AND 0=1 AND 0=1
`, sqlFilters) `, sqlFilters)
@ -146,9 +167,9 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
// Filters: email // Filters: email
if len(params.Email) > 0 { if len(params.Email) > 0 {
sqlFilters = fmt.Sprintf(`--sql sqlFilters = fmt.Sprintf(`
%s %s
AND people.email LIKE @email AND LOWER(people.email) LIKE LOWER(@email)
`, sqlFilters) `, sqlFilters)
sqlParams = append(sqlParams, sql.Named( sqlParams = append(sqlParams, sql.Named(
"email", "email",
@ -158,35 +179,29 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
// Filters: phone // Filters: phone
if len(params.Phone) > 0 { if len(params.Phone) > 0 {
params.Phone = strings.ReplaceAll(params.Phone, " ", "") var phoneWithoutZeroFilter string
params.Phone = strings.ReplaceAll(params.Phone, "-", "") if string(params.Phone[0]) == "0" {
params.Phone = strings.ReplaceAll(params.Phone, ".", "") phoneWithoutZeroFilter = `
params.Phone = strings.ReplaceAll(params.Phone, "/", "") OR
params.Phone = strings.ReplaceAll(params.Phone, "+", "") TRANSLATE(people.phone, ' ,-,.,/,+', '') LIKE TRANSLATE(@phone2, ' ,-,.,/,+', '') OR
TRANSLATE(people.mobile, ' ,-,.,/,+', '') LIKE TRANSLATE(@phone2, ' ,-,.,/,+', '')
`
sqlFilters = fmt.Sprintf(`--sql phone2 := params.Phone[1:]
sqlParams = append(sqlParams, sql.Named(
"phone2",
fmt.Sprintf("%%%s%%", phone2),
))
}
sqlFilters = fmt.Sprintf(`
%s %s
AND ( AND (
REPLACE( TRANSLATE(people.phone, ' ,-,.,/,+', '') LIKE TRANSLATE(@phone, ' ,-,.,/,+', '') OR
REPLACE( TRANSLATE(people.mobile, ' ,-,.,/,+', '') LIKE TRANSLATE(@phone, ' ,-,.,/,+', '')
REPLACE( %s
REPLACE(
REPLACE(people.phone, ' ', '')
, '-', '')
, '.', '')
, '/', '')
, '+', '') LIKE @phone
OR REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(people.mobile, ' ', '')
, '-', '')
, '.', '')
, '/', '')
, '+', '') LIKE @phone
) )
`, sqlFilters) `, sqlFilters, phoneWithoutZeroFilter)
sqlParams = append(sqlParams, sql.Named( sqlParams = append(sqlParams, sql.Named(
"phone", "phone",
fmt.Sprintf("%%%s%%", params.Phone), fmt.Sprintf("%%%s%%", params.Phone),
@ -195,7 +210,7 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
// Filters: address // Filters: address
if len(params.Address) > 0 { if len(params.Address) > 0 {
sqlFilters = fmt.Sprintf(`--sql sqlFilters = fmt.Sprintf(`
%s %s
AND ( AND (
people.address1 LIKE @address people.address1 LIKE @address
@ -210,7 +225,7 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
// Filters: postal code // Filters: postal code
if len(params.PostalCode) > 0 { if len(params.PostalCode) > 0 {
sqlFilters = fmt.Sprintf(`--sql sqlFilters = fmt.Sprintf(`
%s %s
AND people.postal_code = @postal_code AND people.postal_code = @postal_code
`, sqlFilters) `, sqlFilters)
@ -222,7 +237,7 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
// Filters: city // Filters: city
if len(params.City) > 0 { if len(params.City) > 0 {
sqlFilters = fmt.Sprintf(`--sql sqlFilters = fmt.Sprintf(`
%s %s
AND people.city LIKE @city AND people.city LIKE @city
`, sqlFilters) `, sqlFilters)
@ -233,7 +248,7 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
} }
// Security filter: only show results in allowed secitons // Security filter: only show results in allowed secitons
sqlFilters = fmt.Sprintf(`--sql sqlFilters = fmt.Sprintf(`
%s %s
AND people.section_id IN @allowed_sections AND people.section_id IN @allowed_sections
`, sqlFilters) `, sqlFilters)
@ -250,7 +265,7 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
continue continue
} }
sqlFieldJoins = fmt.Sprintf(`--sql sqlFieldJoins = fmt.Sprintf(`
%s %s
LEFT JOIN field_values LEFT JOIN field_values
AS field_%d AS field_%d
@ -271,36 +286,53 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
} }
switch v := value.(type) { switch v := value.(type) {
default:
fmt.Println(v)
continue
case string: case string:
filter = fmt.Sprintf(`--sql if field.FieldType == "date" {
%s filter = fmt.Sprintf(`
field_%d.value_string LIKE @field_%d_%d %s
OR field_%d.value_date LIKE @field_%d_%d TO_CHAR(field_%d.value_date, 'YYYY-MM-DD') = @field_%d_%d
`, filter, field.ID, field.ID, index, field.ID, field.ID, index) `, filter, field.ID, field.ID, index)
sqlParams = append(sqlParams, sql.Named( sqlParams = append(sqlParams, sql.Named(
fmt.Sprintf("field_%d_%d", field.ID, index), fmt.Sprintf("field_%d_%d", field.ID, index),
fmt.Sprintf("%%%s%%", v), v,
)) ))
} else {
filter = fmt.Sprintf(`
%s
LOWER(field_%d.value_string) LIKE LOWER(@field_%d_%d)
`, filter, field.ID, field.ID, index)
sqlParams = append(sqlParams, sql.Named(
fmt.Sprintf("field_%d_%d", field.ID, index),
fmt.Sprintf("%%%s%%", v),
))
}
case float64: case float64:
filter = fmt.Sprintf(`--sql if field.FieldType == "list" {
%s filter = fmt.Sprintf(`
field_%d.value_int = @field_%d_%d %s
OR field_%d.list_item_id = @field_%d_%d field_%d.list_item_id = @field_%d_%d
`, filter, field.ID, field.ID, index, field.ID, field.ID, index) `, filter, field.ID, field.ID, index)
sqlParams = append(sqlParams, sql.Named( sqlParams = append(sqlParams, sql.Named(
fmt.Sprintf("field_%d_%d", field.ID, index), fmt.Sprintf("field_%d_%d", field.ID, index),
v, v,
)) ))
} else {
filter = fmt.Sprintf(`
%s
field_%d.value_int = @field_%d_%d
`, filter, field.ID, field.ID, index)
sqlParams = append(sqlParams, sql.Named(
fmt.Sprintf("field_%d_%d", field.ID, index),
v,
))
}
} }
fieldFilter = fmt.Sprintf("%s %s", fieldFilter, filter) fieldFilter = fmt.Sprintf("%s %s", fieldFilter, filter)
} }
if fieldFilter != "" { if fieldFilter != "" {
sqlFilters = fmt.Sprintf(`--sql sqlFilters = fmt.Sprintf(`
%s %s
AND (%s) AND (%s)
`, sqlFilters, fieldFilter) `, sqlFilters, fieldFilter)
@ -308,7 +340,7 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
} }
// Build and run count query // Build and run count query
sqlQueryCount = fmt.Sprintf(`--sql sqlQueryCount = fmt.Sprintf(`
%s %s
%s %s
%s %s
@ -330,7 +362,7 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
var sqlPagination string var sqlPagination string
if params.PageSize > 0 { if params.PageSize > 0 {
sqlPagination = `--sql sqlPagination = `
LIMIT @pagination_limit LIMIT @pagination_limit
OFFSET @pagination_offset OFFSET @pagination_offset
` `
@ -339,16 +371,16 @@ func PeopleSearch(params PeopleSearchParams) (PeopleSearchResults, error) {
} }
// Build and run paginated result query // Build and run paginated result query
sqlQuery = fmt.Sprintf(`--sql sqlQuery = fmt.Sprintf(`
%s %s
%s %s
%s %s
GROUP BY people.id GROUP BY people.id
ORDER BY CONCAT(people.last_name, people.first_name) COLLATE NOCASE ASC ORDER BY %s %s
%s %s
`, sqlQuery, sqlFieldJoins, sqlFilters, sqlPagination) `, sqlQuery, sqlFieldJoins, sqlFilters, params.OrderColumn, params.OrderDirection, sqlPagination)
sqlResult := db.Raw(sqlQuery, sqlParams...).Scan(&results.Results) sqlResult := db.Raw(sqlQuery, sqlParams...).Preload("Section").Find(&results.Results)
if sqlResult.Error != nil { if sqlResult.Error != nil {
return results, sqlResult.Error return results, sqlResult.Error
} }

View file

@ -16,7 +16,7 @@ func FirstAccountCheck() (bool, error) {
} }
var user models.User var user models.User
result := db.First(&user, "is_admin = 1") result := db.First(&user, "is_admin = ?", true)
if errors.Is(result.Error, gorm.ErrRecordNotFound) { if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return false, nil return false, nil

View file

@ -11,8 +11,8 @@ type Field struct {
Name string Name string
PersonType string PersonType string
FieldType string FieldType string
ListID uint ListID *uint
List List List *List
Position int Position int
} }
@ -25,8 +25,8 @@ type FieldValue struct {
ValueString sql.NullString ValueString sql.NullString
ValueInt sql.NullInt64 ValueInt sql.NullInt64
ValueDate sql.NullTime ValueDate sql.NullTime
ListItemID uint ListItemID *uint
ListItem ListItem ListItem *ListItem
} }
var PersonTypes = map[string]string{ var PersonTypes = map[string]string{

View file

@ -6,7 +6,7 @@ type Section struct {
gorm.Model gorm.Model
Name string Name string
ShortName string ShortName string
ParentSectionID uint ParentSectionID *uint
ParentSection *Section ParentSection *Section
ContainsMembers bool ContainsMembers bool
ContainsContacts bool ContainsContacts bool

View file

@ -8,8 +8,9 @@
"url": "https://git.readonly.ch/bouzoure/pop-camarades" "url": "https://git.readonly.ch/bouzoure/pop-camarades"
}, },
"devDependencies": { "devDependencies": {
"parcel": "^2.15.0", "@parcel/transformer-sass": "2.15.4",
"prettier": "^3.5.3", "parcel": "^2.15.4",
"prettier": "^3.6.2",
"prettier-plugin-jinja-template": "^2.1.0" "prettier-plugin-jinja-template": "^2.1.0"
}, },
"source": "frontend/index.js", "source": "frontend/index.js",
@ -31,7 +32,7 @@
"build": "go build" "build": "go build"
}, },
"dependencies": { "dependencies": {
"bootstrap": "^5.3.6", "bootstrap": "^5.3.7",
"bootstrap-icons": "^1.13.1", "bootstrap-icons": "^1.13.1",
"jquery": "^3.7.1" "jquery": "^3.7.1"
} }

1244
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -688,9 +688,9 @@ Public License instead of this License. But first, please read
## github.com/andybalholm/brotli ## github.com/andybalholm/brotli
* Name: github.com/andybalholm/brotli * Name: github.com/andybalholm/brotli
* Version: v1.1.1 * Version: v1.2.0
* License: [MIT](https://github.com/andybalholm/brotli/blob/v1.1.1/LICENSE) * License: [MIT](https://github.com/andybalholm/brotli/blob/v1.2.0/LICENSE)
``` ```
@ -785,9 +785,9 @@ SOFTWARE.
## github.com/brianvoe/gofakeit/v7 ## github.com/brianvoe/gofakeit/v7
* Name: github.com/brianvoe/gofakeit/v7 * Name: github.com/brianvoe/gofakeit/v7
* Version: v7.2.1 * Version: v7.3.0
* License: [MIT](https://github.com/brianvoe/gofakeit/blob/v7.2.1/LICENSE.txt) * License: [MIT](https://github.com/brianvoe/gofakeit/blob/v7.3.0/LICENSE.txt)
``` ```
@ -950,9 +950,9 @@ SOFTWARE.
## github.com/charmbracelet/log ## github.com/charmbracelet/log
* Name: github.com/charmbracelet/log * Name: github.com/charmbracelet/log
* Version: v0.4.1 * Version: v0.4.2
* License: [MIT](https://github.com/charmbracelet/log/blob/v0.4.1/LICENSE) * License: [MIT](https://github.com/charmbracelet/log/blob/v0.4.2/LICENSE)
``` ```
@ -983,9 +983,9 @@ SOFTWARE.
## github.com/charmbracelet/x/ansi ## github.com/charmbracelet/x/ansi
* Name: github.com/charmbracelet/x/ansi * Name: github.com/charmbracelet/x/ansi
* Version: v0.9.2 * Version: v0.9.3
* License: [MIT](https://github.com/charmbracelet/x/blob/ansi/v0.9.2/ansi/LICENSE) * License: [MIT](https://github.com/charmbracelet/x/blob/ansi/v0.9.3/ansi/LICENSE)
``` ```
@ -1629,77 +1629,6 @@ SOFTWARE.
``` ```
## github.com/glebarez/go-sqlite
* Name: github.com/glebarez/go-sqlite
* Version: v1.22.0
* License: [BSD-3-Clause](https://github.com/glebarez/go-sqlite/blob/v1.22.0/LICENSE)
```
Copyright (c) 2017 The Sqlite Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```
## github.com/glebarez/sqlite
* Name: github.com/glebarez/sqlite
* Version: v1.11.0
* License: [MIT](https://github.com/glebarez/sqlite/blob/v1.11.0/License)
```
The MIT License (MIT)
Copyright (c) 2013-NOW Jinzhu <wosmvp@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
```
## github.com/go-logfmt/logfmt ## github.com/go-logfmt/logfmt
* Name: github.com/go-logfmt/logfmt * Name: github.com/go-logfmt/logfmt
@ -1802,9 +1731,9 @@ SOFTWARE.
## github.com/go-playground/validator/v10 ## github.com/go-playground/validator/v10
* Name: github.com/go-playground/validator/v10 * Name: github.com/go-playground/validator/v10
* Version: v10.26.0 * Version: v10.27.0
* License: [MIT](https://github.com/go-playground/validator/blob/v10.26.0/LICENSE) * License: [MIT](https://github.com/go-playground/validator/blob/v10.27.0/LICENSE)
``` ```
@ -1836,9 +1765,9 @@ SOFTWARE.
## github.com/gofiber/fiber/v2 ## github.com/gofiber/fiber/v2
* Name: github.com/gofiber/fiber/v2 * Name: github.com/gofiber/fiber/v2
* Version: v2.52.6 * Version: v2.52.8
* License: [MIT](https://github.com/gofiber/fiber/blob/v2.52.6/LICENSE) * License: [MIT](https://github.com/gofiber/fiber/blob/v2.52.8/LICENSE)
``` ```
@ -1869,9 +1798,9 @@ SOFTWARE.
## github.com/gofiber/fiber/v2/internal/schema ## github.com/gofiber/fiber/v2/internal/schema
* Name: github.com/gofiber/fiber/v2/internal/schema * Name: github.com/gofiber/fiber/v2/internal/schema
* Version: v2.52.6 * Version: v2.52.8
* License: [BSD-3-Clause](https://github.com/gofiber/fiber/blob/v2.52.6/internal/schema/LICENSE) * License: [BSD-3-Clause](https://github.com/gofiber/fiber/blob/v2.52.8/internal/schema/LICENSE)
``` ```
@ -2007,9 +1936,9 @@ SOFTWARE.
## github.com/gofiber/template/django/v3 ## github.com/gofiber/template/django/v3
* Name: github.com/gofiber/template/django/v3 * Name: github.com/gofiber/template/django/v3
* Version: v3.1.13 * Version: v3.1.14
* License: [MIT](https://github.com/gofiber/template/blob/django/v3.1.13/django/LICENSE) * License: [MIT](https://github.com/gofiber/template/blob/django/v3.1.14/django/LICENSE)
``` ```
@ -2073,9 +2002,9 @@ SOFTWARE.
## github.com/gofiber/utils/v2 ## github.com/gofiber/utils/v2
* Name: github.com/gofiber/utils/v2 * Name: github.com/gofiber/utils/v2
* Version: v2.0.0-beta.8 * Version: v2.0.0-beta.10
* License: [MIT](https://github.com/gofiber/utils/blob/v2.0.0-beta.8/LICENSE) * License: [MIT](https://github.com/gofiber/utils/blob/v2.0.0-beta.10/LICENSE)
``` ```
@ -2751,6 +2680,142 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
``` ```
## github.com/jackc/pgpassfile
* Name: github.com/jackc/pgpassfile
* Version: v1.0.0
* License: [MIT](https://github.com/jackc/pgpassfile/blob/v1.0.0/LICENSE)
```
Copyright (c) 2019 Jack Christensen
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
```
## github.com/jackc/pgservicefile
* Name: github.com/jackc/pgservicefile
* Version: v0.0.0-20240606120523-5a60cdf6a761
* License: [MIT](https://github.com/jackc/pgservicefile/blob/5a60cdf6a761/LICENSE)
```
Copyright (c) 2020 Jack Christensen
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
```
## github.com/jackc/pgx/v5
* Name: github.com/jackc/pgx/v5
* Version: v5.7.5
* License: [MIT](https://github.com/jackc/pgx/blob/v5.7.5/LICENSE)
```
Copyright (c) 2013-2021 Jack Christensen
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
```
## github.com/jackc/puddle/v2
* Name: github.com/jackc/puddle/v2
* Version: v2.2.2
* License: [MIT](https://github.com/jackc/puddle/blob/v2.2.2/LICENSE)
```
Copyright (c) 2018 Jack Christensen
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
```
## github.com/jinzhu/inflection ## github.com/jinzhu/inflection
* Name: github.com/jinzhu/inflection * Name: github.com/jinzhu/inflection
@ -3416,9 +3481,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## github.com/pquerna/otp ## github.com/pquerna/otp
* Name: github.com/pquerna/otp * Name: github.com/pquerna/otp
* Version: v1.4.0 * Version: v1.5.0
* License: [Apache-2.0](https://github.com/pquerna/otp/blob/v1.4.0/LICENSE) * License: [Apache-2.0](https://github.com/pquerna/otp/blob/v1.5.0/LICENSE)
``` ```
@ -3627,45 +3692,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
``` ```
## github.com/remyoudompheng/bigfft
* Name: github.com/remyoudompheng/bigfft
* Version: v0.0.0-20230129092748-24d4a6f8daec
* License: [BSD-3-Clause](https://github.com/remyoudompheng/bigfft/blob/24d4a6f8daec/LICENSE)
```
Copyright (c) 2012 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```
## github.com/rivo/uniseg ## github.com/rivo/uniseg
* Name: github.com/rivo/uniseg * Name: github.com/rivo/uniseg
@ -3736,9 +3762,9 @@ SOFTWARE.
## github.com/valyala/fasthttp ## github.com/valyala/fasthttp
* Name: github.com/valyala/fasthttp * Name: github.com/valyala/fasthttp
* Version: v1.62.0 * Version: v1.63.0
* License: [MIT](https://github.com/valyala/fasthttp/blob/v1.62.0/LICENSE) * License: [MIT](https://github.com/valyala/fasthttp/blob/v1.63.0/LICENSE)
``` ```
@ -3757,9 +3783,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
## github.com/valyala/fasthttp/reuseport ## github.com/valyala/fasthttp/reuseport
* Name: github.com/valyala/fasthttp/reuseport * Name: github.com/valyala/fasthttp/reuseport
* Version: v1.62.0 * Version: v1.63.0
* License: [MIT](https://github.com/valyala/fasthttp/blob/v1.62.0/reuseport/LICENSE) * License: [MIT](https://github.com/valyala/fasthttp/blob/v1.63.0/reuseport/LICENSE)
``` ```
@ -3822,9 +3848,9 @@ SOFTWARE.
## github.com/yuin/goldmark ## github.com/yuin/goldmark
* Name: github.com/yuin/goldmark * Name: github.com/yuin/goldmark
* Version: v1.7.11 * Version: v1.7.12
* License: [MIT](https://github.com/yuin/goldmark/blob/v1.7.11/LICENSE) * License: [MIT](https://github.com/yuin/goldmark/blob/v1.7.12/LICENSE)
``` ```
@ -4068,48 +4094,9 @@ SOFTWARE.
## golang.org/x/crypto ## golang.org/x/crypto
* Name: golang.org/x/crypto * Name: golang.org/x/crypto
* Version: v0.38.0 * Version: v0.40.0
* License: [BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.38.0:LICENSE) * License: [BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.40.0:LICENSE)
```
Copyright 2009 The Go Authors.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google LLC nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```
## golang.org/x/exp/constraints
* Name: golang.org/x/exp/constraints
* Version: v0.0.0-20250506013437-ce4c2cf36ca6
* License: [BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/ce4c2cf3:LICENSE)
``` ```
@ -4146,9 +4133,48 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## golang.org/x/net ## golang.org/x/net
* Name: golang.org/x/net * Name: golang.org/x/net
* Version: v0.40.0 * Version: v0.42.0
* License: [BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.40.0:LICENSE) * License: [BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.42.0:LICENSE)
```
Copyright 2009 The Go Authors.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google LLC nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```
## golang.org/x/sync/semaphore
* Name: golang.org/x/sync/semaphore
* Version: v0.16.0
* License: [BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.16.0:LICENSE)
``` ```
@ -4185,9 +4211,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## golang.org/x/sys ## golang.org/x/sys
* Name: golang.org/x/sys * Name: golang.org/x/sys
* Version: v0.33.0 * Version: v0.34.0
* License: [BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.33.0:LICENSE) * License: [BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.34.0:LICENSE)
``` ```
@ -4224,9 +4250,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## golang.org/x/text ## golang.org/x/text
* Name: golang.org/x/text * Name: golang.org/x/text
* Version: v0.25.0 * Version: v0.27.0
* License: [BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.25.0:LICENSE) * License: [BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.27.0:LICENSE)
``` ```
@ -4299,12 +4325,45 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
``` ```
## gorm.io/driver/postgres
* Name: gorm.io/driver/postgres
* Version: v1.6.0
* License: [MIT](https://github.com/go-gorm/postgres/blob/v1.6.0/License)
```
The MIT License (MIT)
Copyright (c) 2013-NOW Jinzhu <wosmvp@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
```
## gorm.io/gorm ## gorm.io/gorm
* Name: gorm.io/gorm * Name: gorm.io/gorm
* Version: v1.26.1 * Version: v1.30.0
* License: [MIT](https://github.com/go-gorm/gorm/blob/v1.26.1/LICENSE) * License: [MIT](https://github.com/go-gorm/gorm/blob/v1.30.0/LICENSE)
``` ```
@ -4332,131 +4391,3 @@ THE SOFTWARE.
``` ```
## modernc.org/libc
* Name: modernc.org/libc
* Version: v1.65.4
* License: [BSD-3-Clause](https://gitlab.com/cznic/libc/blob/v1.65.4/LICENSE-GO)
```
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```
## modernc.org/mathutil
* Name: modernc.org/mathutil
* Version: v1.7.1
* License: Unknown
```
```
## modernc.org/memory
* Name: modernc.org/memory
* Version: v1.10.0
* License: [BSD-3-Clause](https://gitlab.com/cznic/memory/blob/v1.10.0/LICENSE-GO)
```
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```
## modernc.org/sqlite/lib
* Name: modernc.org/sqlite/lib
* Version: v1.37.0
* License: [BSD-3-Clause](https://gitlab.com/cznic/sqlite/blob/v1.37.0/LICENSE)
```
Copyright (c) 2017 The Sqlite Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container mt-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -12,20 +12,22 @@
<hr /> <hr />
</div> </div>
{% if Errors %} <form id="account" method="post" style="max-width: 1200px;">
<div class="alert alert-danger"> {% if Errors %}
<ul class="m-0"> <div class="alert alert-danger">
{% for Error in Errors %} <ul class="m-0">
<li>{{ Error }}</li> {% for Error in Errors %}
{% endfor %} <li>{{ Error }}</li>
</ul> {% endfor %}
</div> </ul>
{% endif %} </div>
{% endif %}
<form id="account" method="post">
<div class="row mb-3"> <div class="row mb-3">
<label for="name" class="col-md-2 form-label"> Nom complet </label> <label for="name" class="col-md-2 col-xl-3 form-label">
<div class="col-md-10"> Nom complet
</label>
<div class="col-md-10 col-xl-9">
<input <input
id="name" id="name"
class="form-control" class="form-control"
@ -40,8 +42,8 @@
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<label for="email" class="col-md-2 form-label"> Email </label> <label for="email" class="col-md-2 col-xl-3 form-label"> Email </label>
<div class="col-md-10"> <div class="col-md-10 col-xl-9">
<input <input
id="email" id="email"
class="form-control" class="form-control"
@ -55,8 +57,10 @@
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<label for="password" class="col-md-2 form-label"> Mot de passe </label> <label for="password" class="col-md-2 col-xl-3 form-label">
<div class="col-md-10"> Mot de passe
</label>
<div class="col-md-10 col-xl-9">
<input <input
id="password" id="password"
class="form-control" class="form-control"
@ -69,10 +73,10 @@
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<label for="password" class="col-md-2 form-label"> <label for="password" class="col-md-2 col-xl-3 form-label">
Confirmer le mot de passe Confirmer le mot de passe
</label> </label>
<div class="col-md-10"> <div class="col-md-10 col-xl-9">
<input <input
id="password-verify" id="password-verify"
class="form-control" class="form-control"

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container mt-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container mt-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -12,44 +12,83 @@
<hr /> <hr />
</div> </div>
<div class="row"> <div class="row mw-900">
<div class="col-md-6"> <div class="col-12">
<a class="dashboard-tile" href="/admin/sections"> <a class="dashboard-tile" href="/admin/sections">
<div class="alert alert-primary"> <div class="alert alert-primary">
<i class="bi-building me-2"></i> <div class="row align-items-center">
Gestion des sections <div class="col-12 text-center text-md-start col-md-6">
<i class="bi-building me-2"></i>
Gestion des sections
</div>
<div class="col text-center text-md-end fs-1">
{{ SectionsCount }}
</div>
</div>
</div> </div>
</a> </a>
</div> </div>
<div class="col-md-6">
<div class="col-12">
<a class="dashboard-tile" href="/admin/lists"> <a class="dashboard-tile" href="/admin/lists">
<div class="alert alert-primary"> <div class="alert alert-primary">
<i class="bi-list-check me-2"></i> <div class="row align-items-center">
Gestion des listes <div class="col-12 text-center text-md-start col-md-6">
<i class="bi-list-check me-2"></i>
Gestion des listes
</div>
<div class="col text-center text-md-end fs-1">
{{ ListsCount }}
</div>
</div>
</div> </div>
</a> </a>
</div> </div>
<div class="col-md-6">
<div class="col-12">
<a class="dashboard-tile" href="/admin/fields"> <a class="dashboard-tile" href="/admin/fields">
<div class="alert alert-primary"> <div class="alert alert-primary">
<i class="bi-database-add me-2"></i> <div class="row align-items-center">
Gestion des champs supplémentaires <div class="col-12 text-center text-md-start col-md-6">
<i class="bi-database-add me-2"></i>
Gestion des champs supplémentaires
</div>
<div class="col text-center text-md-end fs-1">
{{ FieldsCount }}
</div>
</div>
</div> </div>
</a> </a>
</div> </div>
<div class="col-md-6">
<div class="col-12">
<a class="dashboard-tile" href="/admin/users"> <a class="dashboard-tile" href="/admin/users">
<div class="alert alert-primary"> <div class="alert alert-primary">
<i class="bi-person-square me-2"></i> <div class="row align-items-center">
Gestion des utilisateurs <div class="col-12 text-center text-md-start col-md-6">
<i class="bi-person-square me-2"></i>
Gestion des utilisateurs
</div>
<div class="col text-center text-md-end fs-1">
{{ UsersCount }}
</div>
</div>
</div> </div>
</a> </a>
</div> </div>
<div class="col-md-6">
<div class="col-12">
<a class="dashboard-tile" href="/admin/roles"> <a class="dashboard-tile" href="/admin/roles">
<div class="alert alert-primary"> <div class="alert alert-primary">
<i class="bi-briefcase me-2"></i> <div class="row align-items-center">
Gestion des rôles <div class="col-12 text-center text-md-start col-md-6">
<i class="bi-briefcase me-2"></i>
Gestion des rôles
</div>
<div class="col text-center text-md-end fs-1">
{{ RolesCount }}
</div>
</div>
</div> </div>
</a> </a>
</div> </div>

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container text-center py-5"> <div class="container-fluid my-4 px-4 text-center py-5">
<div class="h1 mb-3">Erreur {{ Code }}</div> <div class="h1 mb-3">Erreur {{ Code }}</div>
<code>{{ Message }}</code> <code>{{ Message }}</code>
</div> </div>

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container mt-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -16,103 +16,105 @@
<hr /> <hr />
</div> </div>
<div class="row mb-3"> <div class="mw-1200">
<div class="col-md-2">Nom du champ</div> <div class="row align-items-center mb-3">
<div class="col-md-10"> <div class="col-md-2">Nom du champ</div>
<input <div class="col-md-10">
type="text" <input
class="form-control" type="text"
value="{{ Field.Name }}" class="form-control"
disabled value="{{ Field.Name }}"
readonly disabled
/> readonly
/>
</div>
</div> </div>
</div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<div class="col-md-2">Population</div> <div class="col-md-2">Population</div>
<div class="col-md-10"> <div class="col-md-10">
{% for Key, Value in PersonTypes %} {% for Key, Value in PersonTypes %}
{% if Key == Field.PersonType %} {% if Key == Field.PersonType %}
<input <input
type="text" type="text"
class="form-control" class="form-control"
value="{{ Value }}" value="{{ Value }}"
disabled disabled
readonly readonly
/> />
{% endif %}
{% endfor %}
</div>
</div>
<div class="row align-items-center mb-3">
<div class="col-md-2">Type de champ</div>
<div class="col-md-10">
{% for Key, Value in FieldTypes %}
{% if Key == Field.FieldType %}
<input
type="text"
class="form-control"
value="{{ Value }}"
disabled
readonly
/>
{% endif %}
{% endfor %}
</div>
</div>
<div class="row align-items-center mb-3">
<div class="col-md-2">Liste</div>
<div class="col-md-10">
{% if Field.ListID %}
<div class="input-group">
<input
type="text"
class="form-control"
value="{{ Field.List.Name }}"
readonly
disabled
/>
<span class="input-group-text">
<a href="/admin/lists/{{ Field.List.ID }}">
Afficher
<i class="bi-box-arrow-up-right ms-1"></i>
</a>
</span>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %} {% endif %}
{% endfor %} </div>
</div> </div>
</div>
<div class="row mb-3"> <div class="row align-items-center my-4">
<div class="col-md-2">Type de champ</div> <div class="col-6">
<div class="col-md-10"> <a
{% for Key, Value in FieldTypes %} class="btn btn-outline-primary"
{% if Key == Field.FieldType %} href="/admin/fields/{{ Field.ID }}/edit"
<input >
type="text" <i class="bi-pencil-square"></i>
class="form-control" Modifier
value="{{ Value }}" </a>
disabled </div>
readonly <div class="col-6 text-end">
/> <button
{% endif %} type="button"
{% endfor %} class="btn btn-outline-danger"
</div> data-bs-toggle="modal"
</div> data-bs-target="#modal-delete"
>
<div class="row mb-3"> <i class="bi-trash3 me-1"></i>
<div class="col-md-2">Liste</div> Supprimer
<div class="col-md-10"> </button>
{% if Field.ListID %} </div>
<div class="input-group">
<input
type="text"
class="form-control"
value="{{ Field.List.Name }}"
readonly
disabled
/>
<span class="input-group-text">
<a href="/admin/lists/{{ Field.List.ID }}">
Afficher
<i class="bi-box-arrow-up-right ms-1"></i>
</a>
</span>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row my-4">
<div class="col-6">
<a
class="btn btn-outline-primary"
href="/admin/fields/{{ Field.ID }}/edit"
>
<i class="bi-pencil-square"></i>
Modifier
</a>
</div>
<div class="col-6 text-end">
<button
type="button"
class="btn btn-outline-danger"
data-bs-toggle="modal"
data-bs-target="#modal-delete"
>
<i class="bi-trash3 me-1"></i>
Supprimer
</button>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container mt-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -24,19 +24,21 @@
<hr /> <hr />
</div> </div>
{% if Errors %} <form id="field" method="post" class="mw-1200">
<div class="alert alert-danger"> {% if Errors %}
<ul class="m-0"> <div class="alert alert-danger">
{% for Error in Errors %} <ul class="m-0">
<li>{{ Error }}</li> {% for Error in Errors %}
{% endfor %} <li>{{ Error }}</li>
</ul> {% endfor %}
</div> </ul>
{% endif %} </div>
{% endif %}
<form id="field" method="post"> <div class="row align-items-center mb-3">
<div class="row mb-3"> <label for="name" class="form-label mb-0 col-md-2">
<label for="name" class="form-label col-md-2"> Nom du champ </label> Nom du champ
</label>
<div class="col-md-10"> <div class="col-md-10">
<input <input
id="name" id="name"
@ -52,8 +54,8 @@
</div> </div>
{% if !Field.ID %} {% if !Field.ID %}
<div class="row mb-3"> <div class="row align-items-center mb-3">
<label for="person_type" class="form-label col-md-2"> <label for="person_type" class="form-label mb-0 col-md-2">
Population Population
</label> </label>
<div class="col-md-10"> <div class="col-md-10">
@ -65,13 +67,13 @@
required required
> >
<option value="member">Membre</option> <option value="member">Membre</option>
<option value="contact">Contact</option> <option value="contact">Sympathisant</option>
</select> </select>
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<label for="field_type" class="form-label col-md-2"> <label for="field_type" class="form-label mb-0 col-md-2">
Type de champ Type de champ
</label> </label>
<div class="col-md-10"> <div class="col-md-10">
@ -91,8 +93,8 @@
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<label for="list" class="form-label col-md-2"> Liste </label> <label for="list" class="form-label mb-0 col-md-2"> Liste </label>
<div class="col-md-10"> <div class="col-md-10">
<select <select
name="list" name="list"

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container my-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -13,39 +13,47 @@
<hr /> <hr />
</div> </div>
<div class="my-3 text-end"> <div class="row my-3">
<a class="btn btn-outline-primary" href="/admin/fields/add"> <div class="col-sm-6">
<i class="bi-plus-lg"></i> <span class="h2 d-none d-sm-inline">Champs supplémentaires</span>
Ajouter </div>
</a> <div class="col-sm-6 text-end">
<a class="btn btn-outline-primary" href="/admin/fields/add">
<i class="bi-plus-lg"></i>
Ajouter
</a>
</div>
</div> </div>
<div class="h4 my-2">Membres</div> <div class="card mb-3">
<div class="table-responsive"> <div class="card-header">Membres</div>
<table class="table"> <div class="card-body">
<thead> {% for Field in Fields %}
<tr> {% if Field.PersonType == "member" %}
<th class="w-50">Nom</th> <div class="card card-body my-2 py-2 bg-body-tertiary">
<th class="w-25">Type de champ</th> <div class="row align-items-center">
<th class="w-25"></th> <div class="col-12 col-md-8 col-lg-6">
</tr> <div class="text-bold fs-7 mt-xxl-0 mt-2">Nom</div>
</thead> <div>
<tbody> <a href="/admin/fields/{{ Field.ID }}">
{% for Field in Fields %} {{ Field.Name }}
{% if Field.PersonType == "member" %} </a>
<tr> </div>
<td> </div>
<a href="/admin/fields/{{ Field.ID }}"> {{ Field.Name }} </a>
</td> <div class="col-12 col-md-4 col-lg-3">
<td> <div class="text-bold fs-7 mt-xxl-0 mt-2">Type de champ</div>
{% for Key, Value in FieldTypes %} <div>
{% if Key == Field.FieldType %} {% for Key, Value in FieldTypes %}
{{ Value }} {% if Key == Field.FieldType %}
{% endif %} <span class="badge text-bg-primary"> {{ Value }} </span>
{% endfor %} {% endif %}
</td> {% endfor %}
<td class="text-end"> </div>
<div class="btn-group"> </div>
<div class="col text-lg-end">
<div class="btn-group mb-2 mt-3 mt-lg-0 mb-lg-0">
<a <a
class="btn btn-sm btn-outline-primary" class="btn btn-sm btn-outline-primary"
href="/admin/fields/{{ Field.ID }}/move-up" href="/admin/fields/{{ Field.ID }}/move-up"
@ -61,40 +69,43 @@
Descendre Descendre
</a> </a>
</div> </div>
</td> </div>
</tr> </div>
{% endif %} </div>
{% endfor %} {% endif %}
</tbody> {% endfor %}
</table> </div>
</div> </div>
<div class="h4 my-2">Contacts</div> <div class="card">
<div class="table-responsive"> <div class="card-header">Sympathisants</div>
<table class="table"> <div class="card-body">
<thead> {% for Field in Fields %}
<tr> {% if Field.PersonType == "contact" %}
<th class="w-50">Nom</th> <div class="card card-body my-2 py-2 bg-body-tertiary">
<th class="w-25">Type de champ</th> <div class="row align-items-center">
<th class="w-25"></th> <div class="col-12 col-md-8 col-lg-6">
</tr> <div class="text-bold fs-7 mt-xxl-0 mt-2">Nom</div>
</thead> <div>
<tbody> <a href="/admin/fields/{{ Field.ID }}">
{% for Field in Fields %} {{ Field.Name }}
{% if Field.PersonType == "contact" %} </a>
<tr> </div>
<td> </div>
<a href="/admin/fields/{{ Field.ID }}"> {{ Field.Name }} </a>
</td> <div class="col-12 col-md-4 col-lg-3">
<td> <div class="text-bold fs-7 mt-xxl-0 mt-2">Type de champ</div>
{% for Key, Value in FieldTypes %} <div>
{% if Key == Field.FieldType %} {% for Key, Value in FieldTypes %}
{{ Value }} {% if Key == Field.FieldType %}
{% endif %} <span class="badge text-bg-primary"> {{ Value }} </span>
{% endfor %} {% endif %}
</td> {% endfor %}
<td class="text-end"> </div>
<div class="btn-group"> </div>
<div class="col text-lg-end">
<div class="btn-group mb-2 mt-3 mt-lg-0 mb-lg-0">
<a <a
class="btn btn-sm btn-outline-primary" class="btn btn-sm btn-outline-primary"
href="/admin/fields/{{ Field.ID }}/move-up" href="/admin/fields/{{ Field.ID }}/move-up"
@ -110,12 +121,12 @@
Descendre Descendre
</a> </a>
</div> </div>
</td> </div>
</tr> </div>
{% endif %} </div>
{% endfor %} {% endif %}
</tbody> {% endfor %}
</table> </div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container mt-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -11,35 +11,56 @@
<hr /> <hr />
</div> </div>
<div class="row"> <div class="row mw-900">
{% if Globals.AllowMembersPage %} {% if Globals.AllowMembersPage %}
<div class="col-md-6"> <div class="col-12">
<a class="dashboard-tile" href="/members"> <a class="dashboard-tile" href="/members">
<div class="alert alert-primary"> <div class="alert alert-primary">
<i class="bi-people me-2"></i> <div class="row align-items-center">
Gestion des membres <div class="col-12 text-center text-md-start col-md-6">
<i class="bi-people me-2"></i>
Gestion des membres
</div>
<div class="col text-center text-md-end fs-1">
{{ MembersCount }}
</div>
</div>
</div> </div>
</a> </a>
</div> </div>
{% endif %} {% endif %}
{% if Globals.AllowContactsPage %} {% if Globals.AllowContactsPage %}
<div class="col-md-6"> <div class="col-12">
<a class="dashboard-tile" href="/contacts"> <a class="dashboard-tile" href="/contacts">
<div class="alert alert-primary"> <div class="alert alert-primary">
<i class="bi-telephone me-2"></i> <div class="row align-items-center">
Gestion des contacts <div class="col-12 text-center text-md-start col-md-6">
<i class="bi-telephone me-2"></i>
Gestion des sympathisants
</div>
<div class="col text-center text-md-end fs-1">
{{ ContactsCount }}
</div>
</div>
</div> </div>
</a> </a>
</div> </div>
{% endif %} {% endif %}
{% if Globals.UserIsAdmin %} {% if Globals.UserIsAdmin %}
<div class="col-md-6"> <div class="col-12">
<a class="dashboard-tile" href="/admin"> <a class="dashboard-tile" href="/admin">
<div class="alert alert-primary"> <div class="alert alert-primary">
<i class="bi-gear me-2"></i> <div class="row align-items-center">
Administration de l'application <div class="col-12 text-center text-md-start col-md-6">
<i class="bi-gear me-2"></i>
Administration de l'application
</div>
<div class="col text-center text-md-end fs-1">
<i class="bi-arrow-right"></i>
</div>
</div>
</div> </div>
</a> </a>
</div> </div>

View file

@ -35,7 +35,7 @@
</main> </main>
<footer class="footer mt-auto py-2 bg-body-tertiary"> <footer class="footer mt-auto py-2 bg-body-tertiary">
<div class="container"> <div class="container-fluid">
<span class="text-body-secondary"> <span class="text-body-secondary">
<a <a
class="text-body-secondary me-2" class="text-body-secondary me-2"

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container my-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -14,66 +14,63 @@
<hr /> <hr />
</div> </div>
<div class="row mb-3"> <div class="mw-1200">
<div class="col-md-2">Nom</div> <div class="row align-items-center mb-3">
<div class="col-md-10"> <div class="col-md-2 col-xl-3">Nom</div>
<input <div class="col-md-10 col-xl-9">
type="text" <input
class="form-control" type="text"
value="{{ List.Name }}" class="form-control"
disabled value="{{ List.Name }}"
readonly disabled
/> readonly
/>
</div>
</div> </div>
</div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<div class="col-md-2">Liste à choix multiples</div> <div class="col-md-2 col-xl-3">Liste à choix multiples</div>
<div class="col-md-10"> <div class="col-md-10 col-xl-9">
{% if List.Multi %} {% if List.Multi %}
<div class="input-group"> <div class="input-group">
<span class="input-group-text"> <span class="input-group-text">
<i class="bi-check-lg text-success"></i> <i class="bi-check-lg text-success"></i>
</span> </span>
<input type="text" class="form-control" value="Oui" disabled /> <input type="text" class="form-control" value="Oui" disabled />
</div> </div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="p-3 my-4 bg-body-tertiary border">
<div class="mb-3">
<span class="h5">Liste</span>
</div>
{% if ListItems %}
<ul class="p-0" style="list-style: none;">
{% for Item in ListItems %}
<li>
<a href="/admin/lists/{{ List.ID }}/items/{{ Item.ID }}">
{{ Item.Value }}
</a>
{% if Item.Default %}
<span class="badge text-bg-success">Par défaut</span>
{% endif %}
</li>
{% endfor %}
</ul>
{% else %} {% else %}
<div class="input-group"> <div class="mb-4">Pas encore d'éléments dans cette liste</div>
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %} {% endif %}
</div>
</div>
<div class="my-4 row">
<div class="col-6">
<a
class="btn btn-outline-primary"
href="/admin/lists/{{ List.ID }}/edit"
>
<i class="bi-pencil-square"></i>
Modifier
</a>
</div>
<div class="col-6 text-end">
<button
type="button"
class="btn btn-outline-danger"
data-bs-toggle="modal"
data-bs-target="#modal-delete"
>
<i class="bi-trash3 me-1"></i>
Supprimer
</button>
</div>
</div>
<div class="my-3 row">
<div class="col-sm-9 h4">Contenu de la liste</div>
<div class="col-sm-3 text-end">
<a <a
class="btn btn-outline-primary" class="btn btn-outline-primary"
href="/admin/lists/{{ List.ID }}/items/add" href="/admin/lists/{{ List.ID }}/items/add"
@ -82,54 +79,30 @@
Ajouter Ajouter
</a> </a>
</div> </div>
</div>
{% if ListItems %} <div class="my-4 row align-items-center">
<div class="table-responsive"> <div class="col-6">
<table class="table"> <a
<thead> class="btn btn-outline-primary"
<tr> href="/admin/lists/{{ List.ID }}/edit"
<th class="w-50">Valeur</th> >
<th class="w-25">Par défaut</th> <i class="bi-pencil-square"></i>
<th class="w-25"></th> Modifier
</tr> </a>
</thead> </div>
<tbody> <div class="col-6 text-end">
{% for Item in ListItems %} <button
<tr> type="button"
<td> class="btn btn-outline-danger"
<a href="/admin/lists/{{ List.ID }}/items/{{ Item.ID }}"> data-bs-toggle="modal"
{{ Item.Value }} data-bs-target="#modal-delete"
</a> >
</td> <i class="bi-trash3 me-1"></i>
<td> Supprimer
{% if Item.Default %} </button>
<i class="bi-check-lg text-success me-1"></i> </div>
Oui
{% else %}
<i class="bi-x-lg text-danger me-1"></i>
Non
{% endif %}
</td>
<td class="text-end">
<button
type="button"
class="btn btn-outline-danger btn-sm"
data-bs-toggle="modal"
data-bs-target="#modal-delete-value-{{ Item.ID }}"
>
<i class="bi-trash3 me-1"></i>
Supprimer
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div> </div>
{% else %} </div>
<div>Pas encore d'éléments dans cette liste.</div>
{% endif %}
</div> </div>
<div id="modal-delete" class="modal" tabindex="-1"> <div id="modal-delete" class="modal" tabindex="-1">
@ -162,37 +135,4 @@
</div> </div>
</div> </div>
</div> </div>
{% for Item in ListItems %}
<div id="modal-delete-value-{{ Item.ID }}" class="modal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-body">
<p>Êtes-vous sûr de vouloir supprimer cette valeur ?</p>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-outline-secondary"
data-bs-dismiss="modal"
>
<i class="bi-x-lg me-1"></i>
Annuler
</button>
<form
action="/admin/lists/{{ List.ID }}/items/{{ Item.ID }}/delete"
method="post"
class="d-inline p-0"
>
<button class="btn btn-outline-danger" type="submit">
<i class="bi-trash3 me-1"></i>
Supprimer
</button>
</form>
</div>
</div>
</div>
</div>
{% endfor %}
{% endblock %} {% endblock %}

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container mt-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -22,20 +22,22 @@
<hr /> <hr />
</div> </div>
{% if Errors %} <form id="list" method="post" class="mw-1200">
<div class="alert alert-danger"> {% if Errors %}
<ul class="m-0"> <div class="alert alert-danger">
{% for Error in Errors %} <ul class="m-0">
<li>{{ Error }}</li> {% for Error in Errors %}
{% endfor %} <li>{{ Error }}</li>
</ul> {% endfor %}
</div> </ul>
{% endif %} </div>
{% endif %}
<form id="list" method="post"> <div class="row align-items-center mb-3">
<div class="row mb-3"> <label for="name" class="form-label mb-0 col-md-2 col-xl-3">
<label for="name" class="form-label col-md-2"> Nom </label> Nom
<div class="col-md-10"> </label>
<div class="col">
<input <input
id="name" id="name"
class="form-control" class="form-control"
@ -49,8 +51,8 @@
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<div class="col-md-10 offset-md-2"> <div class="col-md-10 offset-md-2 offset-xl-3">
<input <input
type="checkbox" type="checkbox"
class="form-check-input me-2" class="form-check-input me-2"

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container mt-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -22,19 +22,19 @@
<hr /> <hr />
</div> </div>
{% if Errors %} <form id="listitem" method="post" class="mw-900">
<div class="alert alert-danger"> {% if Errors %}
<ul class="m-0"> <div class="alert alert-danger">
{% for Error in Errors %} <ul class="m-0">
<li>{{ Error }}</li> {% for Error in Errors %}
{% endfor %} <li>{{ Error }}</li>
</ul> {% endfor %}
</div> </ul>
{% endif %} </div>
{% endif %}
<form id="listitem" method="post"> <div class="row align-items-center mb-3">
<div class="row mb-3"> <label for="value" class="form-label mb-0 col-md-2"> Valeur </label>
<label for="value" class="form-label col-md-2"> Valeur </label>
<div class="col-md-10"> <div class="col-md-10">
<input <input
id="value" id="value"
@ -49,7 +49,7 @@
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<div class="col-md-10 offset-md-2"> <div class="col-md-10 offset-md-2">
<input <input
type="checkbox" type="checkbox"
@ -67,12 +67,60 @@
</div> </div>
</div> </div>
<div class="my-4"> <div class="my-4 row align-items-center">
<button class="btn btn-outline-primary" type="submit"> <div class="col-6">
<i class="me-1 bi-floppy"></i> <button class="btn btn-outline-primary" type="submit">
Enregistrer <i class="me-1 bi-floppy"></i>
</button> Enregistrer
</button>
</div>
<div class="col-6 text-end">
{% if ListItem.ID %}
<button
type="button"
class="btn btn-outline-danger"
data-bs-toggle="modal"
data-bs-target="#modal-delete"
>
<i class="bi-trash3 me-1"></i>
Supprimer
</button>
{% endif %}
</div>
</div> </div>
</form> </form>
</div> </div>
{% if ListItem.ID %}
<div id="modal-delete" class="modal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-body">
<p>Êtes-vous sûr de vouloir supprimer cette valeur ?</p>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-outline-secondary"
data-bs-dismiss="modal"
>
<i class="bi-x-lg me-1"></i>
Annuler
</button>
<form
action="/admin/lists/{{ List.ID }}/items/{{ ListItem.ID }}/delete"
method="post"
class="d-inline p-0"
>
<button class="btn btn-outline-danger" type="submit">
<i class="bi-trash3 me-1"></i>
Supprimer
</button>
</form>
</div>
</div>
</div>
</div>
{% endif %}
{% endblock %} {% endblock %}

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container my-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -13,42 +13,42 @@
<hr /> <hr />
</div> </div>
<div class="my-3 text-end"> <div class="row my-3">
<a class="btn btn-outline-primary" href="/admin/lists/add"> <div class="col-sm-6">
<i class="bi-plus-lg"></i> <span class="h2 d-none d-sm-inline">Listes</span>
Ajouter </div>
</a> <div class="col-sm-6 text-end">
<a class="btn btn-outline-primary" href="/admin/lists/add">
<i class="bi-plus-lg"></i>
Ajouter
</a>
</div>
</div> </div>
{% if Lists %} {% if Lists %}
<div class="table-responsive"> {% for List in Lists %}
<table class="table"> <div class="card card-body my-2 py-2 bg-body-tertiary">
<thead> <div class="row">
<tr> <div class="col-12 col-sm-8 col-md-9 col-xl-6">
<th class="w-75">Nom</th> <div class="text-bold fs-7 mt-xxl-0 mt-2">Nom</div>
<th class="w-25">Choix multiples</th> <div>
</tr> <a href="/admin/lists/{{ List.ID }}"> {{ List.Name }} </a>
</thead> </div>
<tbody> </div>
{% for List in Lists %}
<tr> <div class="col">
<td> <div class="text-bold fs-7 mt-xxl-0 mt-2">Choix multiples</div>
<a href="/admin/lists/{{ List.ID }}"> {{ List.Name }} </a> <div>
</td> {% if List.Multi %}
<td> <span class="badge text-bg-success">Oui</span>
{% if List.Multi %} {% else %}
<i class="bi-check-lg text-success me-1"></i> <span class="badge text-bg-danger">Non</span>
Oui {% endif %}
{% else %} </div>
<i class="bi-x-lg text-danger me-1"></i> </div>
Non </div>
{% endif %} </div>
</td> {% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %} {% else %}
<div class="my-4">Pas de liste pour le moment</div> <div class="my-4">Pas de liste pour le moment</div>
{% endif %} {% endif %}

View file

@ -33,7 +33,7 @@
{% if Globals.AllowContactsPage %} {% if Globals.AllowContactsPage %}
<li class="nav-item"> <li class="nav-item">
<a class="nav-link active" href="/contacts"> <a class="nav-link active" href="/contacts">
<i class="bi-telephone me-2"></i>Contacts <i class="bi-telephone me-2"></i>Sympathisants
</a> </a>
</li> </li>
{% endif %} {% endif %}

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container my-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -10,49 +10,55 @@
{% if MembersPage %} {% if MembersPage %}
<li class="breadcrumb-item active">Membres</li> <li class="breadcrumb-item active">Membres</li>
{% else %} {% else %}
<li class="breadcrumb-item active">Contacts</li> <li class="breadcrumb-item active">Sympathisants</li>
{% endif %} {% endif %}
</ol> </ol>
</nav> </nav>
<hr /> <hr />
</div> </div>
<div class="my-3 text-end"> <div class="row my-3">
{% if MembersPage %} <div class="col-sm-6">
<div class="btn-group"> {% if MembersPage %}
<a class="btn btn-outline-primary" href="/members/add"> <span class="h2 d-none d-sm-inline">Membres</span>
<i class="bi-plus-lg"></i> {% else %}
Ajouter <span class="h2 d-none d-sm-inline">Sympathisants</span>
</a> {% endif %}
<a </div>
class="btn btn-outline-primary" <div class="col-sm-6 text-end">
href="/members/export?s={{ SearchJSON|urlencode }}" {% if MembersPage %}
> <div class="btn-group">
<i class="bi-filetype-csv"></i> <a class="btn btn-outline-primary" href="/members/add">
Exporter <i class="bi-plus-lg"></i>
</a> Ajouter
</div> </a>
{% else %} <a
<div class="btn-group"> class="btn btn-outline-primary"
<a class="btn btn-outline-primary" href="/contacts/add"> href="/members/export?s={{ SearchJSON|urlencode }}"
<i class="bi-plus-lg"></i> >
Ajouter <i class="bi-filetype-csv"></i>
</a> Exporter
<a </a>
class="btn btn-outline-primary" </div>
href="/contacts/export?s={{ SearchJSON|urlencode }}" {% else %}
> <div class="btn-group">
<i class="bi-filetype-csv"></i> <a class="btn btn-outline-primary" href="/contacts/add">
Exporter <i class="bi-plus-lg"></i>
</a> Ajouter
</div> </a>
{% endif %} <a
class="btn btn-outline-primary"
href="/contacts/export?s={{ SearchJSON|urlencode }}"
>
<i class="bi-filetype-csv"></i>
Exporter
</a>
</div>
{% endif %}
</div>
</div> </div>
<div <div id="search-container" class="h-100 p-4 mb-3 bg-body-tertiary border">
id="search-container"
class="h-100 p-4 mb-3 bg-body-tertiary border rounded-3"
>
<div class="row"> <div class="row">
<div class="col-lg-6 mb-3"> <div class="col-lg-6 mb-3">
<label for="name" class="form-label">Nom et prénom</label> <label for="name" class="form-label">Nom et prénom</label>
@ -83,11 +89,10 @@
</div> </div>
<div class="col-sm-6 col-lg-3 mb-3 pt-3"> <div class="col-sm-6 col-lg-3 mb-3 pt-3">
{% if PermShow %} {% if PermShow %}
<div class="form-check form-switch"> <div class="form-check">
<input <input
class="form-check-input" class="form-check-input"
type="checkbox" type="checkbox"
role="switch"
data-search-field="active" data-search-field="active"
data-search-advanced="false" data-search-advanced="false"
id="active" id="active"
@ -99,18 +104,17 @@
> >
{% else %} {% else %}
<label class="form-check-label" for="active" <label class="form-check-label" for="active"
>Afficher contacts actifs</label >Afficher sympathisants actifs</label
> >
{% endif %} {% endif %}
</div> </div>
{% endif %} {% endif %}
{% if PermShowArchived %} {% if PermShowArchived %}
<div class="form-check form-switch"> <div class="form-check">
<input <input
class="form-check-input" class="form-check-input"
type="checkbox" type="checkbox"
role="switch"
data-search-field="archive" data-search-field="archive"
data-search-advanced="false" data-search-advanced="false"
id="archive" id="archive"
@ -121,7 +125,7 @@
> >
{% else %} {% else %}
<label class="form-check-label" for="archive" <label class="form-check-label" for="archive"
>Afficher contacts archivés</label >Afficher sympathisants archivés</label
> >
{% endif %} {% endif %}
</div> </div>
@ -208,7 +212,7 @@
</div> </div>
<div class="row mt-2"> <div class="row mt-2">
<div class="col-6"> <div class="col-12 col-sm-8 col-md-6 d-grid d-sm-block">
<button <button
class="btn btn-outline-primary" class="btn btn-outline-primary"
id="advanced" id="advanced"
@ -225,7 +229,7 @@
<i class="bi-arrow-clockwise me-1"></i> Réinitialiser <i class="bi-arrow-clockwise me-1"></i> Réinitialiser
</button> </button>
</div> </div>
<div class="col-6 text-end"> <div class="col-12 col-sm-4 col-md-6 text-end d-grid d-sm-block">
<button class="btn btn-outline-success" id="search" type="button"> <button class="btn btn-outline-success" id="search" type="button">
<i class="bi-search me-1"></i> Recherche <i class="bi-search me-1"></i> Recherche
</button> </button>
@ -248,19 +252,146 @@
</form> </form>
</div> </div>
<div class="table-responsive"> <div>
<table class="table"> <div class="card card-body my-2 py-2 bg-body-tertiary">
<thead> <div class="row">
<tr> <div
<th class="w-25">Nom</th> class="col-xxl col-lg-4 col-md-6 order-1 order-md-1 order-lg-1 order-xxl-1"
<th class="w-50 d-none d-sm-table-cell">Adresse</th> >
<th class="w-25">Section</th> <div class="text-bold fs-7 mt-xxl-0 mt-2">
</tr> {% if OrderCol == "name" || OrderCol == "" %}
</thead> {% if OrderDir == "asc" || OrderDir == "" %}
<tbody> <a href="?p=1&s={{ SearchJSON|urlencode }}&c=name&o=desc">
{% for Person in People %} Nom <i class="bi-arrow-down"></i>
<tr> </a>
<td> {% else %}
<a href="?p=1&s={{ SearchJSON|urlencode }}&c=name&o=asc">
Nom <i class="bi-arrow-up"></i>
</a>
{% endif %}
{% else %}
<a href="?p=1&s={{ SearchJSON|urlencode }}&c=name&o=asc">
Nom
</a>
{% endif %}
</div>
</div>
<div
class="col-xxl col-lg-4 col-md-6 order-2 order-md-3 order-lg-2 order-xxl-2"
>
<div class="text-bold fs-7 mt-xxl-0 mt-2">
{% if OrderCol == "address" %}
{% if OrderDir == "asc" || OrderDir == "" %}
<a href="?p=1&s={{ SearchJSON|urlencode }}&c=address&o=desc">
Adresse <i class="bi-arrow-down"></i>
</a>
{% else %}
<a href="?p=1&s={{ SearchJSON|urlencode }}&c=address&o=asc">
Adresse <i class="bi-arrow-up"></i>
</a>
{% endif %}
{% else %}
<a href="?p=1&s={{ SearchJSON|urlencode }}&c=address&o=asc">
Adresse
</a>
{% endif %}
</div>
</div>
<div
class="col-xxl col-lg-4 col-md-6 order-3 order-md-5 order-lg-5 order-xxl-3"
>
<div class="text-bold fs-7 mt-xxl-0 mt-2">
{% if OrderCol == "npa" %}
{% if OrderDir == "asc" || OrderDir == "" %}
<a href="?p=1&s={{ SearchJSON|urlencode }}&c=npa&o=desc">
Lieu <i class="bi-arrow-down"></i>
</a>
{% else %}
<a href="?p=1&s={{ SearchJSON|urlencode }}&c=npa&o=asc">
Lieu <i class="bi-arrow-up"></i>
</a>
{% endif %}
{% else %}
<a href="?p=1&s={{ SearchJSON|urlencode }}&c=npa&o=asc">
Lieu
</a>
{% endif %}
</div>
</div>
<div
class="col-xxl col-lg-4 col-md-6 order-4 order-md-2 order-lg-4 order-xxl-4"
>
<div class="text-bold fs-7 mt-xxl-0 mt-2">
{% if OrderCol == "section" %}
{% if OrderDir == "asc" || OrderDir == "" %}
<a href="?p=1&s={{ SearchJSON|urlencode }}&c=section&o=desc">
Section <i class="bi-arrow-down"></i>
</a>
{% else %}
<a href="?p=1&s={{ SearchJSON|urlencode }}&c=section&o=asc">
Section <i class="bi-arrow-up"></i>
</a>
{% endif %}
{% else %}
<a href="?p=1&s={{ SearchJSON|urlencode }}&c=section&o=asc">
Section
</a>
{% endif %}
</div>
</div>
<div
class="col-xxl col-lg-4 col-md-6 order-5 order-md-3 order-lg-4 order-xxl-5"
>
<div class="text-bold fs-7 mt-xxl-0 mt-2">
{% if OrderCol == "created" %}
{% if OrderDir == "asc" || OrderDir == "" %}
<a href="?p=1&s={{ SearchJSON|urlencode }}&c=created&o=desc">
Création <i class="bi-arrow-down"></i>
</a>
{% else %}
<a href="?p=1&s={{ SearchJSON|urlencode }}&c=created&o=asc">
Création <i class="bi-arrow-up"></i>
</a>
{% endif %}
{% else %}
<a href="?p=1&s={{ SearchJSON|urlencode }}&c=created&o=asc">
Création
</a>
{% endif %}
</div>
</div>
<div
class="col-xxl col-lg-4 col-md-6 order-last order-md-last order-lg-last order-xxl-last"
>
<div class="text-bold fs-7 mt-xxl-0 mt-2">
{% if OrderCol == "updated" %}
{% if OrderDir == "asc" || OrderDir == "" %}
<a href="?p=1&s={{ SearchJSON|urlencode }}&c=updated&o=desc">
Modification <i class="bi-arrow-down"></i>
</a>
{% else %}
<a href="?p=1&s={{ SearchJSON|urlencode }}&c=updated&o=asc">
Modification <i class="bi-arrow-up"></i>
</a>
{% endif %}
{% else %}
<a href="?p=1&s={{ SearchJSON|urlencode }}&c=updated&o=asc">
Modification
</a>
{% endif %}
</div>
</div>
</div>
</div>
{% for Person in People %}
<div class="card card-body my-2 py-2 bg-body-tertiary">
<div class="row">
<div
class="col-xxl col-lg-4 col-md-6 order-1 order-md-1 order-lg-1 order-xxl-1"
>
<div class="text-bold fs-7 mt-xxl-0 mt-2">Nom</div>
<div>
{% if Person.IsMember %} {% if Person.IsMember %}
<a href="/members/{{ Person.ID }}"> <a href="/members/{{ Person.ID }}">
{{ Person.LastName }} {{ Person.FirstName }} {{ Person.LastName }} {{ Person.FirstName }}
@ -270,24 +401,53 @@
{{ Person.LastName }} {{ Person.FirstName }} {{ Person.LastName }} {{ Person.FirstName }}
</a> </a>
{% endif %} {% endif %}
</td> </div>
<td class="d-none d-sm-table-cell"> </div>
{{ Person.Address1 }} <div
{% if Person.Address1 and (Person.PostalCode or Person.City) %} class="col-xxl col-lg-4 col-md-6 order-2 order-md-3 order-lg-2 order-xxl-2"
&ndash; >
<div class="text-bold fs-7 mt-xxl-0 mt-2">Adresse</div>
<div>{{ Person.Address1 }}</div>
</div>
<div
class="col-xxl col-lg-4 col-md-6 order-3 order-md-5 order-lg-5 order-xxl-3"
>
<div class="text-bold fs-7 mt-xxl-0 mt-2">Lieu</div>
<div>{{ Person.PostalCode }} {{ Person.City }}</div>
</div>
<div
class="col-xxl col-lg-4 col-md-6 order-4 order-md-2 order-lg-4 order-xxl-4"
>
<div class="text-bold fs-7 mt-xxl-0 mt-2">Section</div>
<div>{{ Person.Section.Name }}</div>
</div>
<div
class="col-xxl col-lg-4 col-md-6 order-5 order-md-3 order-lg-4 order-xxl-5"
>
<div class="text-bold fs-7 mt-xxl-0 mt-2">Création</div>
<div>
{% if Person.CreatedAt|date:"2006-01-02" == "1970-01-01" %}
<code>Inconnu</code>
{% else %}
<code>{{ Person.CreatedAt|date:"02.01.2006 15:04" }}</code>
{% endif %} {% endif %}
{{ Person.PostalCode }} </div>
{{ Person.City }} </div>
</td> <div
<td> class="col-xxl col-lg-4 col-md-6 order-last order-md-last order-lg-last order-xxl-last"
{% if Person.SectionID %} >
{{ Person.Section.Name }} <div class="text-bold fs-7 mt-xxl-0 mt-2">Modification</div>
<div>
{% if Person.UpdatedAt|date:"2006-01-02" == "1970-01-01" %}
<code>Inconnu</code>
{% else %}
<code>{{ Person.UpdatedAt|date:"02.01.2006 15:04" }}</code>
{% endif %} {% endif %}
</td> </div>
</tr> </div>
{% endfor %} </div>
</tbody> </div>
</table> {% endfor %}
</div> </div>
<nav class="mt-3 mb-5"> <nav class="mt-3 mb-5">
@ -305,14 +465,17 @@
</li> </li>
{% else %} {% else %}
<li class="page-item"> <li class="page-item">
<a class="page-link" href="?p=1&s={{ SearchJSON|urlencode }}"> <a
class="page-link"
href="?p=1&s={{ SearchJSON|urlencode }}&c={{ OrderCol }}&o={{ OrderDir }}"
>
<i class="bi-rewind"></i> <i class="bi-rewind"></i>
</a> </a>
</li> </li>
<li class="page-item"> <li class="page-item">
<a <a
class="page-link" class="page-link"
href="?&p={{ Pagination.CurrentPage - 1 }}&s={{ SearchJSON|urlencode }}" href="?&p={{ Pagination.CurrentPage - 1 }}&s={{ SearchJSON|urlencode }}&c={{ OrderCol }}&o={{ OrderDir }}"
> >
<i class="bi-caret-left"></i> <i class="bi-caret-left"></i>
</a> </a>
@ -327,7 +490,7 @@
{% else %} {% else %}
class="page-link" class="page-link"
{% endif %} {% endif %}
href="?&p={{ i }}&s={{ SearchJSON|urlencode }}" href="?&p={{ i }}&s={{ SearchJSON|urlencode }}&c={{ OrderCol }}&o={{ OrderDir }}"
> >
{{ i }} {{ i }}
</a> </a>
@ -349,7 +512,7 @@
<li class="page-item"> <li class="page-item">
<a <a
class="page-link" class="page-link"
href="?&p={{ Pagination.CurrentPage + 1 }}&s={{ SearchJSON|urlencode }}" href="?&p={{ Pagination.CurrentPage + 1 }}&s={{ SearchJSON|urlencode }}&c={{ OrderCol }}&o={{ OrderDir }}"
> >
<i class="bi-caret-right"></i> <i class="bi-caret-right"></i>
</a> </a>
@ -357,7 +520,7 @@
<li class="page-item"> <li class="page-item">
<a <a
class="page-link" class="page-link"
href="?p={{ Pagination.MaxPages }}&s={{ SearchJSON|urlencode }}" href="?p={{ Pagination.MaxPages }}&s={{ SearchJSON|urlencode }}&c={{ OrderCol }}&o={{ OrderDir }}"
> >
<i class="bi-fast-forward"></i> <i class="bi-fast-forward"></i>
</a> </a>

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container mt-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -10,7 +10,9 @@
{% if Person.IsMember %} {% if Person.IsMember %}
<li class="breadcrumb-item"><a href="/members">Membres</a></li> <li class="breadcrumb-item"><a href="/members">Membres</a></li>
{% else %} {% else %}
<li class="breadcrumb-item"><a href="/contacts">Contacts</a></li> <li class="breadcrumb-item">
<a href="/contacts">Sympathisants</a>
</li>
{% endif %} {% endif %}
<li class="breadcrumb-item active"> <li class="breadcrumb-item active">
@ -21,375 +23,378 @@
<hr /> <hr />
</div> </div>
<div class="row mb-3"> <div class="mw-1200">
<div class="col-md-2">Nom de famille</div> <div class="row align-items-center mb-3">
<div class="col-md-10"> <div class="col-md-2 col-xl-3">Nom de famille</div>
<input <div class="col">
type="text" <input
class="form-control" type="text"
value="{{ Person.LastName }}" class="form-control"
disabled value="{{ Person.LastName }}"
readonly disabled
/> readonly
</div> />
</div>
<div class="row mb-3">
<div class="col-md-2">Prénom</div>
<div class="col-md-10">
<input
type="text"
class="form-control"
value="{{ Person.FirstName }}"
disabled
readonly
/>
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Email</div>
<div class="col-md-10">
<input
type="text"
class="form-control"
value="{{ Person.Email }}"
disabled
readonly
/>
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Téléphone fixe</div>
<div class="col-md-10">
<input
type="text"
class="form-control"
value="{{ Person.Phone }}"
disabled
readonly
/>
</div>
</div>
<div class="row mb-5">
<div class="col-md-2">Téléphone mobile</div>
<div class="col-md-10">
<input
type="text"
class="form-control"
value="{{ Person.Mobile }}"
disabled
readonly
/>
</div>
</div>
<div class="row mb-2">
<div class="col-md-2">Adresse</div>
<div class="col-md-10">
<input
type="text"
class="form-control"
value="{{ Person.Address1 }}"
disabled
readonly
/>
</div>
</div>
<div class="row mb-2">
<div class="col-md-10 offset-md-2">
<input
type="text"
class="form-control"
value="{{ Person.Address2 }}"
disabled
readonly
/>
</div>
</div>
<div class="row mb-5">
<div class="col-md-3 col-lg-2 offset-md-2 mb-2 mb-md-0">
<input
type="text"
class="form-control"
value="{{ Person.PostalCode }}"
disabled
readonly
/>
</div>
<div class="col-md-7 col-lg-8">
<input
type="text"
class="form-control"
value="{{ Person.City }}"
disabled
readonly
/>
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Section</div>
<div class="col-md-10">
<input
type="text"
class="form-control"
value="{{ Person.Section.Name }}"
disabled
readonly
/>
</div>
</div>
{% if Fields %}
<div class="mt-4 mb-3">
<span class="h4"> Champs supplémentaires </span>
</div>
{% endif %}
{% for Field in Fields %}
<div class="row mb-3">
<div class="col-md-2">{{ Field.Name }}</div>
<div class="col-md-10">
{% if Field.FieldType == "text" %}
<input
type="text"
class="form-control"
disabled
readonly
{% for FieldValue in FieldValues %}
{% if FieldValue.FieldID == Field.ID %}
value="{{ FieldValue.ValueString.String }}"
{% endif %}
{% endfor %}
/>
{% endif %}
{% if Field.FieldType == "longtext" %}
<textarea
type="text"
class="form-control"
disabled
readonly
rows="4"
>
{% for FieldValue in FieldValues %}{% if FieldValue.FieldID == Field.ID %}{{ FieldValue.ValueString.String }}{% endif %}{% endfor %}</textarea
>
{% endif %}
{% if Field.FieldType == "number" %}
<input
type="text"
class="form-control"
disabled
readonly
{% for FieldValue in FieldValues %}
{% if FieldValue.FieldID == Field.ID %}
value="{{ FieldValue.ValueInt.Int64 }}"
{% endif %}
{% endfor %}
/>
{% endif %}
{% if Field.FieldType == "date" %}
<input
type="text"
class="form-control"
disabled
readonly
{% for FieldValue in FieldValues %}
{% if FieldValue.FieldID == Field.ID %}
value="{{ FieldValue.ValueDate.Time|date:"02.01.2006" }}"
{% endif %}
{% endfor %}
/>
{% endif %}
{% if Field.FieldType == "list" and Field.List.Multi %}
{% set count = 1 %}
{% for FieldValue in FieldValues %}
{% if FieldValue.FieldID == Field.ID %}
{% if FieldValue.FieldID == Field.ID %}
<div class="mb-1">
<input
type="checkbox"
class="form-check-input me-2"
checked
disabled
/>
<label class="form-label"
>{{ FieldValue.ListItem.Value }}</label
>
</div>
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% if Field.FieldType == "list" and !Field.List.Multi %}
<input
type="text"
class="form-control"
disabled
readonly
{% for FieldValue in FieldValues %}
{% if FieldValue.FieldID == Field.ID %}
value="{{ FieldValue.ListItem.Value }}"
{% endif %}
{% endfor %}
/>
{% endif %}
</div> </div>
</div> </div>
{% endfor %}
<div class="my-5"> <div class="row align-items-center mb-3">
{% if Person.IsMember %} <div class="col-md-2 col-xl-3">Prénom</div>
<div class="row"> <div class="col">
<div class="col-md-6"> <input
{% if !Person.DeletedAt.Valid %} type="text"
class="form-control"
{% if PermEdit %} value="{{ Person.FirstName }}"
<a disabled
class="btn btn-outline-primary" readonly
href="/members/{{ Person.ID }}/edit" />
>
<i class="bi-pencil-square"></i>
Modifier
</a>
{% endif %}
{% if PermConvert %}
<button
class="btn btn-outline-secondary"
type="button"
data-bs-toggle="modal"
data-bs-target="#modal-convert"
>
<i class="bi-arrow-repeat"></i>
Convertir en contact
</button>
{% endif %}
{% endif %}
</div>
<div class="col-md-6 text-md-end mt-2 mt-md-0">
{% if Person.DeletedAt.Valid %}
{% if PermRestore %}
<button
class="btn btn-outline-secondary"
type="button"
data-bs-toggle="modal"
data-bs-target="#modal-restore"
>
<i class="bi-person-check"></i>
Restaurer
</button>
{% endif %}
{% else %}
{% if PermArchive %}
<button
class="btn btn-outline-secondary"
type="button"
data-bs-toggle="modal"
data-bs-target="#modal-archive"
>
<i class="bi-person-slash"></i>
Archiver
</button>
{% endif %}
{% endif %}
{% if PermPurge %}
<button
class="btn btn-outline-danger"
type="button"
data-bs-toggle="modal"
data-bs-target="#modal-delete"
>
<i class="bi-trash3"></i>
Supprimer
</button>
{% endif %}
</div>
</div> </div>
{% else %} </div>
<div class="row">
<div class="col-md-6">
{% if !Person.DeletedAt.Valid %}
{% if PermEdit %} <div class="row align-items-center mb-3">
<a <div class="col-md-2 col-xl-3">Email</div>
class="btn btn-outline-primary" <div class="col">
href="/contacts/{{ Person.ID }}/edit" <input
> type="text"
<i class="bi-pencil-square"></i> class="form-control"
Modifier value="{{ Person.Email }}"
</a> disabled
{% endif %} readonly
/>
</div>
</div>
{% if PermConvert %} <div class="row align-items-center mb-3">
<button <div class="col-md-2 col-xl-3">Téléphone fixe</div>
class="btn btn-outline-secondary" <div class="col">
type="button" <input
data-bs-toggle="modal" type="text"
data-bs-target="#modal-convert" class="form-control"
> value="{{ Person.Phone }}"
<i class="bi-arrow-repeat"></i> disabled
Convertir en membre readonly
</button> />
{% endif %} </div>
{% endif %} </div>
</div>
<div class="col-md-6 text-md-end mt-2 mt-md-0">
{% if Person.DeletedAt.Valid %}
{% if PermRestore %} <div class="row align-items-center mb-5">
<button <div class="col-md-2 col-xl-3">Téléphone mobile</div>
class="btn btn-outline-secondary" <div class="col">
type="button" <input
data-bs-toggle="modal" type="text"
data-bs-target="#modal-restore" class="form-control"
> value="{{ Person.Mobile }}"
<i class="bi-person-check"></i> disabled
Restaurer readonly
</button> />
{% endif %} </div>
{% else %} </div>
{% if PermArchive %} <div class="row align-items-center mb-2">
<button <div class="col-md-2 col-xl-3">Adresse</div>
class="btn btn-outline-secondary" <div class="col">
type="button" <input
data-bs-toggle="modal" type="text"
data-bs-target="#modal-archive" class="form-control"
> value="{{ Person.Address1 }}"
<i class="bi-person-slash"></i> disabled
Archiver readonly
</button> />
{% endif %} </div>
{% endif %} </div>
{% if PermPurge %} <div class="row align-items-center mb-2">
<button <div class="col offset-md-2 offset-xl-3">
class="btn btn-outline-danger" <input
type="button" type="text"
data-bs-toggle="modal" class="form-control"
data-bs-target="#modal-delete" value="{{ Person.Address2 }}"
> disabled
<i class="bi-trash3"></i> readonly
Supprimer />
</button> </div>
{% endif %} </div>
</div>
<div class="row align-items-center mb-5">
<div class="col-md-3 col-lg-2 offset-md-2 offset-xl-3 mb-2 mb-md-0">
<input
type="text"
class="form-control"
value="{{ Person.PostalCode }}"
disabled
readonly
/>
</div>
<div class="col">
<input
type="text"
class="form-control"
value="{{ Person.City }}"
disabled
readonly
/>
</div>
</div>
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">Section</div>
<div class="col">
<input
type="text"
class="form-control"
value="{{ Person.Section.Name }}"
disabled
readonly
/>
</div>
</div>
{% if Fields %}
<div class="mt-4 mb-3">
<span class="h4"> Champs supplémentaires </span>
</div> </div>
{% endif %} {% endif %}
{% for Field in Fields %}
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">{{ Field.Name }}</div>
<div class="col">
{% if Field.FieldType == "text" %}
<input
type="text"
class="form-control"
disabled
readonly
{% for FieldValue in FieldValues %}
{% if FieldValue.FieldID == Field.ID %}
value="{{ FieldValue.ValueString.String }}"
{% endif %}
{% endfor %}
/>
{% endif %}
{% if Field.FieldType == "longtext" %}
<textarea
type="text"
class="form-control"
disabled
readonly
row
align-items-centers="4"
>
{% for FieldValue in FieldValues %}{% if FieldValue.FieldID == Field.ID %}{{ FieldValue.ValueString.String }}{% endif %}{% endfor %}</textarea
>
{% endif %}
{% if Field.FieldType == "number" %}
<input
type="text"
class="form-control"
disabled
readonly
{% for FieldValue in FieldValues %}
{% if FieldValue.FieldID == Field.ID %}
value="{{ FieldValue.ValueInt.Int64 }}"
{% endif %}
{% endfor %}
/>
{% endif %}
{% if Field.FieldType == "date" %}
<input
type="text"
class="form-control"
disabled
readonly
{% for FieldValue in FieldValues %}
{% if FieldValue.FieldID == Field.ID %}
value="{{ FieldValue.ValueDate.Time|date:"02.01.2006" }}"
{% endif %}
{% endfor %}
/>
{% endif %}
{% if Field.FieldType == "list" and Field.List.Multi %}
{% set count = 1 %}
{% for FieldValue in FieldValues %}
{% if FieldValue.FieldID == Field.ID %}
{% if FieldValue.FieldID == Field.ID %}
<div class="mb-1">
<input
type="checkbox"
class="form-check-input me-2"
checked
disabled
/>
<label class="form-label"
>{{ FieldValue.ListItem.Value }}</label
>
</div>
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% if Field.FieldType == "list" and !Field.List.Multi %}
<input
type="text"
class="form-control"
disabled
readonly
{% for FieldValue in FieldValues %}
{% if FieldValue.FieldID == Field.ID %}
value="{{ FieldValue.ListItem.Value }}"
{% endif %}
{% endfor %}
/>
{% endif %}
</div>
</div>
{% endfor %}
<div class="my-5">
{% if Person.IsMember %}
<div class="row align-items-center">
<div class="col-md-6">
{% if !Person.DeletedAt.Valid %}
{% if PermEdit %}
<a
class="btn btn-outline-primary"
href="/members/{{ Person.ID }}/edit"
>
<i class="bi-pencil-square"></i>
Modifier
</a>
{% endif %}
{% if PermConvert %}
<button
class="btn btn-outline-primary"
type="button"
data-bs-toggle="modal"
data-bs-target="#modal-convert"
>
<i class="bi-arrow-repeat align-items-center-repeat"></i>
Convertir en sympathisant
</button>
{% endif %}
{% endif %}
</div>
<div class="col-md-6 text-md-end mt-2 mt-md-0">
{% if Person.DeletedAt.Valid %}
{% if PermRestore %}
<button
class="btn btn-outline-primary"
type="button"
data-bs-toggle="modal"
data-bs-target="#modal-restore"
>
<i class="bi-person-check"></i>
Restaurer
</button>
{% endif %}
{% else %}
{% if PermArchive %}
<button
class="btn btn-outline-primary"
type="button"
data-bs-toggle="modal"
data-bs-target="#modal-archive"
>
<i class="bi-person-slash"></i>
Archiver
</button>
{% endif %}
{% endif %}
{% if PermPurge %}
<button
class="btn btn-outline-danger"
type="button"
data-bs-toggle="modal"
data-bs-target="#modal-delete"
>
<i class="bi-trash3"></i>
Supprimer
</button>
{% endif %}
</div>
</div>
{% else %}
<div class="row align-items-center">
<div class="col-md-6">
{% if !Person.DeletedAt.Valid %}
{% if PermEdit %}
<a
class="btn btn-outline-primary"
href="/contacts/{{ Person.ID }}/edit"
>
<i class="bi-pencil-square"></i>
Modifier
</a>
{% endif %}
{% if PermConvert %}
<button
class="btn btn-outline-primary"
type="button"
data-bs-toggle="modal"
data-bs-target="#modal-convert"
>
<i class="bi-arrow-repeat align-items-center-repeat"></i>
Convertir en membre
</button>
{% endif %}
{% endif %}
</div>
<div class="col-md-6 text-md-end mt-2 mt-md-0">
{% if Person.DeletedAt.Valid %}
{% if PermRestore %}
<button
class="btn btn-outline-primary"
type="button"
data-bs-toggle="modal"
data-bs-target="#modal-restore"
>
<i class="bi-person-check"></i>
Restaurer
</button>
{% endif %}
{% else %}
{% if PermArchive %}
<button
class="btn btn-outline-primary"
type="button"
data-bs-toggle="modal"
data-bs-target="#modal-archive"
>
<i class="bi-person-slash"></i>
Archiver
</button>
{% endif %}
{% endif %}
{% if PermPurge %}
<button
class="btn btn-outline-danger"
type="button"
data-bs-toggle="modal"
data-bs-target="#modal-delete"
>
<i class="bi-trash3"></i>
Supprimer
</button>
{% endif %}
</div>
</div>
{% endif %}
</div>
</div> </div>
</div> </div>
@ -400,7 +405,7 @@
{% if Person.IsMember %} {% if Person.IsMember %}
<p>Êtes-vous sûr de vouloir supprimer ce membre ?</p> <p>Êtes-vous sûr de vouloir supprimer ce membre ?</p>
{% else %} {% else %}
<p>Êtes-vous sûr de vouloir supprimer ce contact ?</p> <p>Êtes-vous sûr de vouloir supprimer ce sympathisant ?</p>
{% endif %} {% endif %}
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
@ -448,7 +453,7 @@
{% if Person.IsMember %} {% if Person.IsMember %}
<p>Êtes-vous sûr de vouloir archiver ce membre ?</p> <p>Êtes-vous sûr de vouloir archiver ce membre ?</p>
{% else %} {% else %}
<p>Êtes-vous sûr de vouloir archiver ce contact ?</p> <p>Êtes-vous sûr de vouloir archiver ce sympathisant ?</p>
{% endif %} {% endif %}
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
@ -496,7 +501,7 @@
{% if Person.IsMember %} {% if Person.IsMember %}
<p>Êtes-vous sûr de vouloir restaurer ce membre ?</p> <p>Êtes-vous sûr de vouloir restaurer ce membre ?</p>
{% else %} {% else %}
<p>Êtes-vous sûr de vouloir restaurer ce contact ?</p> <p>Êtes-vous sûr de vouloir restaurer ce sympathisant ?</p>
{% endif %} {% endif %}
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
@ -542,9 +547,13 @@
<div class="modal-content"> <div class="modal-content">
<div class="modal-body"> <div class="modal-body">
{% if Person.IsMember %} {% if Person.IsMember %}
<p>Êtes-vous sûr de vouloir convertir ce membre en contact ?</p> <p>
Êtes-vous sûr de vouloir convertir ce membre en sympathisant ?
</p>
{% else %} {% else %}
<p>Êtes-vous sûr de vouloir convertir ce contact en membre ?</p> <p>
Êtes-vous sûr de vouloir convertir ce sympathisant en membre ?
</p>
{% endif %} {% endif %}
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
@ -564,7 +573,7 @@
class="d-inline p-0" class="d-inline p-0"
> >
<button class="btn btn-outline-primary" type="submit"> <button class="btn btn-outline-primary" type="submit">
<i class="bi-arrow-repeat"></i> <i class="bi-arrow align-items-center-repeat"></i>
Convertir Convertir
</button> </button>
</form> </form>
@ -575,7 +584,7 @@
class="d-inline p-0" class="d-inline p-0"
> >
<button class="btn btn-outline-primary" type="submit"> <button class="btn btn-outline-primary" type="submit">
<i class="bi-arrow-repeat"></i> <i class="bi-arrow align-items-center-repeat"></i>
Convertir Convertir
</button> </button>
</form> </form>

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container mt-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -10,7 +10,9 @@
{% if Person.IsMember or MembersPage %} {% if Person.IsMember or MembersPage %}
<li class="breadcrumb-item"><a href="/members">Membres</a></li> <li class="breadcrumb-item"><a href="/members">Membres</a></li>
{% else %} {% else %}
<li class="breadcrumb-item"><a href="/contacts">Contacts</a></li> <li class="breadcrumb-item">
<a href="/contacts">Sympathisants</a>
</li>
{% endif %} {% endif %}
{% if Person.ID %} {% if Person.ID %}
@ -37,22 +39,22 @@
<hr /> <hr />
</div> </div>
{% if Errors %} <form id="person" method="post" class="mw-1200">
<div class="alert alert-danger"> {% if Errors %}
<ul class="m-0"> <div class="alert alert-danger">
{% for Error in Errors %} <ul class="m-0">
<li>{{ Error }}</li> {% for Error in Errors %}
{% endfor %} <li>{{ Error }}</li>
</ul> {% endfor %}
</div> </ul>
{% endif %} </div>
{% endif %}
<form id="person" method="post"> <div class="row align-items-center mb-3">
<div class="row mb-3"> <label for="last_name" class="form-label col-md-2 col-xl-3">
<label for="last_name" class="form-label col-md-2">
Nom de famille Nom de famille
</label> </label>
<div class="col-md-10"> <div class="col">
<input <input
id="name" id="name"
class="form-control" class="form-control"
@ -65,9 +67,11 @@
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<label for="first_name" class="form-label col-md-2"> Prénom </label> <label for="first_name" class="form-label col-md-2 col-xl-3">
<div class="col-md-10"> Prénom
</label>
<div class="col">
<input <input
id="first_name" id="first_name"
class="form-control" class="form-control"
@ -80,9 +84,9 @@
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<label for="email" class="form-label col-md-2"> Email </label> <label for="email" class="form-label col-md-2 col-xl-3"> Email </label>
<div class="col-md-10"> <div class="col">
<input <input
id="email" id="email"
class="form-control" class="form-control"
@ -94,9 +98,11 @@
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<label for="phone" class="form-label col-md-2"> Téléphone fixe </label> <label for="phone" class="form-label col-md-2 col-xl-3">
<div class="col-md-10"> Téléphone fixe
</label>
<div class="col">
<input <input
id="phone" id="phone"
class="form-control" class="form-control"
@ -108,11 +114,11 @@
</div> </div>
</div> </div>
<div class="row mb-5"> <div class="row align-items-center mb-5">
<label for="mobile" class="form-label col-md-2"> <label for="mobile" class="form-label col-md-2 col-xl-3">
Téléphone mobile Téléphone mobile
</label> </label>
<div class="col-md-10"> <div class="col">
<input <input
id="mobile" id="mobile"
class="form-control" class="form-control"
@ -124,9 +130,11 @@
</div> </div>
</div> </div>
<div class="row mb-2"> <div class="row align-items-center mb-2">
<label for="address1" class="form-label col-md-2"> Adresse </label> <label for="address1" class="form-label col-md-2 col-xl-3">
<div class="col-md-10"> Adresse
</label>
<div class="col">
<input <input
id="address1" id="address1"
class="form-control" class="form-control"
@ -139,8 +147,8 @@
</div> </div>
</div> </div>
<div class="row mb-2"> <div class="row align-items-center mb-2">
<div class="col-md-10 offset-md-2"> <div class="col offset-md-2 offset-xl-3">
<input <input
id="address2" id="address2"
class="form-control" class="form-control"
@ -153,8 +161,8 @@
</div> </div>
</div> </div>
<div class="row mb-5"> <div class="row align-items-center mb-5">
<div class="col-md-3 col-lg-2 offset-md-2 mb-2 mb-md-0"> <div class="col-md-3 col-lg-2 offset-md-2 offset-xl-3 mb-2 mb-md-0">
<input <input
id="postal_code" id="postal_code"
class="form-control" class="form-control"
@ -166,7 +174,7 @@
autocomplete="off" autocomplete="off"
/> />
</div> </div>
<div class="col-md-7 col-lg-8"> <div class="col">
<input <input
id="city" id="city"
class="form-control" class="form-control"
@ -179,9 +187,11 @@
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<label for="section" class="form-label col-md-2"> Section </label> <label for="section" class="form-label col-md-2 col-xl-3">
<div class="col-md-10"> Section
</label>
<div class="col">
<select <select
class="form-select" class="form-select"
name="section" name="section"
@ -210,11 +220,14 @@
{% endif %} {% endif %}
{% for Field in Fields %} {% for Field in Fields %}
<div class="row mb-3"> <div class="row align-items-center mb-3">
<label for="field-{{ Field.ID }}" class="form-label col-md-2"> <label
for="field-{{ Field.ID }}"
class="form-label col-md-2 col-xl-3"
>
{{ Field.Name }} {{ Field.Name }}
</label> </label>
<div class="col-md-10"> <div class="col">
{% if Field.FieldType == "text" %} {% if Field.FieldType == "text" %}
<input <input
id="field-{{ Field.ID }}" id="field-{{ Field.ID }}"
@ -235,7 +248,8 @@
id="field-{{ Field.ID }}" id="field-{{ Field.ID }}"
class="form-control" class="form-control"
name="field-{{ Field.ID }}" name="field-{{ Field.ID }}"
rows="4" row
align-items-centers="4"
autocomplete="off" autocomplete="off"
> >
{% for FieldValue in FieldValues %}{% if FieldValue.FieldID == Field.ID %}{{ FieldValue.ValueString.String }}{% endif %}{% endfor %}</textarea {% for FieldValue in FieldValues %}{% if FieldValue.FieldID == Field.ID %}{{ FieldValue.ValueString.String }}{% endif %}{% endfor %}</textarea

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container mt-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -14,383 +14,555 @@
<hr /> <hr />
</div> </div>
<div class="row mb-3"> <div class="mw-1200">
<div class="col-md-2">Nom</div> <div class="row align-items-center mb-4">
<div class="col-md-10"> <div class="col-md-2 col-xl-3">Nom</div>
<input <div class="col">
type="text" <input
class="form-control" type="text"
value="{{ Role.Name }}" class="form-control"
disabled value="{{ Role.Name }}"
readonly disabled
/> readonly
/>
</div>
</div> </div>
</div>
<div class="mt-4 mb-3"> <div class="card mb-4">
<span class="h4"> Permissions membres </span> <div class="card-header">Permissions membres</div>
</div> <div class="card-body">
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">Afficher membres</div>
<div class="col">
{% if Role.ShowMember %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input
type="text"
class="form-control"
value="Oui"
disabled
/>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input
type="text"
class="form-control"
value="Non"
disabled
/>
</div>
{% endif %}
</div>
</div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<div class="col-md-2">Afficher membres</div> <div class="col-md-2 col-xl-3">Créer membres</div>
<div class="col-md-10"> <div class="col">
{% if Role.ShowMember %} {% if Role.CreateMember %}
<div class="input-group"> <div class="input-group">
<span class="input-group-text"> <span class="input-group-text">
<i class="bi-check-lg text-success"></i> <i class="bi-check-lg text-success"></i>
</span> </span>
<input type="text" class="form-control" value="Oui" disabled /> <input
type="text"
class="form-control"
value="Oui"
disabled
/>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input
type="text"
class="form-control"
value="Non"
disabled
/>
</div>
{% endif %}
</div>
</div> </div>
{% else %}
<div class="input-group"> <div class="row align-items-center mb-3">
<span class="input-group-text"> <div class="col-md-2 col-xl-3">Modifier membres</div>
<i class="bi-x-lg text-danger"></i> <div class="col">
</span> {% if Role.EditMember %}
<input type="text" class="form-control" value="Non" disabled /> <div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input
type="text"
class="form-control"
value="Oui"
disabled
/>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input
type="text"
class="form-control"
value="Non"
disabled
/>
</div>
{% endif %}
</div>
</div> </div>
{% endif %}
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">Afficher membres archivés</div>
<div class="col">
{% if Role.ShowArchivedMember %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input
type="text"
class="form-control"
value="Oui"
disabled
/>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input
type="text"
class="form-control"
value="Non"
disabled
/>
</div>
{% endif %}
</div>
</div>
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">Archiver membres</div>
<div class="col">
{% if Role.ArchiveMember %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input
type="text"
class="form-control"
value="Oui"
disabled
/>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input
type="text"
class="form-control"
value="Non"
disabled
/>
</div>
{% endif %}
</div>
</div>
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">Restaurer membres</div>
<div class="col">
{% if Role.RestoreMember %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input
type="text"
class="form-control"
value="Oui"
disabled
/>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input
type="text"
class="form-control"
value="Non"
disabled
/>
</div>
{% endif %}
</div>
</div>
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">
Purger membres (suppression définitive)
</div>
<div class="col">
{% if Role.PurgeMember %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input
type="text"
class="form-control"
value="Oui"
disabled
/>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input
type="text"
class="form-control"
value="Non"
disabled
/>
</div>
{% endif %}
</div>
</div>
<div class="row align-items-center">
<div class="col-md-2 col-xl-3">
Convertir membres en sympathisants
</div>
<div class="col">
{% if Role.ConvertMemberToContact %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input
type="text"
class="form-control"
value="Oui"
disabled
/>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input
type="text"
class="form-control"
value="Non"
disabled
/>
</div>
{% endif %}
</div>
</div>
</div>
</div> </div>
</div>
<div class="row mb-3"> <div class="card">
<div class="col-md-2">Créer membres</div> <div class="card-header">Permissions sympathisants</div>
<div class="col-md-10"> <div class="card-body">
{% if Role.CreateMember %} <div class="row align-items-center mb-3">
<div class="input-group"> <div class="col-md-2 col-xl-3">Afficher sympathisants</div>
<span class="input-group-text"> <div class="col">
<i class="bi-check-lg text-success"></i> {% if Role.ShowContact %}
</span> <div class="input-group">
<input type="text" class="form-control" value="Oui" disabled /> <span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input
type="text"
class="form-control"
value="Oui"
disabled
/>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input
type="text"
class="form-control"
value="Non"
disabled
/>
</div>
{% endif %}
</div>
</div> </div>
{% else %}
<div class="input-group"> <div class="row align-items-center mb-3">
<span class="input-group-text"> <div class="col-md-2 col-xl-3">Créer sympathisants</div>
<i class="bi-x-lg text-danger"></i> <div class="col">
</span> {% if Role.CreateContact %}
<input type="text" class="form-control" value="Non" disabled /> <div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input
type="text"
class="form-control"
value="Oui"
disabled
/>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input
type="text"
class="form-control"
value="Non"
disabled
/>
</div>
{% endif %}
</div>
</div> </div>
{% endif %}
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">Modifier sympathisants</div>
<div class="col">
{% if Role.EditContact %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input
type="text"
class="form-control"
value="Oui"
disabled
/>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input
type="text"
class="form-control"
value="Non"
disabled
/>
</div>
{% endif %}
</div>
</div>
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">Afficher sympathisants archivés</div>
<div class="col">
{% if Role.ShowArchivedContact %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input
type="text"
class="form-control"
value="Oui"
disabled
/>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input
type="text"
class="form-control"
value="Non"
disabled
/>
</div>
{% endif %}
</div>
</div>
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">Archiver sympathisants</div>
<div class="col">
{% if Role.ArchiveContact %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input
type="text"
class="form-control"
value="Oui"
disabled
/>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input
type="text"
class="form-control"
value="Non"
disabled
/>
</div>
{% endif %}
</div>
</div>
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">Restaurer sympathisants</div>
<div class="col">
{% if Role.RestoreContact %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input
type="text"
class="form-control"
value="Oui"
disabled
/>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input
type="text"
class="form-control"
value="Non"
disabled
/>
</div>
{% endif %}
</div>
</div>
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">
Purger sympathisants (suppression définitive)
</div>
<div class="col">
{% if Role.PurgeContact %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input
type="text"
class="form-control"
value="Oui"
disabled
/>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input
type="text"
class="form-control"
value="Non"
disabled
/>
</div>
{% endif %}
</div>
</div>
<div class="row align-items-center">
<div class="col-md-2 col-xl-3">
Convertir sympathisants en membres
</div>
<div class="col">
{% if Role.ConvertContactToMember %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input
type="text"
class="form-control"
value="Oui"
disabled
/>
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input
type="text"
class="form-control"
value="Non"
disabled
/>
</div>
{% endif %}
</div>
</div>
</div>
</div> </div>
</div>
<div class="row mb-3"> <div class="my-4 row align-items-center">
<div class="col-md-2">Modifier membres</div> <div class="col-6">
<div class="col-md-10"> <a
{% if Role.EditMember %} class="btn btn-outline-primary"
<div class="input-group"> href="/admin/roles/{{ Role.ID }}/edit"
<span class="input-group-text"> >
<i class="bi-check-lg text-success"></i> <i class="bi-pencil-square"></i>
</span> Modifier
<input type="text" class="form-control" value="Oui" disabled /> </a>
</div> </div>
{% else %} <div class="col-6 text-end">
<div class="input-group"> <button
<span class="input-group-text"> type="button"
<i class="bi-x-lg text-danger"></i> class="btn btn-outline-danger"
</span> data-bs-toggle="modal"
<input type="text" class="form-control" value="Non" disabled /> data-bs-target="#modal-delete"
</div> >
{% endif %} <i class="bi-trash3 me-1"></i>
</div> Supprimer
</div> </button>
</div>
<div class="row mb-3">
<div class="col-md-2">Afficher membres archivés</div>
<div class="col-md-10">
{% if Role.ShowArchivedMember %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Archiver membres</div>
<div class="col-md-10">
{% if Role.ArchiveMember %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Restaurer membres</div>
<div class="col-md-10">
{% if Role.RestoreMember %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Purger membres (suppression définitive)</div>
<div class="col-md-10">
{% if Role.PurgeMember %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Convertir membres en contacts</div>
<div class="col-md-10">
{% if Role.ConvertMemberToContact %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="mt-4 mb-3">
<span class="h4"> Permissions contacts </span>
</div>
<div class="row mb-3">
<div class="col-md-2">Afficher contacts</div>
<div class="col-md-10">
{% if Role.ShowContact %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Créer contacts</div>
<div class="col-md-10">
{% if Role.CreateContact %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Modifier contacts</div>
<div class="col-md-10">
{% if Role.EditContact %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Afficher contacts archivés</div>
<div class="col-md-10">
{% if Role.ShowArchivedContact %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Archiver contacts</div>
<div class="col-md-10">
{% if Role.ArchiveContact %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Restaurer contacts</div>
<div class="col-md-10">
{% if Role.RestoreContact %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Purger contacts (suppression définitive)</div>
<div class="col-md-10">
{% if Role.PurgeContact %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Convertir contacts en membres</div>
<div class="col-md-10">
{% if Role.ConvertContactToMember %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="my-4 row">
<div class="col-6">
<a
class="btn btn-outline-primary"
href="/admin/roles/{{ Role.ID }}/edit"
>
<i class="bi-pencil-square"></i>
Modifier
</a>
</div>
<div class="col-6 text-end">
<button
type="button"
class="btn btn-outline-danger"
data-bs-toggle="modal"
data-bs-target="#modal-delete"
>
<i class="bi-trash3 me-1"></i>
Supprimer
</button>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container mt-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -22,18 +22,18 @@
<hr /> <hr />
</div> </div>
{% if Errors %} <form id="role" method="post" class="mw-1200">
<div class="alert alert-danger"> {% if Errors %}
<ul class="m-0"> <div class="alert alert-danger">
{% for Error in Errors %} <ul class="m-0">
<li>{{ Error }}</li> {% for Error in Errors %}
{% endfor %} <li>{{ Error }}</li>
</ul> {% endfor %}
</div> </ul>
{% endif %} </div>
{% endif %}
<form id="role" method="post"> <div class="row align-items-center mb-3">
<div class="row mb-3">
<label for="name" class="form-label col-md-2"> Nom </label> <label for="name" class="form-label col-md-2"> Nom </label>
<div class="col-md-10"> <div class="col-md-10">
<input <input
@ -49,267 +49,221 @@
</div> </div>
</div> </div>
<div class="mt-4 mb-3 d-md-none"> <div class="row mb-3">
<span class="h4"> Permissions membres </span> <div class="col-md-2">
<div class="mb-2">Permissions membres</div>
</div>
<div class="col-md-10">
<div class="mb-1">
<input
type="checkbox"
class="form-check-input me-2"
id="show_member"
name="show_member"
autocomplete="off"
{% if Role.ShowMember %}checked{% endif %}
/>
<label for="show_member" class="form-label"> Afficher </label>
</div>
<div class="mb-1">
<input
type="checkbox"
class="form-check-input me-2"
id="create_member"
name="create_member"
autocomplete="off"
{% if Role.CreateMember %}checked{% endif %}
/>
<label for="create_member" class="form-label"> Créer </label>
</div>
<div class="mb-1">
<input
type="checkbox"
class="form-check-input me-2"
id="edit_member"
name="edit_member"
autocomplete="off"
{% if Role.EditMember %}checked{% endif %}
/>
<label for="edit_member" class="form-label"> Modifier </label>
</div>
<div class="mb-1">
<input
type="checkbox"
class="form-check-input me-2"
id="show_archived_member"
name="show_archived_member"
autocomplete="off"
{% if Role.ShowArchivedMember %}checked{% endif %}
/>
<label for="show_archived_member" class="form-label">
Afficher archivés
</label>
</div>
<div class="mb-1">
<input
type="checkbox"
class="form-check-input me-2"
id="archive_member"
name="archive_member"
autocomplete="off"
{% if Role.ArchiveMember %}checked{% endif %}
/>
<label for="archive_member" class="form-label"> Archiver </label>
</div>
<div class="mb-1">
<input
type="checkbox"
class="form-check-input me-2"
id="restore_member"
name="restore_member"
autocomplete="off"
{% if Role.RestoreMember %}checked{% endif %}
/>
<label for="restore_member" class="form-label"> Restaurer </label>
</div>
<div class="mb-1">
<input
type="checkbox"
class="form-check-input me-2"
id="purge_member"
name="purge_member"
autocomplete="off"
{% if Role.PurgeMember %}checked{% endif %}
/>
<label for="purge_member" class="form-label">
Purger (suppression définitive)
</label>
</div>
<div class="mb-1">
<input
type="checkbox"
class="form-check-input me-2"
id="convert_member_to_contact"
name="convert_member_to_contact"
autocomplete="off"
{% if Role.ConvertMemberToContact %}checked{% endif %}
/>
<label for="convert_member_to_contact" class="form-label">
Convertir en sympathisants
</label>
</div>
</div>
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<div class="col-md-2"> <div class="col-md-2">
<div class="d-none d-md-block">Permissions membres</div> <div class="mb-2">Permissions sympathisants</div>
</div> </div>
<div class="col-md-10"> <div class="col-md-10">
<input <div class="mb-1">
type="checkbox" <input
class="form-check-input me-2" type="checkbox"
id="show_member" class="form-check-input me-2"
name="show_member" id="show_contact"
autocomplete="off" name="show_contact"
{% if Role.ShowMember %}checked{% endif %} autocomplete="off"
/> {% if Role.ShowContact %}checked{% endif %}
<label for="show_member" class="form-label"> Afficher membres </label> />
</div> <label for="show_contact" class="form-label"> Afficher </label>
</div> </div>
<div class="row mb-3"> <div class="mb-1">
<div class="col-md-10 offset-md-2"> <input
<input type="checkbox"
type="checkbox" class="form-check-input me-2"
class="form-check-input me-2" id="create_contact"
id="create_member" name="create_contact"
name="create_member" autocomplete="off"
autocomplete="off" {% if Role.CreateContact %}checked{% endif %}
{% if Role.CreateMember %}checked{% endif %} />
/> <label for="create_contact" class="form-label"> Créer </label>
<label for="create_member" class="form-label"> Créer membres </label> </div>
</div>
</div>
<div class="row mb-3"> <div class="mb-1">
<div class="col-md-10 offset-md-2"> <input
<input type="checkbox"
type="checkbox" class="form-check-input me-2"
class="form-check-input me-2" id="edit_contact"
id="edit_member" name="edit_contact"
name="edit_member" autocomplete="off"
autocomplete="off" {% if Role.EditContact %}checked{% endif %}
{% if Role.EditMember %}checked{% endif %} />
/> <label for="edit_contact" class="form-label"> Modifier </label>
<label for="edit_member" class="form-label"> Modifier membres </label> </div>
</div>
</div>
<div class="row mb-3"> <div class="mb-1">
<div class="col-md-10 offset-md-2"> <input
<input type="checkbox"
type="checkbox" class="form-check-input me-2"
class="form-check-input me-2" id="show_archived_contact"
id="show_archived_member" name="show_archived_contact"
name="show_archived_member" autocomplete="off"
autocomplete="off" {% if Role.ShowArchivedContact %}checked{% endif %}
{% if Role.ShowArchivedMember %}checked{% endif %} />
/> <label for="show_archived_contact" class="form-label">
<label for="show_archived_member" class="form-label"> Afficher archivés
Afficher membres archivés </label>
</label> </div>
</div>
</div>
<div class="row mb-3"> <div class="mb-1">
<div class="col-md-10 offset-md-2"> <input
<input type="checkbox"
type="checkbox" class="form-check-input me-2"
class="form-check-input me-2" id="archive_contact"
id="archive_member" name="archive_contact"
name="archive_member" autocomplete="off"
autocomplete="off" {% if Role.ArchiveContact %}checked{% endif %}
{% if Role.ArchiveMember %}checked{% endif %} />
/> <label for="archive_contact" class="form-label"> Archiver </label>
<label for="archive_member" class="form-label"> </div>
Archiver membres
</label>
</div>
</div>
<div class="row mb-3"> <div class="mb-1">
<div class="col-md-10 offset-md-2"> <input
<input type="checkbox"
type="checkbox" class="form-check-input me-2"
class="form-check-input me-2" id="restore_contact"
id="restore_member" name="restore_contact"
name="restore_member" autocomplete="off"
autocomplete="off" {% if Role.RestoreContact %}checked{% endif %}
{% if Role.RestoreMember %}checked{% endif %} />
/> <label for="restore_contact" class="form-label"> Restaurer </label>
<label for="restore_member" class="form-label"> </div>
Restaurer membres
</label>
</div>
</div>
<div class="row mb-3"> <div class="mb-1">
<div class="col-md-10 offset-md-2"> <input
<input type="checkbox"
type="checkbox" class="form-check-input me-2"
class="form-check-input me-2" id="purge_contact"
id="purge_member" name="purge_contact"
name="purge_member" autocomplete="off"
autocomplete="off" {% if Role.PurgeContact %}checked{% endif %}
{% if Role.PurgeMember %}checked{% endif %} />
/> <label for="purge_contact" class="form-label">
<label for="purge_member" class="form-label"> Purger (suppression définitive)
Purger membres (suppression définitive) </label>
</label> </div>
</div>
</div>
<div class="row mb-3"> <div class="mb-1">
<div class="col-md-10 offset-md-2"> <input
<input type="checkbox"
type="checkbox" class="form-check-input me-2"
class="form-check-input me-2" id="convert_contact_to_member"
id="convert_member_to_contact" name="convert_contact_to_member"
name="convert_member_to_contact" autocomplete="off"
autocomplete="off" {% if Role.ConvertContactToMember %}checked{% endif %}
{% if Role.ConvertMemberToContact %}checked{% endif %} />
/> <label for="convert_contact_to_member" class="form-label">
<label for="convert_member_to_contact" class="form-label"> Convertir en membres
Convertir membres en contacts </label>
</label> </div>
</div>
</div>
<div class="mt-4 mb-3 d-md-none">
<span class="h4"> Permissions contacts </span>
</div>
<div class="row mb-3">
<div class="col-md-2">
<div class="d-none d-md-block">Permissions contacts</div>
</div>
<div class="col-md-10">
<input
type="checkbox"
class="form-check-input me-2"
id="show_contact"
name="show_contact"
autocomplete="off"
{% if Role.ShowContact %}checked{% endif %}
/>
<label for="show_contact" class="form-label">
Afficher contacts
</label>
</div>
</div>
<div class="row mb-3">
<div class="col-md-10 offset-md-2">
<input
type="checkbox"
class="form-check-input me-2"
id="create_contact"
name="create_contact"
autocomplete="off"
{% if Role.CreateContact %}checked{% endif %}
/>
<label for="create_contact" class="form-label">
Créer contacts
</label>
</div>
</div>
<div class="row mb-3">
<div class="col-md-10 offset-md-2">
<input
type="checkbox"
class="form-check-input me-2"
id="edit_contact"
name="edit_contact"
autocomplete="off"
{% if Role.EditContact %}checked{% endif %}
/>
<label for="edit_contact" class="form-label">
Modifier contacts
</label>
</div>
</div>
<div class="row mb-3">
<div class="col-md-10 offset-md-2">
<input
type="checkbox"
class="form-check-input me-2"
id="show_archived_contact"
name="show_archived_contact"
autocomplete="off"
{% if Role.ShowArchivedContact %}checked{% endif %}
/>
<label for="show_archived_contact" class="form-label">
Afficher contacts archivés
</label>
</div>
</div>
<div class="row mb-3">
<div class="col-md-10 offset-md-2">
<input
type="checkbox"
class="form-check-input me-2"
id="archive_contact"
name="archive_contact"
autocomplete="off"
{% if Role.ArchiveContact %}checked{% endif %}
/>
<label for="archive_contact" class="form-label">
Archiver contacts
</label>
</div>
</div>
<div class="row mb-3">
<div class="col-md-10 offset-md-2">
<input
type="checkbox"
class="form-check-input me-2"
id="restore_contact"
name="restore_contact"
autocomplete="off"
{% if Role.RestoreContact %}checked{% endif %}
/>
<label for="restore_contact" class="form-label">
Restaurer contacts
</label>
</div>
</div>
<div class="row mb-3">
<div class="col-md-10 offset-md-2">
<input
type="checkbox"
class="form-check-input me-2"
id="purge_contact"
name="purge_contact"
autocomplete="off"
{% if Role.PurgeContact %}checked{% endif %}
/>
<label for="purge_contact" class="form-label">
Purger contacts (suppression définitive)
</label>
</div>
</div>
<div class="row mb-3">
<div class="col-md-10 offset-md-2">
<input
type="checkbox"
class="form-check-input me-2"
id="convert_contact_to_member"
name="convert_contact_to_member"
autocomplete="off"
{% if Role.ConvertContactToMember %}checked{% endif %}
/>
<label for="convert_contact_to_member" class="form-label">
Convertir contacts en membres
</label>
</div> </div>
</div> </div>

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container my-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -13,32 +13,31 @@
<hr /> <hr />
</div> </div>
<div class="my-3 text-end"> <div class="row my-3">
<a class="btn btn-outline-primary" href="/admin/roles/add"> <div class="col-sm-6">
<i class="bi-plus-lg"></i> <span class="h2 d-none d-sm-inline">Rôles</span>
Ajouter </div>
</a> <div class="col-sm-6 text-end">
<a class="btn btn-outline-primary" href="/admin/roles/add">
<i class="bi-plus-lg"></i>
Ajouter
</a>
</div>
</div> </div>
{% if Roles %} {% if Roles %}
<div class="table-responsive"> {% for Role in Roles %}
<table class="table"> <div class="card card-body my-2 py-2 bg-body-tertiary">
<thead> <div class="row">
<tr> <div class="col">
<th>Nom</th> <div class="text-bold fs-7 mt-xxl-0 mt-2">Nom</div>
</tr> <div>
</thead> <a href="/admin/roles/{{ Role.ID }}"> {{ Role.Name }} </a>
<tbody> </div>
{% for Role in Roles %} </div>
<tr> </div>
<td> </div>
<a href="/admin/roles/{{ Role.ID }}"> {{ Role.Name }} </a> {% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %} {% else %}
<div class="my-4">Pas de rôle pour le moment</div> <div class="my-4">Pas de rôle pour le moment</div>
{% endif %} {% endif %}

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container mt-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -16,146 +16,148 @@
<hr /> <hr />
</div> </div>
<div class="row mb-3"> <div class="mw-1200">
<div class="col-md-2">Nom</div> <div class="row align-items-center mb-3">
<div class="col-md-10"> <div class="col-md-2 col-xl-3">Nom</div>
<input <div class="col-md-10 col-xl-9">
type="text"
class="form-control"
value="{{ Section.Name }}"
disabled
readonly
/>
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Nom technique</div>
<div class="col-md-10">
<input
type="text"
class="form-control"
value="{{ Section.ShortName }}"
disabled
readonly
/>
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Section parente</div>
<div class="col-md-10">
{% if Section.ParentSectionID %}
<input <input
type="text" type="text"
class="form-control" class="form-control"
value="{{ Section.ParentSection.Name }}" value="{{ Section.Name }}"
disabled disabled
readonly readonly
/> />
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Peut contenir des membres</div>
<div class="col-md-10">
{% if Section.ContainsMembers %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Peut contenir des contacts</div>
<div class="col-md-10">
{% if Section.ContainsContacts %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="my-4 row">
<div class="col-6">
<a
class="btn btn-outline-primary"
href="/admin/sections/{{ Section.ID }}/edit"
>
<i class="bi-pencil-square"></i>
Modifier
</a>
</div>
<div class="col-6 text-end">
<button
type="button"
class="btn btn-outline-danger"
data-bs-toggle="modal"
data-bs-target="#modal-delete"
>
<i class="bi-trash3 me-1"></i>
Supprimer
</button>
</div>
</div>
</div>
<div id="modal-delete" class="modal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-body">
<p>Êtes-vous sûr de vouloir supprimer cette section ?</p>
</div> </div>
<div class="modal-footer"> </div>
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">Nom technique</div>
<div class="col-md-10 col-xl-9">
<input
type="text"
class="form-control"
value="{{ Section.ShortName }}"
disabled
readonly
/>
</div>
</div>
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">Section parente</div>
<div class="col-md-10 col-xl-9">
{% if Section.ParentSectionID %}
<input
type="text"
class="form-control"
value="{{ Section.ParentSection.Name }}"
disabled
readonly
/>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">Peut contenir des membres</div>
<div class="col-md-10 col-xl-9">
{% if Section.ContainsMembers %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">Peut contenir des sympathisants</div>
<div class="col-md-10 col-xl-9">
{% if Section.ContainsContacts %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="my-4 row align-items-center">
<div class="col-6">
<a
class="btn btn-outline-primary"
href="/admin/sections/{{ Section.ID }}/edit"
>
<i class="bi-pencil-square"></i>
Modifier
</a>
</div>
<div class="col-6 text-end">
<button <button
type="button" type="button"
class="btn btn-outline-secondary" class="btn btn-outline-danger"
data-bs-dismiss="modal" data-bs-toggle="modal"
data-bs-target="#modal-delete"
> >
<i class="bi-x-lg me-1"></i> <i class="bi-trash3 me-1"></i>
Annuler Supprimer
</button> </button>
</div>
</div>
</div>
<form <div id="modal-delete" class="modal" tabindex="-1">
action="/admin/sections/{{ Section.ID }}/delete" <div class="modal-dialog modal-dialog-centered">
method="post" <div class="modal-content">
class="d-inline p-0" <div class="modal-body">
> <p>Êtes-vous sûr de vouloir supprimer cette section ?</p>
<button class="btn btn-outline-danger" type="submit"> </div>
<i class="bi-trash3 me-1"></i> <div class="modal-footer">
Supprimer <button
type="button"
class="btn btn-outline-secondary"
data-bs-dismiss="modal"
>
<i class="bi-x-lg me-1"></i>
Annuler
</button> </button>
</form>
<form
action="/admin/sections/{{ Section.ID }}/delete"
method="post"
class="d-inline p-0"
>
<button class="btn btn-outline-danger" type="submit">
<i class="bi-trash3 me-1"></i>
Supprimer
</button>
</form>
</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container mt-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -24,20 +24,22 @@
<hr /> <hr />
</div> </div>
{% if Errors %} <form id="section" method="post" class="mw-1200">
<div class="alert alert-danger"> {% if Errors %}
<ul class="m-0"> <div class="alert alert-danger">
{% for Error in Errors %} <ul class="m-0">
<li>{{ Error }}</li> {% for Error in Errors %}
{% endfor %} <li>{{ Error }}</li>
</ul> {% endfor %}
</div> </ul>
{% endif %} </div>
{% endif %}
<form id="section" method="post"> <div class="row align-items-center mb-3">
<div class="row mb-3"> <label for="name" class="form-label mb-0 col-md-2 col-xl-3">
<label for="name" class="form-label col-md-2"> Nom </label> Nom
<div class="col-md-10"> </label>
<div class="col-md-10 col-xl-9">
<input <input
id="name" id="name"
class="form-control" class="form-control"
@ -51,11 +53,11 @@
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<label for="short_name" class="form-label col-md-2"> <label for="short_name" class="form-label mb-0 col-md-2 col-xl-3">
Nom technique Nom technique
</label> </label>
<div class="col-md-10"> <div class="col-md-10 col-xl-9">
<input <input
id="short_name" id="short_name"
class="form-control" class="form-control"
@ -68,11 +70,11 @@
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<label for="parent_section" class="form-label col-md-2"> <label for="parent_section" class="form-label mb-0 col-md-2 col-xl-3">
Section parente Section parente
</label> </label>
<div class="col-md-10"> <div class="col-md-10 col-xl-9">
<select <select
id="parent_section" id="parent_section"
class="form-select" class="form-select"
@ -97,8 +99,8 @@
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<div class="col-md-10 offset-md-2"> <div class="col-md-10 col-xl-9 offset-md-2 offset-xl-3">
<input <input
type="checkbox" type="checkbox"
class="form-check-input me-2" class="form-check-input me-2"
@ -109,14 +111,14 @@
checked checked
{% endif %} {% endif %}
/> />
<label for="contains_members" class="form-label"> <label for="contains_members" class="form-label mb-0">
Contient des membres Contient des membres
</label> </label>
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<div class="col-md-10 offset-md-2"> <div class="col-md-10 col-xl-9 offset-md-2 offset-xl-3">
<input <input
type="checkbox" type="checkbox"
class="form-check-input me-2" class="form-check-input me-2"
@ -127,8 +129,8 @@
checked checked
{% endif %} {% endif %}
/> />
<label for="contains_contacts" class="form-label"> <label for="contains_contacts" class="form-label mb-0">
Contient des contacts Contient des sympathisants
</label> </label>
</div> </div>
</div> </div>

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container my-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -13,63 +13,74 @@
<hr /> <hr />
</div> </div>
<div class="my-3 text-end"> <div class="row my-3">
<a class="btn btn-outline-primary" href="/admin/sections/add"> <div class="col-sm-6">
<i class="bi-plus-lg"></i> <span class="h2 d-none d-sm-inline">Sections</span>
Ajouter </div>
</a> <div class="col-sm-6 text-end">
<a class="btn btn-outline-primary" href="/admin/sections/add">
<i class="bi-plus-lg"></i>
Ajouter
</a>
</div>
</div> </div>
{% if Sections %} {% if Sections %}
<div class="table-responsive"> {% for Section in Sections %}
<table class="table"> <div class="card card-body my-2 py-2 bg-body-tertiary">
<thead> <div class="row">
<tr> <div class="col-12 col-sm-8 col-md-9 col-xl-3 order-1">
<th class="w-25">Nom</th> <div class="text-bold fs-7 mt-xxl-0 mt-2">Nom</div>
<th class="w-25">Section parente</th> <div>
<th class="w-25">Membres</th> <a href="/admin/sections/{{ Section.ID }}">
<th class="w-25">Contacts</th> {{ Section.Name }}
</tr> </a>
</thead> </div>
<tbody> </div>
{% for Section in Sections %}
<tr> <div
<td> class="col-12 col-sm-8 col-md-9 col-xl-3 order-2 order-sm-3 order-xl-2"
<a href="/admin/sections/{{ Section.ID }}"> >
{{ Section.Name }} <div class="text-bold fs-7 mt-xxl-0 mt-2">Section parente</div>
</a> <div>
</td> {% if Section.ParentSectionID %}
<td> <a href="/admin/sections/{{ Section.ParentSectionID }}">
{% if Section.ParentSectionID %}
{{ Section.ParentSection.Name }} {{ Section.ParentSection.Name }}
{% else %} </a>
<i class="bi-x-lg text-danger me-1"></i> {% else %}
Non <span class="badge text-bg-danger"
{% endif %} >Pas de section parente</span
</td> >
<td> {% endif %}
{% if Section.ContainsMembers %} </div>
<i class="bi-check-lg text-success me-1"></i> </div>
Oui
{% else %} <div
<i class="bi-x-lg text-danger me-1"></i> class="col-12 col-sm-4 col-md-3 col-xl-3 order-3 order-sm-2 order-xl-3"
Non >
{% endif %} <div class="text-bold fs-7 mt-xxl-0 mt-2">Membres</div>
</td> <div>
<td> {% if Section.ContainsMembers %}
{% if Section.ContainsContacts %} <span class="badge text-bg-success">Oui</span>
<i class="bi-check-lg text-success me-1"></i> {% else %}
Oui <span class="badge text-bg-danger">Non</span>
{% else %} {% endif %}
<i class="bi-x-lg text-danger me-1"></i> </div>
Non </div>
{% endif %}
</td> <div class="col-12 col-sm-4 col-md-3 col-xl-3 order-4">
</tr> <div class="text-bold fs-7 mt-xxl-0 mt-2">Sympathisants</div>
{% endfor %} <div>
</tbody> {% if Section.ContainsContacts %}
</table> <span class="badge text-bg-success">Oui</span>
</div> {% else %}
<span class="badge text-bg-danger">Non</span>
{% endif %}
</div>
</div>
</div>
</div>
{% endfor %}
{% else %} {% else %}
<div class="my-4">Pas de section pour le moment</div> <div class="my-4">Pas de section pour le moment</div>
{% endif %} {% endif %}

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container mt-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -16,154 +16,158 @@
<hr /> <hr />
</div> </div>
<div class="row mb-3"> <div class="mw-1200">
<div class="col-md-2">Nom complet</div> <div class="row align-items-center mb-3">
<div class="col-md-10"> <div class="col-md-2 col-xl-3">Nom complet</div>
<input <div class="col">
type="text" <input
class="form-control" type="text"
value="{{ User.Name }}" class="form-control"
disabled value="{{ User.Name }}"
readonly disabled
/> readonly
/>
</div>
</div> </div>
</div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<div class="col-md-2">Email</div> <div class="col-md-2 col-xl-3">Email</div>
<div class="col-md-10"> <div class="col">
<input <input
type="text" type="text"
class="form-control" class="form-control"
value="{{ User.Email }}" value="{{ User.Email }}"
disabled disabled
readonly readonly
/> />
</div>
</div> </div>
</div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<div class="col-md-2">Administrateur</div> <div class="col-md-2 col-xl-3">Administrateur</div>
<div class="col-md-10"> <div class="col">
{% if User.IsAdmin %} {% if User.IsAdmin %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Ecran de bienvenue à la prochaine connexion</div>
<div class="col-md-10">
{% if User.SkipWelcome %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row mb-3">
<div class="col-md-2">Double facteur (TOTP)</div>
<div class="col-md-10">
{% if User.TotpSecret.Valid %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Enrôlé" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input
type="text"
class="form-control"
value="Enrôlement lors de la prochaine connexion"
disabled
/>
</div>
{% endif %}
</div>
</div>
<div class="mt-4 mb-3">
<span class="h4"> Permissions </span>
</div>
{% if UserRoles %}
{% for UserRole in UserRoles %}
<div class="row mb-3">
<div class="col-md-2">{{ UserRole.Section.Name }}</div>
<div class="col-md-10">
<div class="input-group"> <div class="input-group">
<span class="input-group-text"> <span class="input-group-text">
<i class="bi-key"></i> <i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">
Ecran de bienvenue à la prochaine connexion
</div>
<div class="col">
{% if User.SkipWelcome %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Non" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span>
<input type="text" class="form-control" value="Oui" disabled />
</div>
{% endif %}
</div>
</div>
<div class="row align-items-center mb-3">
<div class="col-md-2 col-xl-3">Double facteur (TOTP)</div>
<div class="col">
{% if User.TotpSecret.Valid %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-check-lg text-success"></i>
</span>
<input type="text" class="form-control" value="Enrôlé" disabled />
</div>
{% else %}
<div class="input-group">
<span class="input-group-text">
<i class="bi-x-lg text-danger"></i>
</span> </span>
<input <input
type="text" type="text"
class="form-control" class="form-control"
value="{{ UserRole.Role.Name }}" value="Enrôlement lors de la prochaine connexion"
disabled disabled
readonly
/> />
</div> </div>
</div> {% endif %}
</div> </div>
{% endfor %}
{% else %}
<div>Pas encore de permissions pour cet utilisateur.</div>
{% endif %}
<div class="my-4 row">
<div class="col-6">
<a
class="btn btn-outline-primary"
href="/admin/users/{{ User.ID }}/edit"
>
<i class="bi-pencil-square me-1"></i>
Modifier
</a>
<a
class="btn btn-outline-primary"
href="/admin/users/{{ User.ID }}/permissions"
>
<i class="bi-key me-1"></i>
Permissions
</a>
</div> </div>
<div class="col-6 text-end">
<button <div class="mt-4 mb-3">
type="button" <span class="h4"> Permissions </span>
class="btn btn-outline-danger" </div>
data-bs-toggle="modal" {% if UserRoles %}
data-bs-target="#modal-delete" {% for UserRole in UserRoles %}
> <div class="row align-items-center mb-3">
<i class="bi-trash3 me-1"></i> <div class="col-md-2 col-xl-3">{{ UserRole.Section.Name }}</div>
Supprimer <div class="col">
</button> <div class="input-group">
<span class="input-group-text">
<i class="bi-key"></i>
</span>
<input
type="text"
class="form-control"
value="{{ UserRole.Role.Name }}"
disabled
readonly
/>
</div>
</div>
</div>
{% endfor %}
{% else %}
<div>Pas encore de permissions pour cet utilisateur.</div>
{% endif %}
<div class="my-4 row align-items-center">
<div class="col-6">
<a
class="btn btn-outline-primary"
href="/admin/users/{{ User.ID }}/edit"
>
<i class="bi-pencil-square me-1"></i>
Modifier
</a>
<a
class="btn btn-outline-primary"
href="/admin/users/{{ User.ID }}/permissions"
>
<i class="bi-key me-1"></i>
Permissions
</a>
</div>
<div class="col-6 text-end">
<button
type="button"
class="btn btn-outline-danger"
data-bs-toggle="modal"
data-bs-target="#modal-delete"
>
<i class="bi-trash3 me-1"></i>
Supprimer
</button>
</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container mt-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -24,20 +24,22 @@
<hr /> <hr />
</div> </div>
{% if Errors %} <form id="user" method="post" class="mw-1200">
<div class="alert alert-danger"> {% if Errors %}
<ul class="m-0"> <div class="alert alert-danger">
{% for Error in Errors %} <ul class="m-0">
<li>{{ Error }}</li> {% for Error in Errors %}
{% endfor %} <li>{{ Error }}</li>
</ul> {% endfor %}
</div> </ul>
{% endif %} </div>
{% endif %}
<form id="user" method="post"> <div class="row align-items-center mb-3">
<div class="row mb-3"> <label for="name" class="form-label col-md-2 col-xl-3">
<label for="name" class="form-label col-md-2"> Nom complet </label> Nom complet
<div class="col-md-10"> </label>
<div class="col">
<input <input
id="name" id="name"
class="form-control" class="form-control"
@ -51,9 +53,9 @@
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<label for="email" class="form-label col-md-2"> Email </label> <label for="email" class="form-label col-md-2 col-xl-3"> Email </label>
<div class="col-md-10"> <div class="col">
<input <input
id="email" id="email"
class="form-control" class="form-control"
@ -66,8 +68,8 @@
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<div class="col-md-10 offset-md-2"> <div class="col offset-md-2 offset-xl-3">
<input <input
type="checkbox" type="checkbox"
class="form-check-input me-2" class="form-check-input me-2"
@ -82,9 +84,11 @@
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row align-items-center mb-3">
<label for="password" class="form-label col-md-2"> Mot de passe </label> <label for="password" class="form-label col-md-2 col-xl-3">
<div class="col-md-10"> Mot de passe
</label>
<div class="col">
<input <input
id="password" id="password"
class="form-control" class="form-control"
@ -100,8 +104,8 @@
</div> </div>
{% if User.ID %} {% if User.ID %}
<div class="row mb-3"> <div class="row align-items-center mb-3">
<div class="col-md-10 offset-md-2"> <div class="col offset-md-2 offset-xl-3">
<input <input
type="checkbox" type="checkbox"
class="form-check-input me-2" class="form-check-input me-2"

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container mt-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -19,22 +19,22 @@
<hr /> <hr />
</div> </div>
{% if Errors %}
<div class="alert alert-danger">
<ul class="m-0">
{% for Error in Errors %}
<li>{{ Error }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% if Sections %} {% if Sections %}
<form id="user" method="post"> <form id="user" method="post" class="mw-1200">
{% if Errors %}
<div class="alert alert-danger">
<ul class="m-0">
{% for Error in Errors %}
<li>{{ Error }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% for Section in Sections %} {% for Section in Sections %}
<div class="row mb-3"> <div class="row mb-3">
<div class="col-md-2">{{ Section.Name }}</div> <div class="col-md-2 col-xl-3">{{ Section.Name }}</div>
<div class="col-md-10"> <div class="col">
<div class="input-group"> <div class="input-group">
<span class="input-group-text"> <span class="input-group-text">
<i class="bi-key"></i> <i class="bi-key"></i>

View file

@ -1,7 +1,7 @@
{% extends "layouts/main.html" %} {% extends "layouts/main.html" %}
{% block main %} {% block main %}
<div class="container my-4"> <div class="container-fluid my-4 px-4">
<div class="mb-4"> <div class="mb-4">
<nav> <nav>
<ol class="breadcrumb"> <ol class="breadcrumb">
@ -13,45 +13,47 @@
<hr /> <hr />
</div> </div>
<div class="my-3 text-end"> <div class="row my-3">
<a class="btn btn-outline-primary" href="/admin/users/add"> <div class="col-sm-6">
<i class="bi-plus-lg"></i> <span class="h2 d-none d-sm-inline">Utilisateurs</span>
Ajouter </div>
</a> <div class="col-sm-6 text-end">
<a class="btn btn-outline-primary" href="/admin/users/add">
<i class="bi-plus-lg"></i>
Ajouter
</a>
</div>
</div> </div>
{% if Users %} {% if Users %}
<div class="table-responsive"> {% for User in Users %}
<table class="table"> <div class="card card-body my-2 py-2 bg-body-tertiary">
<thead> <div class="row">
<tr> <div class="col-12 col-sm-8 col-md-9 col-xl-5 order-1">
<th class="w-50">Nom complet</th> <div class="text-bold fs-7 mt-xxl-0 mt-2">Nom</div>
<th class="w-25">Email</th> <div>
<th class="w-25">Administrateur</th> <a href="/admin/users/{{ User.ID }}"> {{ User.Name }} </a>
</tr> </div>
</thead> </div>
<tbody>
{% for User in Users %} <div class="col-12 col-xl-5 order-2 order-sm-3 order-xl-2">
<tr> <div class="text-bold fs-7 mt-xxl-0 mt-2">Email</div>
<td> <div>{{ User.Email }}</div>
<span class="user-photo me-2">{{ User.Name|first }}</span> </div>
<a href="/admin/users/{{ User.ID }}"> {{ User.Name }} </a>
</td> <div class="col order-3 order-sm-2 order-xl-3">
<td>{{ User.Email }}</td> <div class="text-bold fs-7 mt-xxl-0 mt-2">Administrateur</div>
<td> <div>
{% if User.IsAdmin %} {% if User.IsAdmin %}
<i class="bi-check-lg text-success me-1"></i> <span class="badge text-bg-success">Oui</span>
Oui {% else %}
{% else %} <span class="badge text-bg-danger">Non</span>
<i class="bi-x-lg text-danger me-1"></i> {% endif %}
Non </div>
{% endif %} </div>
</td> </div>
</tr> </div>
{% endfor %} {% endfor %}
</tbody>
</table>
</div>
{% else %} {% else %}
<div class="my-4">Pas d'utilisateurs pour le moment</div> <div class="my-4">Pas d'utilisateurs pour le moment</div>
{% endif %} {% endif %}