Skip to content

Commit

Permalink
feat(ToolLabelEditor): warn if label name is not unique
Browse files Browse the repository at this point in the history
Still allows duplicate names if user presses "Done".

New labels are created with unique names suffixed with a number.

New labels loop through the confgi.ts:TOOL_COLORS.
  • Loading branch information
PaulHax committed Feb 22, 2024
1 parent 40f05c0 commit b22383f
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 13 deletions.
17 changes: 16 additions & 1 deletion src/components/LabelControls.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,22 @@ const editingLabel = computed(() => {
return props.labelsStore.labels[editingLabelID.value];
});
const makeUniqueName = (name: string) => {
const existingNames = new Set(
Object.values(props.labelsStore.labels).map((label) => label.labelName)
);
let uniqueName = name;
let i = 1;
while (existingNames.has(uniqueName)) {
uniqueName = `${name} (${i})`;
i++;
}
return uniqueName;
};
const createLabel = () => {
editingLabelID.value = props.labelsStore.addLabel();
const labelName = makeUniqueName('New Label');
editingLabelID.value = props.labelsStore.addLabel({ labelName });
};
function startEditing(label: LabelID) {
Expand Down Expand Up @@ -114,6 +128,7 @@ function deleteEditingLabel() {
@delete="deleteEditingLabel"
@cancel="stopEditing(false)"
@done="stopEditing(true)"
:labelsStore="labelsStore"
/>
</isolated-dialog>
</template>
Expand Down
30 changes: 25 additions & 5 deletions src/components/ToolLabelEditor.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<script setup lang="ts">
import { computed } from 'vue';
import LabelEditor from '@/src/components/LabelEditor.vue';
import type { LabelsStore } from '../store/tools/useLabels';
import type { AnnotationTool } from '../types/annotation-tool';
defineEmits([
'done',
Expand All @@ -10,11 +13,27 @@ defineEmits([
'update:color',
]);
defineProps({
name: String,
strokeWidth: Number,
color: String,
});
const props = defineProps<{
name: string;
strokeWidth: number;
color: string;
labelsStore: LabelsStore<Pick<AnnotationTool, 'strokeWidth'>>;
}>();
const existingNames = computed(
() =>
new Set(
Object.values(props.labelsStore.labels).map((label) => label.labelName)
)
);
function isUniqueEditingName(name: string) {
return !existingNames.value.has(name);
}
function uniqueNameRule(name: string) {
return isUniqueEditingName(name) || 'Name is not unique';
}
</script>

<template>
Expand All @@ -37,6 +56,7 @@ defineProps({
:model-value="name"
@update:model-value="$emit('update:name', $event)"
@keydown.stop.enter="done"
:rules="[uniqueNameRule]"
/>
<v-text-field
label="Stroke Width"
Expand Down
10 changes: 5 additions & 5 deletions src/io/import/configJson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ const applyLabels = (manifest: Config) => {
};

const applyLabelsToStore = (
maybeLabels: (typeof manifest.labels)[keyof typeof manifest.labels],
store: AnnotationToolStore
store: AnnotationToolStore,
maybeLabels: (typeof manifest.labels)[keyof typeof manifest.labels]
) => {
const labelsOrFallback = defaultLabelsIfUndefined(maybeLabels);
if (!labelsOrFallback) return;
Expand All @@ -99,9 +99,9 @@ const applyLabels = (manifest: Config) => {
};

const { rulerLabels, rectangleLabels, polygonLabels } = manifest.labels;
applyLabelsToStore(rulerLabels, useRulerStore());
applyLabelsToStore(rectangleLabels, useRectangleStore());
applyLabelsToStore(polygonLabels, usePolygonStore());
applyLabelsToStore(useRulerStore(), rulerLabels);
applyLabelsToStore(useRectangleStore(), rectangleLabels);
applyLabelsToStore(usePolygonStore(), polygonLabels);
};

const applySampleData = (manifest: Config) => {
Expand Down
9 changes: 7 additions & 2 deletions src/store/tools/useLabels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,19 @@ export const useLabels = <Props>(newLabelDefault: Props) => {
activeLabel.value = id;
};

let nextToolColorIndex = 0;

const addLabel = (label: ToolLabel = {}) => {
const id = useIdStore().nextId();
labels.value[id] = {
...labelDefault,
...newLabelDefault,
color: TOOL_COLORS[nextToolColorIndex],
...label,
};

nextToolColorIndex = (nextToolColorIndex + 1) % TOOL_COLORS.length;

setActiveLabel(id);
return id;
};
Expand Down Expand Up @@ -74,7 +79,7 @@ export const useLabels = <Props>(newLabelDefault: Props) => {
};

/*
* If new label have the same name as existing label, overwrite existing label.
* If input label has the same name as existing label, update existing label with input label properties.
*
* param label: label to merge
* param clearDefault: if true, clear initial labels, do nothing if initial labels already cleared
Expand All @@ -93,7 +98,7 @@ export const useLabels = <Props>(newLabelDefault: Props) => {
};

/*
* If new label have the same name as existing label, overwrite existing label.
* If input label has the same name as existing label, update existing label with input label properties.
*
* param newLabels: each key is the label name
* param clearDefault: if true, clear initial labels, do nothing if initial labels already cleared
Expand Down

0 comments on commit b22383f

Please sign in to comment.