Now opens a blank article editor modal with the category pre-selected (stored in localStorage). You can fill in the article details and create a new article directly from the folder view without navigating away.
alps

GROUPS_FEATURE_SUMMARY

6 min readInvalid Date5 views

Teams & Groups Feature - Complete Implementation Summary

Status: ✅ Complete

The Teammate Groups feature has been successfully implemented and integrated into the existing Alps application following the SettingsShell pattern.

What Was Built

1. Backend - Group Management API

<strong>File: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">backend/controllers/group.controller.js</code></strong>

  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">listGroups(req, res)</code> - GET /api/v1/groups
  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">createGroup(req, res)</code> - POST /api/v1/groups
  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">updateGroup(req, res)</code> - PATCH /api/v1/groups/:groupId
  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">deleteGroup(req, res)</code> - DELETE /api/v1/groups/:groupId

All operations are workspace-scoped to <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">req.user.workspaceId</code>.

<strong>File: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">backend/routes/group.route.js</code></strong>

  • Defines routes for group CRUD operations
  • All protected with <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">authController.protect</code> middleware

<strong>Integration in <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">backend/app.js</code></strong>

  • Routes mounted at <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">/api/v1/groups</code>

<strong>Update to <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">backend/controllers/messageController.js</code></strong>

  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">assignConversation()</code> now accepts optional <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">groupId</code> in request body
  • When <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">groupId</code> provided: sets <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">assignedGroupId</code> and clears <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">assignedToId</code>
  • When <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">assigneeId</code> provided: sets <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">assignedToId</code> and clears <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">assignedGroupId</code>
  • System message updated: "Assigned to {Group Name}"
  • Pusher event includes <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">assignedGroupId</code> in payload

2. Frontend - API Service Functions

<strong>File: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">frontend/asset/services/request.js</code></strong>

Added 4 new group API functions:

javascript
export const getGroups = async (token) => GET /api/v1/groups
export const createGroup = async (token, body) => POST /api/v1/groups
export const updateGroup = async (token, groupId, body) => PATCH /api/v1/groups/:groupId
export const deleteGroup = async (token, groupId) => DELETE /api/v1/groups/:groupId

3. Frontend - Settings UI Integration

<strong>File: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">frontend/asset/SettingsPages/AgentsAndTeamsPage.jsx</code> (REDESIGNED)</strong>

Previously had standalone <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">/settings/groups/page.jsx</code> - <strong>DELETED</strong>

Now integrated directly into AgentsAndTeamsPage following the established pattern:

<strong>New "Teams & Groups" section</strong> featuring:

  • Section header with description
  • "New Group" button (purple button consistent with UI)
  • Group creation form:

- Group name input<br> - Multi-select checkboxes for team members (scrollable list)<br> - Save/Cancel buttons

  • Groups list display:

- Group name as bold heading<br> - Member badges (showing member names)<br> - Edit and Delete buttons per group<br> - Empty state message if no groups exist

<strong>State management added:</strong>

  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">groups</code> - array of groups
  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">showGroupForm</code> - toggle form visibility
  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">editingGroupId</code> - track which group is being edited
  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">groupFormData</code> - form state (name + memberIds)
  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">groupSubmitting</code> - loading state

<strong>Handler functions added:</strong>

  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">getMemberName(memberId)</code> - lookup member by ID
  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">toggleGroupMember(memberId)</code> - add/remove member from group
  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">handleGroupSubmit(e)</code> - create or update group
  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">handleGroupEdit(group)</code> - load group into form
  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">handleGroupDelete(groupId)</code> - delete group with confirmation

<strong>Integration with existing data:</strong>

  • Fetches groups on component load via <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">fetchAll()</code>
  • Uses existing <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">teamMembers</code> state for member selection
  • No duplicate member fetch needed

4. Frontend - Conversation Assignment UI

<strong>File: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">frontend/asset/InboxPages/UserDetails.jsx</code> (PREVIOUSLY UPDATED)</strong>

Already integrated with:

  • Import of <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">getGroups</code> from request.js
  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">assignedGroupId</code> state management
  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">fetchGroups()</code> function
  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">handleGroupAssign(groupId)</code> function
  • Conversation section with:

- "Assign to Agent" dropdown (existing)<br> - "Assign to Group" dropdown (new)<br> - Mutual exclusivity: selecting agent clears group, and vice versa

5. Frontend - @Mention in Chat

<strong>File: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">frontend/asset/InboxPages/ChatBox.jsx</code> (PREVIOUSLY UPDATED)</strong>

Already integrated with:

  • Mention state management (mentionOpen, mentionQuery, mentionMembers, mentionGroups)
  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">handleMentionClick()</code> - opens mention dropdown when @ button clicked
  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">insertMention(name)</code> - inserts @name into textarea
  • Mention dropdown showing:

- All workspace members<br> - All groups (prefixed with @ for clarity)

  • Functional @mention button linked to dropdown

Data Model

Firestore Collection: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">groups</code>

