Skip to content

Commit 980ed74

Browse files
committed
Advanced Tags Management
1 parent 4a837c0 commit 980ed74

4 files changed

Lines changed: 89 additions & 68 deletions

File tree

frontend/src/App.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
/* width */
6363
::-webkit-scrollbar {
6464
height: 2px;
65-
width: 10px;
65+
width: 6px;
6666
}
6767

6868
/* Track */

frontend/src/components/HomeComponents/Tasks/AddTaskDialog.tsx

Lines changed: 84 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,36 @@ export const AddTaskdialog = ({
385385
setNewTask({ ...newTask, tags })
386386
}
387387
placeholder="Select or create tags..."
388+
hideSelectedDisplay
388389
/>
389390
</div>
391+
{newTask.tags.length > 0 && (
392+
<div className="flex flex-wrap gap-2 p-3 bg-background rounded-lg border min-h-[60px]">
393+
{newTask.tags.map((tag) => (
394+
<Badge
395+
key={tag}
396+
variant="secondary"
397+
className="h-auto py-2 px-3 text-sm bg-blue-500/10 text-blue-700 dark:text-blue-300 hover:bg-blue-500/20"
398+
>
399+
<TagIcon className="h-3 w-3 mr-1 flex-shrink-0" />
400+
<span className="max-w-[200px] truncate">{tag}</span>
401+
<button
402+
type="button"
403+
className="ml-2 text-red-500 hover:text-red-700 flex-shrink-0"
404+
aria-label={`Remove tag ${tag}`}
405+
onClick={() =>
406+
setNewTask({
407+
...newTask,
408+
tags: newTask.tags.filter((t) => t !== tag),
409+
})
410+
}
411+
>
412+
413+
</button>
414+
</Badge>
415+
))}
416+
</div>
417+
)}
390418
</div>
391419
</section>
392420

@@ -422,32 +450,27 @@ export const AddTaskdialog = ({
422450
/>
423451
</div>
424452
{newTask.annotations.length > 0 && (
425-
<div className="space-y-2">
426-
<p className="text-sm text-muted-foreground">
427-
Added annotations:
428-
</p>
429-
<div className="flex flex-wrap gap-2 p-3 bg-background rounded-lg border min-h-[60px]">
430-
{newTask.annotations.map((annotation, index) => (
431-
<Badge
432-
key={index}
433-
variant="secondary"
434-
className="h-auto py-2 px-3 text-sm bg-green-500/10 text-green-700 dark:text-green-300 hover:bg-green-500/20"
453+
<div className="flex flex-wrap gap-2 p-3 bg-background rounded-lg border min-h-[60px]">
454+
{newTask.annotations.map((annotation, index) => (
455+
<Badge
456+
key={index}
457+
variant="secondary"
458+
className="h-auto py-2 px-3 text-sm bg-green-500/10 text-green-700 dark:text-green-300 hover:bg-green-500/20"
459+
>
460+
<FileText className="h-3 w-3 mr-1 flex-shrink-0" />
461+
<span className="max-w-[200px] truncate">
462+
{annotation.description}
463+
</span>
464+
<button
465+
type="button"
466+
className="ml-2 text-red-500 hover:text-red-700 flex-shrink-0"
467+
aria-label="remove annotation"
468+
onClick={() => handleRemoveAnnotation(annotation)}
435469
>
436-
<FileText className="h-3 w-3 mr-1 flex-shrink-0" />
437-
<span className="max-w-[200px] truncate">
438-
{annotation.description}
439-
</span>
440-
<button
441-
type="button"
442-
className="ml-2 text-red-500 hover:text-red-700 flex-shrink-0"
443-
aria-label="remove annotation"
444-
onClick={() => handleRemoveAnnotation(annotation)}
445-
>
446-
447-
</button>
448-
</Badge>
449-
))}
450-
</div>
470+
471+
</button>
472+
</Badge>
473+
))}
451474
</div>
452475
)}
453476
</div>
@@ -535,48 +558,43 @@ export const AddTaskdialog = ({
535558

536559
{/* Display selected dependencies */}
537560
{newTask.depends.length > 0 && (
538-
<div className="space-y-2">
539-
<p className="text-sm text-muted-foreground">
540-
Selected dependencies:
541-
</p>
542-
<div className="flex flex-wrap gap-2 p-3 bg-background rounded-lg border min-h-[60px]">
543-
{newTask.depends.map((taskUuid) => {
544-
const dependentTask = allTasks.find(
545-
(t) => t.uuid === taskUuid
546-
);
547-
return (
548-
<Badge
549-
key={taskUuid}
550-
variant="secondary"
551-
className="h-auto py-2 px-3 text-sm bg-purple-500/10 text-purple-700 dark:text-purple-300 hover:bg-purple-500/20"
561+
<div className="flex flex-wrap gap-2 p-3 bg-background rounded-lg border min-h-[60px]">
562+
{newTask.depends.map((taskUuid) => {
563+
const dependentTask = allTasks.find(
564+
(t) => t.uuid === taskUuid
565+
);
566+
return (
567+
<Badge
568+
key={taskUuid}
569+
variant="secondary"
570+
className="h-auto py-2 px-3 text-sm bg-purple-500/10 text-purple-700 dark:text-purple-300 hover:bg-purple-500/20"
571+
>
572+
<Link2 className="h-3 w-3 mr-1 flex-shrink-0" />
573+
<span className="max-w-[200px] truncate">
574+
#{dependentTask?.id || '?'}{' '}
575+
{dependentTask?.description?.substring(0, 20) ||
576+
taskUuid.substring(0, 8)}
577+
{dependentTask?.description &&
578+
dependentTask.description.length > 20 &&
579+
'...'}
580+
</span>
581+
<button
582+
type="button"
583+
className="ml-2 text-red-500 hover:text-red-700 flex-shrink-0"
584+
onClick={() => {
585+
setNewTask({
586+
...newTask,
587+
depends: newTask.depends.filter(
588+
(d) => d !== taskUuid
589+
),
590+
});
591+
}}
552592
>
553-
<Link2 className="h-3 w-3 mr-1 flex-shrink-0" />
554-
<span className="max-w-[200px] truncate">
555-
#{dependentTask?.id || '?'}{' '}
556-
{dependentTask?.description?.substring(0, 20) ||
557-
taskUuid.substring(0, 8)}
558-
{dependentTask?.description &&
559-
dependentTask.description.length > 20 &&
560-
'...'}
561-
</span>
562-
<button
563-
type="button"
564-
className="ml-2 text-red-500 hover:text-red-700 flex-shrink-0"
565-
onClick={() => {
566-
setNewTask({
567-
...newTask,
568-
depends: newTask.depends.filter(
569-
(d) => d !== taskUuid
570-
),
571-
});
572-
}}
573-
>
574-
575-
</button>
576-
</Badge>
577-
);
578-
})}
579-
</div>
593+
594+
</button>
595+
</Badge>
596+
);
597+
})}
580598
</div>
581599
)}
582600
</div>

frontend/src/components/HomeComponents/Tasks/MultiSelect.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export const MultiSelect = React.forwardRef<
2121
showActions = false,
2222
onSave,
2323
onCancel,
24+
hideSelectedDisplay = false,
2425
},
2526
ref
2627
) => {
@@ -115,7 +116,7 @@ export const MultiSelect = React.forwardRef<
115116
<ChevronDown className="h-4 w-4 opacity-50" />
116117
</Button>
117118

118-
{selectedItems.length > 0 && (
119+
{selectedItems.length > 0 && !hideSelectedDisplay && (
119120
<div className="flex flex-wrap items-center gap-2 mt-2">
120121
{selectedItems.map((item) => (
121122
<Badge key={item} className="flex items-center gap-1">

frontend/src/components/utils/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ export interface MultiSelectProps {
141141
showActions?: boolean;
142142
onSave?: () => void;
143143
onCancel?: () => void;
144+
/** When true, selected items are not shown inside the MultiSelect (e.g. when rendered elsewhere). */
145+
hideSelectedDisplay?: boolean;
144146
}
145147

146148
export interface EditTaskDialogProps {

0 commit comments

Comments
 (0)