From 9b1658ab6ab1be2b8aba28359efb447569f8cd20 Mon Sep 17 00:00:00 2001 From: Steven Fitzpatrick Date: Sun, 25 Jan 2026 19:44:34 +0000 Subject: [PATCH 1/3] feat: click to edit, ctrl+click to delete --- ui/src/common/TagChip.tsx | 2 +- ui/src/dashboard/Entry/DashboardEntryForm.tsx | 1 - ui/src/tag/TagSelector.tsx | 27 ++++++++++++------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/ui/src/common/TagChip.tsx b/ui/src/common/TagChip.tsx index 0134f4aa..66f12392 100644 --- a/ui/src/common/TagChip.tsx +++ b/ui/src/common/TagChip.tsx @@ -18,7 +18,7 @@ const useStyles = makeStyles((theme: Theme) => ({ interface TagChipProps { label: string; color: string; - onClick?: () => void; + onClick?: (e: React.MouseEvent) => void; } export const TagChip: React.FC = ({color, label, onClick}) => { diff --git a/ui/src/dashboard/Entry/DashboardEntryForm.tsx b/ui/src/dashboard/Entry/DashboardEntryForm.tsx index 8fcde629..19d3f2e6 100644 --- a/ui/src/dashboard/Entry/DashboardEntryForm.tsx +++ b/ui/src/dashboard/Entry/DashboardEntryForm.tsx @@ -206,7 +206,6 @@ export const DashboardEntryForm: React.FC = ({entry, onChange: s }} createTags={false} onlySelectKeys - removeWhenClicked /> = ({ @@ -48,7 +47,6 @@ export const TagSelector: React.FC = ({ createTags = true, allowDuplicateKeys = false, onlySelectKeys = false, - removeWhenClicked = false, }) => { const classes = useStyles(); const [tooltipErrorActive, tooltipError, showTooltipError] = useError(4000); @@ -127,14 +125,21 @@ export const TagSelector: React.FC = ({ return; }; - const onTagClicked = (entry: TagSelectorEntry) => { - if (!removeWhenClicked) { + const onTagClicked = (entry: TagSelectorEntry, edit: boolean) => { + // Prevent overwriting text that's already being edited + if (currentValue && edit) { + showTooltipError('Input is not empty. Use ctrl+click to delete tag without editing.'); return; } - const tagIndex = selectedEntries.indexOf(entry); - selectedEntries.splice(tagIndex, 1); - setSelectedEntries(selectedEntries); + setSelectedEntries(selectedEntries.filter((selected) => selected !== entry)); + + if (edit) { + setCurrentValueInternal(itemLabel(entry, onlySelectKeys)); + setOpen(true); + } + + focusInput(); }; const onKeyDown = (event: React.KeyboardEvent) => { @@ -254,13 +259,17 @@ const Item: React.FC = ({entry, selected, onlySelectKeys, onClick}) = ); }; -const toChips = (entries: TagSelectorEntry[], onlySelectKeys: boolean, onClick: (entry: TagSelectorEntry) => void) => { +const toChips = ( + entries: TagSelectorEntry[], + onlySelectKeys: boolean, + onClick: (entry: TagSelectorEntry, edit: boolean) => void +) => { return entries.map((entry) => ( onClick(entry)} + onClick={(e) => onClick(entry, !e.ctrlKey)} /> )); }; From f7006dbe975b68f65a0834e606393cb440840c3e Mon Sep 17 00:00:00 2001 From: Steven Fitzpatrick Date: Sun, 25 Jan 2026 20:09:23 +0000 Subject: [PATCH 2/3] fix: preserve value part when creating a new tag --- ui/src/tag/TagSelector.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ui/src/tag/TagSelector.tsx b/ui/src/tag/TagSelector.tsx index 977a3d9c..ac70b5f2 100644 --- a/ui/src/tag/TagSelector.tsx +++ b/ui/src/tag/TagSelector.tsx @@ -222,7 +222,10 @@ export const TagSelector: React.FC = ({ ) : null} {addDialogOpen && ( trySubmit({tag, value: ''})} + onAdded={(tag) => { + const valuePart = currentValue.split(':')[1] || ''; + trySubmit({tag, value: valuePart}); + }} open={true} initialName={currentValue.split(':')[0]} close={() => { From 442acc195bf3b68511614f2192d0db5796f3e785 Mon Sep 17 00:00:00 2001 From: Jannis Mattheis Date: Sun, 1 Feb 2026 12:06:52 +0100 Subject: [PATCH 3/3] fix: show tag selector errors in dashboard entry edit dialog --- ui/src/tag/TagSelector.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/src/tag/TagSelector.tsx b/ui/src/tag/TagSelector.tsx index ac70b5f2..dda8fc65 100644 --- a/ui/src/tag/TagSelector.tsx +++ b/ui/src/tag/TagSelector.tsx @@ -182,6 +182,7 @@ export const TagSelector: React.FC = ({ disableHoverListener disableTouchListener open={tooltipErrorActive} + PopperProps={{style: {zIndex: 100000}}} placement={'top'} title={