Skip to content

Commit 09d67ac

Browse files
authored
Merge pull request LordNayan#8 from sparrowapp-dev/board-improvement
feat: Add Board ID filtering to list endpoint and Copy Board ID feature.
2 parents ee4c032 + 0685802 commit 09d67ac

3 files changed

Lines changed: 38 additions & 1 deletion

File tree

apps/api/src/controllers/boards.controller.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { Board, Company, Post } from '../models/index.js';
44
import { asyncHandler, AppError } from '../middlewares/index.js';
55

66
export const listBoards = asyncHandler(async (req: Request, res: Response): Promise<void> => {
7+
const { boardID } = req.body;
8+
79
// Get companyID from authenticated user first, then subdomain/context
810
let companyID: mongoose.Types.ObjectId;
911

@@ -24,9 +26,15 @@ export const listBoards = asyncHandler(async (req: Request, res: Response): Prom
2426
companyID = defaultCompany._id;
2527
}
2628

29+
// Build match query - filter by boardID if provided
30+
const matchQuery: any = { companyID: new mongoose.Types.ObjectId(companyID) };
31+
if (boardID) {
32+
matchQuery._id = new mongoose.Types.ObjectId(boardID);
33+
}
34+
2735
// Get boards with dynamic postCount via aggregation
2836
const boards = await Board.aggregate([
29-
{ $match: { companyID: new mongoose.Types.ObjectId(companyID) } },
37+
{ $match: matchQuery },
3038
{
3139
$lookup: {
3240
from: 'posts',

apps/api/src/middlewares/validate.middleware.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export const cursorPaginationSchema = z.object({
4545
// Board schemas
4646
export const boardListSchema = z.object({
4747
apiKey: z.string().optional(),
48+
boardID: objectIdSchema.optional(),
4849
});
4950

5051
export const boardRetrieveSchema = z.object({

apps/web/src/pages/admin/AdminBoardsPage.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import {
99
TrashIcon,
1010
EyeIcon,
1111
EyeSlashIcon,
12+
ClipboardIcon,
13+
CheckIcon,
1214
} from '@heroicons/react/24/outline';
1315
import toast from 'react-hot-toast';
1416

@@ -20,6 +22,18 @@ export function AdminBoardsPage() {
2022
const [editingBoard, setEditingBoard] = useState<{ id: string; name: string; isPrivate: boolean } | null>(null);
2123
const [newBoard, setNewBoard] = useState<CreateBoardData>({ name: '', isPrivate: false });
2224
const [isSubmitting, setIsSubmitting] = useState(false);
25+
const [copiedBoardId, setCopiedBoardId] = useState<string | null>(null);
26+
27+
const handleCopyBoardId = async (boardId: string) => {
28+
try {
29+
await navigator.clipboard.writeText(boardId);
30+
setCopiedBoardId(boardId);
31+
toast.success('Board ID copied to clipboard!');
32+
setTimeout(() => setCopiedBoardId(null), 2000);
33+
} catch (err) {
34+
toast.error('Failed to copy Board ID');
35+
}
36+
};
2337

2438
useEffect(() => {
2539
fetchBoards();
@@ -181,6 +195,18 @@ export function AdminBoardsPage() {
181195
</td>
182196
<td className="of-px-6 of-py-4 of-whitespace-nowrap of-text-right">
183197
<div className="of-flex of-items-center of-justify-end of-gap-2">
198+
<Button
199+
size="sm"
200+
variant="ghost"
201+
onClick={() => handleCopyBoardId(board.id)}
202+
title="Copy Board ID"
203+
>
204+
{copiedBoardId === board.id ? (
205+
<CheckIcon className="of-w-4 of-h-4 of-text-green-600" />
206+
) : (
207+
<ClipboardIcon className="of-w-4 of-h-4" />
208+
)}
209+
</Button>
184210
<Button
185211
size="sm"
186212
variant="ghost"
@@ -189,6 +215,7 @@ export function AdminBoardsPage() {
189215
name: board.name,
190216
isPrivate: board.isPrivate,
191217
})}
218+
title="Edit Board"
192219
>
193220
<PencilIcon className="of-w-4 of-h-4" />
194221
</Button>
@@ -197,6 +224,7 @@ export function AdminBoardsPage() {
197224
variant="ghost"
198225
onClick={() => handleDelete(board.id, board.name)}
199226
className="of-text-red-600 hover:of-text-red-700"
227+
title="Delete Board"
200228
>
201229
<TrashIcon className="of-w-4 of-h-4" />
202230
</Button>

0 commit comments

Comments
 (0)