Skip to content

Commit

Permalink
🎯 feat/enable bulk span (#4986)
Browse files Browse the repository at this point in the history
  • Loading branch information
damianpumar authored Jun 18, 2024
1 parent 2ad60fb commit 49bfa4b
Show file tree
Hide file tree
Showing 16 changed files with 205 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,35 @@ export default {
type: Array,
},
},
computed: {
searchValue() {
return this.$route.query?._search ?? "";
},
},
methods: {
onSelectedRecord(isSelected) {
this.$emit("on-select-record", isSelected, this.record);
},
},
computed: {
spanQuestionsAnswers() {
return this.record.questions
.filter((q) => q.isSpanType)
.map((q) => ({
id: q.id,
answer: q.answer.values,
}));
},
},
watch: {
spanQuestionsAnswers: {
deep: true,
handler() {
if (
this.record.questions
.filter((q) => q.isSpanType)
.some((q) => q.isModified)
) {
this.onSelectedRecord(true);
}
},
},
},
};
</script>
<style lang="scss" scoped>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<span class="text_field_component__title-content" v-text="title" />
<BaseActionTooltip
class="text_field_component__tooltip"
tooltip="Copied"
tooltip="$t('copied')"
tooltip-position="left"
>
<BaseButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ export class Highlighting {
return [...this.spanSelection.spans];
}

get nodeSpans() {
return this.spans.filter((s) => s.node.id === this.nodeId);
}

