docs: update group concept
This commit is contained in:
parent
1d1f3b16b1
commit
1c7c56130d
1 changed files with 31 additions and 21 deletions
|
|
@ -117,10 +117,10 @@ CREATE TABLE groups (
|
|||
description TEXT,
|
||||
inserted_at TIMESTAMP NOT NULL,
|
||||
updated_at TIMESTAMP NOT NULL,
|
||||
CONSTRAINT groups_name_unique UNIQUE (name)
|
||||
CONSTRAINT groups_name_unique UNIQUE (LOWER(name))
|
||||
);
|
||||
|
||||
CREATE INDEX groups_name_index ON groups(name);
|
||||
CREATE INDEX groups_name_index ON groups(LOWER(name));
|
||||
```
|
||||
|
||||
**Attributes:**
|
||||
|
|
@ -130,7 +130,7 @@ CREATE INDEX groups_name_index ON groups(name);
|
|||
- `inserted_at` / `updated_at` - Timestamps
|
||||
|
||||
**Constraints:**
|
||||
- `name` must be unique
|
||||
- `name` must be unique (case-insensitive, using LOWER(name))
|
||||
- `name` cannot be null
|
||||
- `name` max length: 100 characters
|
||||
- `description` max length: 500 characters
|
||||
|
|
@ -194,7 +194,7 @@ end
|
|||
- `destroy` - Delete group (with confirmation)
|
||||
|
||||
**Validations:**
|
||||
- `name` required, unique, max 100 chars
|
||||
- `name` required, unique (case-insensitive), max 100 chars
|
||||
- `description` optional, max 500 chars
|
||||
|
||||
#### `Mv.Membership.MemberGroup`
|
||||
|
|
@ -319,7 +319,7 @@ end
|
|||
- Display group badges for each member
|
||||
- Badge shows group name
|
||||
- Multiple badges if member in multiple groups
|
||||
- Click badge to filter by that group
|
||||
- *(Optional)* Click badge to filter by that group (enhanced UX, can be added later)
|
||||
|
||||
**Filtering:**
|
||||
- Dropdown/select to filter by group
|
||||
|
|
@ -374,7 +374,11 @@ end
|
|||
</span>
|
||||
```
|
||||
|
||||
**Clickable Group Badge (for filtering):**
|
||||
**Clickable Group Badge (for filtering) - Optional:**
|
||||
|
||||
**Note:** This is an optional enhancement. The dropdown filter provides the same functionality. The clickable badge improves UX by showing the active filter visually and allowing quick removal.
|
||||
|
||||
**Estimated effort:** 1.5-2.5 hours
|
||||
|
||||
```heex
|
||||
<button
|
||||
|
|
@ -712,13 +716,13 @@ Das MVP umfasst die **grundlegenden Funktionen**, die notwendig sind, um Gruppen
|
|||
7. ✅ Nach Gruppen filtern
|
||||
8. ✅ Nach Gruppen sortieren
|
||||
9. ✅ Gruppen in Mitgliederdetail anzeigen
|
||||
10. ✅ Gruppen in Mitgliedersuche (automatisch via search_vector)
|
||||
|
||||
**Nicht im MVP:**
|
||||
- ❌ Hierarchische Gruppen
|
||||
- ❌ Rollen/Positionen in Gruppen
|
||||
- ❌ Erweiterte Gruppenattribute (Datum, Status, etc.)
|
||||
- ❌ Gruppen-spezifische Berechtigungen
|
||||
- ❌ Gruppen in Mitgliedersuche (kann später kommen)
|
||||
|
||||
### Fachliche Einheiten (Vertikale Slices)
|
||||
|
||||
|
|
@ -846,11 +850,9 @@ Das MVP umfasst die **grundlegenden Funktionen**, die notwendig sind, um Gruppen
|
|||
- ✅ Einheit 3: Gruppen-Verwaltungs-UI
|
||||
- ✅ Einheit 4: Gruppen in Mitgliederübersicht
|
||||
- ✅ Einheit 5: Gruppen in Mitgliederdetail
|
||||
- ✅ Einheit 6: Gruppen in Mitgliedersuche (automatisch via search_vector)
|
||||
- ✅ Einheit 7: Berechtigungen
|
||||
|
||||
**Optional für MVP (kann später kommen):**
|
||||
- ⏸️ Einheit 6: Gruppen in Mitgliedersuche (kann in Phase 2 kommen)
|
||||
|
||||
**Total MVP Estimation:** 13-15h
|
||||
|
||||
### Implementierungsreihenfolge
|
||||
|
|
@ -947,11 +949,13 @@ Jede fachliche Einheit kann als **separates Issue** umgesetzt werden:
|
|||
3. Group filter dropdown
|
||||
4. Group sorting
|
||||
5. URL query param persistence
|
||||
6. *(Optional)* Clickable group badges for filtering (enhanced UX)
|
||||
|
||||
**Deliverables:**
|
||||
- Groups visible in member overview
|
||||
- Filter by group
|
||||
- Filter by group (via dropdown)
|
||||
- Sort by group
|
||||
- *(Optional)* Clickable badges for quick filtering
|
||||
|
||||
**Estimation:** 2-3h
|
||||
|
||||
|
|
@ -1046,12 +1050,14 @@ Jede fachliche Einheit kann als **separates Issue** umgesetzt werden:
|
|||
- Group filter dropdown
|
||||
- Group sorting
|
||||
- URL persistence
|
||||
- *(Optional)* Clickable group badges for filtering
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Groups visible in member overview
|
||||
- Can filter by group
|
||||
- Can filter by group (via dropdown)
|
||||
- Can sort by group
|
||||
- Filter persists in URL
|
||||
- *(Optional)* Can filter by clicking group badge
|
||||
|
||||
### Issue 4: Member Detail - Groups Display
|
||||
**Type:** Frontend
|
||||
|
|
@ -1069,13 +1075,16 @@ Jede fachliche Einheit kann als **separates Issue** umgesetzt werden:
|
|||
**Type:** Backend
|
||||
**Estimation:** 2h
|
||||
**Tasks:**
|
||||
- Update search vector trigger
|
||||
- Extend fuzzy search
|
||||
- Test search
|
||||
- Update search vector trigger to include group names
|
||||
- Extend fuzzy search to search group names
|
||||
- Test search functionality
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Group names searchable in member search
|
||||
- Group names searchable in member search (automatic via search_vector)
|
||||
- Search finds members by group name
|
||||
- Search vector updates automatically when member-group associations change
|
||||
|
||||
**Note:** This is part of MVP as group names are automatically included in full-text search once the search_vector trigger is updated.
|
||||
|
||||
### Issue 6: Authorization
|
||||
**Type:** Backend/Frontend
|
||||
|
|
@ -1132,11 +1141,12 @@ defmodule Mv.Membership.GroupTest do
|
|||
assert %{name: ["has already been taken"]} = errors_on(changeset)
|
||||
end
|
||||
|
||||
test "name uniqueness is case-sensitive" do
|
||||
test "name uniqueness is case-insensitive" do
|
||||
Group.create!(%{name: "Vorstand"})
|
||||
attrs = %{name: "VORSTAND"}
|
||||
# For MVP: case-sensitive uniqueness
|
||||
assert {:ok, _} = Group.create(attrs)
|
||||
# Name uniqueness should be case-insensitive
|
||||
assert {:error, changeset} = Group.create(attrs)
|
||||
assert %{name: ["has already been taken"]} = errors_on(changeset)
|
||||
end
|
||||
|
||||
test "allows description to be nil" do
|
||||
|
|
@ -1458,8 +1468,8 @@ create table(:groups, primary_key: false) do
|
|||
add :updated_at, :utc_datetime_usec, null: false
|
||||
end
|
||||
|
||||
create unique_index(:groups, [:name])
|
||||
create index(:groups, [:name])
|
||||
create unique_index(:groups, [fragment("LOWER(name)")], name: :groups_name_unique)
|
||||
create index(:groups, [fragment("LOWER(name)")], name: :groups_name_index)
|
||||
```
|
||||
|
||||
**Migration 2: Create member_groups join table**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue