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() {
+
}
+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, "")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "")
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