From 46474981f004723be58032f5154249343f7a9d5e Mon Sep 17 00:00:00 2001 From: cclohmar Date: Mon, 15 Jun 2026 05:39:32 +0000 Subject: [PATCH] feat(groups): app permission checkboxes in create group form --- src/core/admin/groups.go | 11 ++++--- src/core/admin/templates/groups.templ | 16 +++++++++ src/core/admin/templates/groups_templ.go | 42 +++++++++++++++++++++++- src/core/admin/templates/layout.templ | 4 +++ src/core/admin/templates/layout_templ.go | 2 +- src/core/admin/ui.go | 11 ++++++- src/core/db/db.go | 7 +++- 7 files changed, 84 insertions(+), 9 deletions(-) diff --git a/src/core/admin/groups.go b/src/core/admin/groups.go index a4baa5d..638ff51 100644 --- a/src/core/admin/groups.go +++ b/src/core/admin/groups.go @@ -10,6 +10,7 @@ type Group struct { ID int `json:"id"` Name string `json:"name"` Description string `json:"description"` + Apps string `json:"apps"` UserCount int `json:"user_count"` } @@ -24,7 +25,7 @@ func NewGroupStore(db *sql.DB) *GroupStore { func (s *GroupStore) List() ([]Group, error) { rows, err := s.db.Query(` - SELECT g.id, g.name, g.description, + SELECT g.id, g.name, g.description, g.apps, (SELECT COUNT(*) FROM users WHERE ',' || groups || ',' LIKE '%,' || g.name || ',%') as user_count FROM groups g ORDER BY g.name `) @@ -36,7 +37,7 @@ func (s *GroupStore) List() ([]Group, error) { var groups []Group for rows.Next() { var g Group - if err := rows.Scan(&g.ID, &g.Name, &g.Description, &g.UserCount); err != nil { + if err := rows.Scan(&g.ID, &g.Name, &g.Description, &g.Apps, &g.UserCount); err != nil { return nil, err } groups = append(groups, g) @@ -46,7 +47,7 @@ func (s *GroupStore) List() ([]Group, error) { func (s *GroupStore) GetByName(name string) (*Group, error) { var g Group - err := s.db.QueryRow(`SELECT id, name, description FROM groups WHERE name = ?`, name).Scan(&g.ID, &g.Name, &g.Description) + err := s.db.QueryRow(`SELECT id, name, description, apps FROM groups WHERE name = ?`, name).Scan(&g.ID, &g.Name, &g.Description, &g.Apps) if err == sql.ErrNoRows { return nil, nil } @@ -56,8 +57,8 @@ func (s *GroupStore) GetByName(name string) (*Group, error) { return &g, nil } -func (s *GroupStore) Create(name, description string) error { - _, err := s.db.Exec(`INSERT INTO groups (name, description) VALUES (?, ?)`, name, description) +func (s *GroupStore) Create(name, description, apps string) error { + _, err := s.db.Exec(`INSERT INTO groups (name, description, apps) VALUES (?, ?, ?)`, name, description, apps) if err != nil { return fmt.Errorf("create group %s: %w", name, err) } diff --git a/src/core/admin/templates/groups.templ b/src/core/admin/templates/groups.templ index 83fca4a..a6b78a2 100644 --- a/src/core/admin/templates/groups.templ +++ b/src/core/admin/templates/groups.templ @@ -69,11 +69,27 @@ templ CreateGroupForm() { +
+ +
+ for _, a := range allApps() { + + } +
+
} +func allApps() []string { + return []string{"Admin Panel", "Files", "Mail", "Calendar", "Office", "Contacts", "Tasks", "Chat"} +} + + type GroupRow struct { Name string UserCount int diff --git a/src/core/admin/templates/groups_templ.go b/src/core/admin/templates/groups_templ.go index 37044fe..9c3cb6a 100644 --- a/src/core/admin/templates/groups_templ.go +++ b/src/core/admin/templates/groups_templ.go @@ -192,7 +192,43 @@ func CreateGroupForm() templ.Component { templ_7745c5c3_Var10 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "

New Group

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "

New Group

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + for _, a := range allApps() { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -200,6 +236,10 @@ func CreateGroupForm() templ.Component { }) } +func allApps() []string { + return []string{"Admin Panel", "Files", "Mail", "Calendar", "Office", "Contacts", "Tasks", "Chat"} +} + type GroupRow struct { Name string UserCount int diff --git a/src/core/admin/templates/layout.templ b/src/core/admin/templates/layout.templ index 93cd78a..8455248 100644 --- a/src/core/admin/templates/layout.templ +++ b/src/core/admin/templates/layout.templ @@ -143,5 +143,9 @@ templ adminStyles() { .group-row-left{display:flex;align-items:center;gap:10px} .group-icon{width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:0.8rem;font-weight:700;color:#fff} .group-row-right{display:flex;align-items:center;gap:8px} + .checkbox-list{display:grid;grid-template-columns:1fr 1fr;gap:4px;max-height:120px;overflow-y:auto} + .checkbox-item{display:flex;align-items:center;gap:6px;padding:6px 8px;border-radius:6px;cursor:pointer;font-size:0.85rem} + .checkbox-item:hover{background:var(--surface2)} + .checkbox-item input[type=checkbox]{accent-color:var(--blue)} } diff --git a/src/core/admin/templates/layout_templ.go b/src/core/admin/templates/layout_templ.go index 4dadc5d..88887c7 100644 --- a/src/core/admin/templates/layout_templ.go +++ b/src/core/admin/templates/layout_templ.go @@ -169,7 +169,7 @@ func adminStyles() templ.Component { templ_7745c5c3_Var10 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/src/core/admin/ui.go b/src/core/admin/ui.go index 2e35eb0..afe71bb 100644 --- a/src/core/admin/ui.go +++ b/src/core/admin/ui.go @@ -332,7 +332,16 @@ func (h *Handler) createGroup(w http.ResponseWriter, r *http.Request) { http.Error(w, "name required", http.StatusBadRequest) return } - if err := h.groupStore.Create(name, desc); err != nil { + // Collect checked apps + apps := r.Form["app"] + appsStr := "" + for i, a := range apps { + if i > 0 { + appsStr += "," + } + appsStr += a + } + if err := h.groupStore.Create(name, desc, appsStr); err != nil { http.Error(w, err.Error(), http.StatusConflict) return } diff --git a/src/core/db/db.go b/src/core/db/db.go index b906f2f..3c2d788 100644 --- a/src/core/db/db.go +++ b/src/core/db/db.go @@ -67,10 +67,15 @@ func (d *Database) ensureTable(name string) error { id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE NOT NULL, description TEXT NOT NULL DEFAULT '', + apps TEXT NOT NULL DEFAULT '', created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) `) - return err + if err != nil { + return err + } + d.DB.Exec(`ALTER TABLE groups ADD COLUMN apps TEXT NOT NULL DEFAULT ''`) + return nil case "users": // Create table if it doesn't exist