Skip to content

Commit

Permalink
馃З feat order by suggestion score (#4731)
Browse files Browse the repository at this point in the history
  • Loading branch information
damianpumar committed May 2, 2024
1 parent b35c843 commit 2c1a792
Show file tree
Hide file tree
Showing 10 changed files with 199 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
:componentId="question.id"
:suggestion="question.suggestion"
:maxOptionsToShowBeforeCollapse="question.settings.visible_options"
:suggestionFirst="question.settings.suggestionFirst"
:multiple="true"
:isFocused="isFocused"
v-model="question.answer.values"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ export default {
type: Boolean,
default: () => false,
},
suggestionFirst: {
type: Boolean,
default: () => false,
},
isFocused: {
type: Boolean,
default: () => false,
Expand Down Expand Up @@ -183,11 +187,40 @@ export default {
.filter((option) => option.isSelected);
},
visibleOptions() {
if (this.isExpanded) return this.filteredOptions;
if (!this.suggestionFirst) {
if (this.isExpanded) return this.filteredOptions;
return this.filteredOptions
.slice(0, this.maxOptionsToShowBeforeCollapse)
.concat(this.remainingVisibleOptions);
return this.filteredOptions
.slice(0, this.maxOptionsToShowBeforeCollapse)
.concat(this.remainingVisibleOptions);
}
const suggestedOptions = this.filteredOptions
.filter((v) => this.suggestion && this.suggestion.isSuggested(v.value))
.sort((a, b) => {
const isASuggested = this.suggestion.getSuggestion(a.value);
const isBSuggested = this.suggestion.getSuggestion(b.value);
return isASuggested?.score > isBSuggested?.score ? -1 : 1;
});
const noSuggestedOptions = this.filteredOptions.filter(
(v) => !this.suggestion || !this.suggestion.isSuggested(v.value)
);
if (this.isExpanded) {
return [...suggestedOptions, ...noSuggestedOptions];
}
const options = [
...suggestedOptions.filter((o) => o.isSelected),
...noSuggestedOptions.filter((o) => o.isSelected),
];
return options.slice(
0,
Math.max(options.length, this.maxOptionsToShowBeforeCollapse)
);
},
numberToShowInTheCollapseButton() {
return this.filteredOptions.length - this.visibleOptions.length;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,15 @@
>{{ $t("useMarkdown") }}</BaseSwitch
>

<BaseSwitch
v-if="question.isMultiLabelType"
:id="`options-order-${question.id}`"
v-model="question.settings.suggestionFirst"
>{{ $t("suggestionFirst") }}</BaseSwitch
>

<BaseRangeSlider
v-if="question.settings.options?.length > 3"
v-if="question.settings.shouldShowVisibleOptions"
:id="`visible_options-${question.id}`"
:min="3"
:max="question.settings.options.length"
Expand Down
1 change: 1 addition & 0 deletions frontend/translation/de.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default {
description: "Beschreibung",
labels: "Labels",
useMarkdown: "Verwende Markdown",
suggestionFirst: "Vorschlag zuerst",
visibleForAnnotators: "Sichtbar f眉r Annotatoren",
allowExtraMetadata: "Erlaube extra Metadata",
extraMetadata: "Extra Metadata",
Expand Down
1 change: 1 addition & 0 deletions frontend/translation/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default {
description: "Description",
labels: "Labels",
useMarkdown: "Use Markdown",
suggestionFirst: "Suggestion first",
visibleForAnnotators: "Visible for annotators",
allowExtraMetadata: "Allow extra metadata",
extraMetadata: "Extra metadata",
Expand Down
19 changes: 9 additions & 10 deletions frontend/v1/domain/entities/question/Question.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
RankingQuestionAnswer,
SpanQuestionAnswer,
} from "./QuestionAnswer";
import { QuestionSetting } from "./QuestionSetting";
import { QuestionType } from "./QuestionType";
import { Suggestion } from "./Suggestion";

Expand All @@ -20,6 +21,7 @@ interface OriginalQuestion {
}

export class Question {
public settings: QuestionSetting;
public answer: QuestionAnswer;
public suggestion: Suggestion;
private original: OriginalQuestion;
Expand All @@ -31,10 +33,11 @@ export class Question {
public readonly datasetId: string,
title: string,
public readonly isRequired: boolean,
public settings: any
settings: any
) {
this.description = description;
this.title = title;
this.settings = new QuestionSetting(settings);

this.initialize();
this.initializeAnswers();
Expand Down Expand Up @@ -99,11 +102,7 @@ export class Question {
return (
this.title !== this.original.title ||
this.description !== this.original.description ||
this.settings.use_markdown !== this.original.settings.use_markdown ||
this.settings.visible_options !==
this.original.settings.visible_options ||
JSON.stringify(this.settings.options) !==
JSON.stringify(this.original.settings.options)
!this.settings.isEqual(this.original.settings)
);
}

Expand Down Expand Up @@ -251,19 +250,19 @@ export class Question {
this.original = {
title: this.title,
description: this.description,
settings: {
settings: new QuestionSetting({
...rest,
options: options?.map((option: string) => option),
},
}),
};
}

private restoreOriginal() {
const { options, ...rest } = this.original.settings;

this.settings = {
this.settings = new QuestionSetting({
...rest,
options: options?.map((option: string) => option),
};
});
}
}
2 changes: 1 addition & 1 deletion frontend/v1/domain/entities/question/QuestionAnswer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class SpanQuestionAnswer extends QuestionAnswer {

constructor(
public readonly type: QuestionType,
private questionName: string,
questionName: string,
options: Omit<Option, "isSelected" | "id">[]
) {
super(type);
Expand Down
82 changes: 82 additions & 0 deletions frontend/v1/domain/entities/question/QuestionSetting.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { QuestionSetting } from "./QuestionSetting";

describe("QuestionSetting", () => {
describe("suggestionFirst", () => {
test("return true when options_order is suggestion", () => {
const setting = new QuestionSetting({ options_order: "suggestion" });
expect(setting.suggestionFirst).toBeTruthy();
});
test("return false when options_order is natural", () => {
const setting = new QuestionSetting({ options_order: "natural" });
expect(setting.suggestionFirst).toBeFalsy();
});
});

describe("isEqual", () => {
test("return false when options_order is different", () => {
const setting = new QuestionSetting({ options_order: "suggestion" });
const setting2 = new QuestionSetting({ options_order: "natural" });
expect(setting.isEqual(setting2)).toBeFalsy();
});

test("return false when use_markdown is different", () => {
const setting = new QuestionSetting({ use_markdown: true });
const setting2 = new QuestionSetting({ use_markdown: false });
expect(setting.isEqual(setting2)).toBeFalsy();
});

test("return false when visible_options is different", () => {
const setting = new QuestionSetting({ visible_options: 1 });
const setting2 = new QuestionSetting({ visible_options: 2 });
expect(setting.isEqual(setting2)).toBeFalsy();
});

test("return false when options are different", () => {
const setting = new QuestionSetting({ options: ["a"] });
const setting2 = new QuestionSetting({ options: ["b"] });
expect(setting.isEqual(setting2)).toBeFalsy();
});

test("return false if options are in different positions", () => {
const setting = new QuestionSetting({ options: ["a", "b"] });
const setting2 = new QuestionSetting({ options: ["b", "a"] });
expect(setting.isEqual(setting2)).toBeFalsy();
});

test("return true when all properties are the same", () => {
const setting = new QuestionSetting({
options_order: "suggestion",
use_markdown: true,
visible_options: 1,
options: ["a"],
});
const setting2 = new QuestionSetting({
options_order: "suggestion",
use_markdown: true,
visible_options: 1,
options: ["a"],
});
expect(setting.isEqual(setting2)).toBeTruthy();
});
});

describe("shouldShowVisibleOptions", () => {
test("return false when options are less than 3", () => {
const setting = new QuestionSetting({ options: ["a", "b"] });
expect(setting.shouldShowVisibleOptions).toBeFalsy();
});

test("return false when visible_options is not present", () => {
const setting = new QuestionSetting({ options: ["a", "b", "c"] });
expect(setting.shouldShowVisibleOptions).toBeFalsy();
});

test("return true when options are more than 3 and visible_options is present", () => {
const setting = new QuestionSetting({
options: ["a", "b", "c", "d"],
visible_options: 3,
});
expect(setting.shouldShowVisibleOptions).toBeTruthy();
});
});
});
51 changes: 51 additions & 0 deletions frontend/v1/domain/entities/question/QuestionSetting.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
export class QuestionSetting {
type:
| "text"
| "ranking"
| "multi_label_selection"
| "label_selection"
| "span";

use_markdown: boolean;
visible_options: number;
allow_overlapping: boolean;
allow_character_annotation: boolean;
field: string;
options: any;
options_order: "natural" | "suggestion";

constructor(private readonly settings: any) {
this.type = settings.type;

this.use_markdown = settings.use_markdown;
this.visible_options = settings.visible_options;
this.options = settings.options;
this.options_order = settings.options_order;
this.allow_overlapping = settings.allow_overlapping;
this.allow_character_annotation = settings.allow_character_annotation;
this.field = settings.field;
}

get suggestionFirst() {
if (!this.options_order) return undefined;

return this.options_order === "suggestion";
}

set suggestionFirst(value: boolean) {
this.options_order = value ? "suggestion" : "natural";
}

get shouldShowVisibleOptions() {
return this.options?.length > 3 && "visible_options" in this.settings;
}

isEqual(setting: QuestionSetting) {
return (
this.use_markdown === setting.use_markdown &&
this.visible_options === setting.visible_options &&
this.options_order === setting.options_order &&
JSON.stringify(this.options) === JSON.stringify(setting.options)
);
}
}
20 changes: 8 additions & 12 deletions frontend/v1/infrastructure/types/question.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,16 @@ interface SingleSelectionSetting {
}[];
}

type Entity = {
id: string;
name: string;
color: string;
};
type Span = {
from: string;
to: string;
entity: string;
};
interface SpanSetting {
type: "span";
entities: Entity[];
values: Record<string, Span[]>;
options: {
description?: string;
text: string;
value: string;
}[];
allow_overlapping: boolean;
allow_character_annotation: boolean;
field: string;
}

export interface BackendQuestion {
Expand Down

0 comments on commit 2c1a792

Please sign in to comment.