private get entitySpanContainer() {
const { spanContainerId } = this.styles;

Expand Down Expand Up @@ -165,7 +169,7 @@ export class Highlighting {
}

private updateLineHeight() {
const maxOverlappedLevels = this.spans.reduce(
const maxOverlappedLevels = this.nodeSpans.reduce(
(max, span) => Math.max(max, span.overlap.level),
0
);
Expand Down Expand Up @@ -335,11 +339,7 @@ export class Highlighting {

this.updateLineHeight();

for (const span of this.spans) {
const { node } = span;

if (node.id !== this.nodeId) continue;

for (const span of this.nodeSpans) {
const entityPosition = this.createPosition(span);

const entityElement = this.EntityComponentConstructor(
Expand Down Expand Up @@ -414,11 +414,7 @@ export class Highlighting {
private removeSpan(span: Span) {
this.spanSelection.removeSpan(span);

const spans = this.spans;

this.removeAllHighlights();

this.loadHighlights(spans);
this.applyStyles();
}

public createRange({ from, to, node }: Span) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,38 @@ describe("Span Selection", () => {

expect(spanSelection.spans).toHaveLength(0);
});

test("should remove span and re calculate the overlapping", () => {
const spanSelection = new SpanSelection();
spanSelection.config.allowOverlap = true;

const textSelection1 = createTextSelection({
from: 10,
to: 17,
text: "rem Ips",
entity: "TOKEN",
});

const textSelection2 = createTextSelection({
from: 8,
to: 19,
text: "Lorem Ipsum",
entity: "TOKEN-2",
});

spanSelection.addSpan(textSelection1);
spanSelection.addSpan(textSelection2);

expect(spanSelection.spans[0].overlap.level).toBe(1);
expect(spanSelection.spans[1].overlap.level).toBe(2);

spanSelection.removeSpan(spanSelection.spans[0]);

expect(spanSelection.spans).toHaveLength(1);
expect(spanSelection.spans[0].from).toBe(textSelection2.from);
expect(spanSelection.spans[0].to).toBe(textSelection2.to);
expect(spanSelection.spans[0].overlap.level).toBe(1);
});
});

describe("should replace the entity for the span", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,16 @@ export class SpanSelection {

this.completeOutOfBoundaries(selected);

const overlaps = this.selections.filter((s) => {
return (
(selected.from <= s.from && selected.to >= s.to) ||
(selected.from >= s.from && selected.to <= s.to) ||
(selected.from < s.from && selected.to > s.from) ||
(selected.from < s.to && selected.to > s.to)
);
});
const overlaps = this.selections
.filter((s) => s.node.id === selected.node.id)
.filter((s) => {
return (
(selected.from <= s.from && selected.to >= s.to) ||
(selected.from >= s.from && selected.to <= s.to) ||
(selected.from < s.from && selected.to > s.from) ||
(selected.from < s.to && selected.to > s.to)
);
});

const maxLevelInOverlaps =
overlaps.reduce((acc, curr) => Math.max(acc, curr.overlap.level), 0) + 1;
Expand Down Expand Up @@ -165,6 +167,18 @@ export class SpanSelection {
}

removeSpan(span: Span) {
this.remove(span);

const nodeSpans = this.spans.filter((s) => s.node.id === span.node.id);

nodeSpans.forEach((span) => {
this.remove(span);
});

this.loadSpans(nodeSpans);
}

private remove(span: Span) {
this.selections = this.selections.filter(
(s) => this.createId(s) !== this.createId(span)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,11 @@ export const useSpanAnnotationTextFieldViewModel = ({
watch(
() => highlighting.value.spans,
(spans) => {
const response = convertSpansToResponse(spans);
const nodeSpans = spans.filter((s) => s.node.id === id);

spanQuestion.response({
value: response,
});
const response = convertSpansToResponse(nodeSpans);

spanQuestion.answer.response({ value: response });
}
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,11 +270,19 @@ export default {
shouldShowModalToConfirm() {
return this.affectAllRecords && this.numberOfSelectedRecords > 100;
},
spansQuestionsWithSelectedEntities() {
return this.record.questions
.filter((q) => q.isSpanType)
.filter((s) => s.answer.options.some((e) => e.isSelected));
},
},
methods: {
onSelectRecord(isSelected, record) {
if (isSelected) {
return this.selectedRecords.push(record);
if (!this.selectedRecords.some((r) => r.id === record.id))
return this.selectedRecords.push(record);
return;
}
this.selectedRecords = this.selectedRecords.filter(
Expand Down Expand Up @@ -369,6 +377,26 @@ export default {
},
},
watch: {
spansQuestionsWithSelectedEntities: {
deep: true,
handler() {
const spanQuestions = this.recordsOnPage
.flatMap((r) => r.questions)
.filter((q) => q.isSpanType);
this.spansQuestionsWithSelectedEntities.forEach((q) => {
spanQuestions.forEach((question) => {
if (question.id === q.id) {
question.answer.options.forEach((option) => {
option.isSelected = q.answer.options.some(
(o) => o.isSelected && o.id === option.id
);
});
}
});
});
},
},
"recordCriteria.status"() {
this.recordCriteria.page.focusMode();
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@
ref="span"
:question="question"
:isFocused="checkIfQuestionIsFocused(index)"
:is-bulk-mode="isBulkMode"
:enableSpanQuestionShortcutsGlobal="enableSpanQuestionShortcutsGlobal"
@on-focus="updateQuestionAutofocus(index)"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<span v-text="warningMessage" />
</div>
<EntityLabelSelectionComponent
v-if="!isBulkMode && supportedSpanAnnotation"
v-if="supportedSpanAnnotation"
v-model="question.answer.options"
:componentId="question.id"
:maxOptionsToShowBeforeCollapse="this.question.settings.visible_options"
Expand Down Expand Up @@ -51,8 +51,6 @@ export default {
warningMessage() {
if (!this.supportedSpanAnnotation) {
return this.$t("spanAnnotation.notSupported");
} else if (this.isBulkMode) {
return this.$t("spanAnnotation.bulkMode");
}
},
},
Expand Down
1 change: 0 additions & 1 deletion argilla-frontend/translation/de.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ export default {
spanAnnotation: {
shortcutHelper: "Halten Sie 'Shift' gedrückt, um Zeichenebene auszuwählen",
notSupported: "Bereichsannotation wird von Ihrem Browser nicht unterstützt",
bulkMode: "Bereichsannotation wird in der Massenansicht nicht unterstützt",
},
login: {
title: "Anmelden",
Expand Down
1 change: 0 additions & 1 deletion argilla-frontend/translation/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ export default {
spanAnnotation: {
shortcutHelper: "Hold 'Shift' to select character level",
notSupported: "Span annotation is not supported for your browser",
bulkMode: "Span annotation is not supported in Bulk view",
},
login: {
title: "Sign in",
Expand Down
17 changes: 17 additions & 0 deletions argilla-frontend/v1/domain/entities/question/Question.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,23 @@ describe("Question", () => {

expect(question.isModified).toBeFalsy();
});

test("isModified is false when the question was loaded with response", () => {
const question = createTextQuestionMocked();

question.response({ value: "positive" });

expect(question.isModified).toBeFalsy();
});

test("isModified is true when the question was loaded with response and modified after initialization", () => {
const question = createTextQuestionMocked();
question.response({ value: "positive" });

question.title = "NEW TITLE";

expect(question.isModified).toBeTruthy();
});
});

describe("question validation should", () => {
Expand Down
Loading

0 comments on commit 49bfa4b

Please sign in to comment.