javascript
{
  id,                // auto-generated
  workspaceId,       // string - scoped to workspace
  name,              // string - e.g. "Billing Team"
  memberIds: [],     // string[] - userIds of members in group
  createdAt,         // timestamp
  updatedAt          // timestamp
}

Conversations: Added optional <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">assignedGroupId</code> field

When a conversation is assigned to a group, it stores:

  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">assignedGroupId</code> - ID of the assigned group
  • <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">assignedToId: null</code> - cleared when group assigned
  • System message indicating group assignment

Workflow: How to Use the Feature

1. Create a Group (Settings → Agents & Teams → Teams & Groups)

  1. Click "New Group" button
  2. Enter group name (e.g., "Billing Team")
  3. Check boxes to select team members
  4. Click "Save Group"
  5. Group appears in the list below

2. Manage Groups

  • <strong>Edit</strong>: Click "Edit" button on group card, modify details, save
  • <strong>Delete</strong>: Click trash icon, confirm deletion
  • On deletion: conversations assigned to that group become unassigned

3. Assign Conversation to Group

  1. Open conversation in inbox
  2. Open right sidebar (UserDetails)
  3. Find "Assign to Group" dropdown in Conversation section
  4. Select a group
  5. System message "Assigned to {Group Name}" appears
  6. All group members can now see and manage the conversation

4. @Mention in Chat

  1. In reply/note textarea, click @ button OR type <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">@</code>
  2. Dropdown appears showing:

- All team members<br> - All groups (with @ prefix)

  1. Click/type to select
  2. <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">@Name</code> inserted into text
  3. Post the message
  4. Mention is stored as plain text (server-side parsing in v2)

Files Changed

| File | Action | Purpose |<br>|---|---|---|<br>| <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">backend/controllers/group.controller.js</code> | <strong>NEW</strong> | Group CRUD API |<br>| <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">backend/routes/group.route.js</code> | <strong>NEW</strong> | Group routes |<br>| <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">backend/app.js</code> | Modified | Mount group routes |<br>| <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">backend/controllers/messageController.js</code> | Modified | Support groupId in assignConversation |<br>| <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">frontend/asset/services/request.js</code> | Modified | Add 4 group API functions |<br>| <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">frontend/asset/SettingsPages/AgentsAndTeamsPage.jsx</code> | Modified | Add Teams & Groups section |<br>| <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">frontend/app/settings/groups/page.jsx</code> | <strong>DELETED</strong> | Removed standalone page |<br>| <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">frontend/asset/InboxPages/UserDetails.jsx</code> | Previously modified | Group assignment UI |<br>| <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">frontend/asset/InboxPages/ChatBox.jsx</code> | Previously modified | @mention functionality |

Key Design Decisions

  1. <strong>Pattern Consistency</strong>: Groups UI follows the established SettingsShell/AgentsAndTeamsPage pattern, not a standalone page. Matches the style of "General", "SLA", etc.
  1. <strong>Team Member Display</strong>: Uses existing <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">teamMembers</code> state already fetched by AgentsAndTeamsPage, no duplicate API calls.
  1. <strong>Mutual Exclusivity</strong>: When assigning a conversation to a group, individual agent assignment is cleared (and vice versa). Prevents conflicts.
  1. <strong>Confirmation on Delete</strong>: Warns user that conversations assigned to a deleted group become unassigned.
  1. <strong>No Notification v1</strong>: @mentions are stored as plain text. Server-side parsing and notifications will be added in v2 (separate feature).
  1. <strong>Workspace Scoping</strong>: All groups are scoped to the workspace, preventing cross-workspace access.

Testing Checklist

  • [ ] Create a group with 2-3 team members → group appears in list
  • [ ] Edit group name → changes reflected immediately
  • [ ] Add/remove members from group → changes reflect in the list
  • [ ] Delete group → confirmed deletion, conversation becomes unassigned
  • [ ] Open conversation → "Assign to Group" dropdown shows all groups
  • [ ] Assign conversation to group → system message appears
  • [ ] Type <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">@</code> in ChatBox reply → dropdown shows members + groups
  • [ ] Click @ button in ChatBox → dropdown shows members + groups
  • [ ] Select group or member → <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">@Name</code> inserted into text
  • [ ] Send reply with @mention → mention appears in message

Known Limitations (v1)

  1. <strong>No auto-assignment</strong>: New conversations don't automatically route to a group
  2. <strong>No notifications</strong>: @mentions don't send emails/push notifications yet
  3. <strong>No filtering</strong>: Inbox doesn't have "filter by group" option yet
  4. <strong>Plain text mentions</strong>: No server-side parsing of @mentions for tagging/notifications

These are planned for v2 and can be added without rearchitecting.

Future Enhancements (v2+)

  • [ ] Inbox auto-assignment rules (conversations tagged X auto-assign to Group Y)
  • [ ] @mention notifications (email/push when mentioned)
  • [ ] Server-side @mention parsing and tagging
  • [ ] Group activity reports
  • [ ] Group-based conversation filtering in inbox list
  • [ ] Role-based group access control

Did this answer your question?