From f9ab91042877732a0f64f29bbbfdb2f595b14199 Mon Sep 17 00:00:00 2001 From: Leire Date: Mon, 18 Nov 2024 11:26:01 +0100 Subject: [PATCH 1/4] [BUGFIX] Show `Import data` if user is admin or owner (#5688) FIx #5686 --- argilla-frontend/pages/dataset/_id/annotation-mode/index.vue | 1 + .../dataset/_id/annotation-mode/useAnnotationModeViewModel.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/argilla-frontend/pages/dataset/_id/annotation-mode/index.vue b/argilla-frontend/pages/dataset/_id/annotation-mode/index.vue index 234eb24306..31f4a01987 100644 --- a/argilla-frontend/pages/dataset/_id/annotation-mode/index.vue +++ b/argilla-frontend/pages/dataset/_id/annotation-mode/index.vue @@ -12,6 +12,7 @@ > diff --git a/argilla-frontend/pages/dataset/_id/annotation-mode/useAnnotationModeViewModel.ts b/argilla-frontend/pages/dataset/_id/annotation-mode/useAnnotationModeViewModel.ts index 087c758267..f553303113 100644 --- a/argilla-frontend/pages/dataset/_id/annotation-mode/useAnnotationModeViewModel.ts +++ b/argilla-frontend/pages/dataset/_id/annotation-mode/useAnnotationModeViewModel.ts @@ -9,10 +9,11 @@ import { useDatasetViewModel } from "../useDatasetViewModel"; import { GetDatasetByIdUseCase } from "@/v1/domain/usecases/get-dataset-by-id-use-case"; import { useDataset } from "@/v1/infrastructure/storage/DatasetStorage"; import { RecordCriteria } from "~/v1/domain/entities/record/RecordCriteria"; -import { useRoutes, useUser } from "~/v1/infrastructure/services"; +import { useRoutes, useUser, useRole } from "~/v1/infrastructure/services"; import { RecordStatus } from "~/v1/domain/entities/record/RecordAnswer"; export const useAnnotationModeViewModel = () => { + const { isAdminOrOwner } = useRole(); const router = useRouter(); const routes = useRoutes(); const { getUser } = useUser(); @@ -113,5 +114,6 @@ export const useAnnotationModeViewModel = () => { breadcrumbs, updateQueryParams, getUser, + isAdminOrOwner, }; }; From 91ed8caf48e42ab9af5c9f00df542c38aaba8f70 Mon Sep 17 00:00:00 2001 From: Paco Aranda Date: Mon, 18 Nov 2024 15:09:58 +0100 Subject: [PATCH 2/4] [REFACTOR] `argilla server`: Remove passlib dependency (#5674) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Closes https://github.com/argilla-io/argilla/issues/5664 **Type of change** - Improvement (change adding some improvement to an existing functionality) **How Has This Been Tested** **Checklist** - I added relevant documentation - I followed the style guidelines of this project - I did a self-review of my code - I made corresponding changes to the documentation - I confirm My changes generate no new warnings - I have added tests that prove my fix is effective or that my feature works - I have added relevant notes to the CHANGELOG.md file (See https://keepachangelog.com/) --------- Co-authored-by: José Francisco Calvo Co-authored-by: José Francisco Calvo Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- argilla-server/pdm.lock | 27 +--------------- argilla-server/pyproject.toml | 2 +- .../src/argilla_server/contexts/accounts.py | 32 +++++++++++++------ 3 files changed, 24 insertions(+), 37 deletions(-) diff --git a/argilla-server/pdm.lock b/argilla-server/pdm.lock index b8534d410d..afbb0afb5f 100644 --- a/argilla-server/pdm.lock +++ b/argilla-server/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "postgresql", "test"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:43263bc708af6895a1834c1a3826349b82a643e70dae41abf99d8b6bff2d454e" +content_hash = "sha256:bac5d1141affbb735ae70537eb0534eb8dabf287bd33af762ac7bd877073d282" [[metadata.targets]] requires_python = ">=3.9" @@ -1666,31 +1666,6 @@ files = [ {file = "pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667"}, ] -[[package]] -name = "passlib" -version = "1.7.4" -summary = "comprehensive password hashing framework supporting over 30 schemes" -groups = ["default"] -files = [ - {file = "passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1"}, - {file = "passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"}, -] - -[[package]] -name = "passlib" -version = "1.7.4" -extras = ["bcrypt"] -summary = "comprehensive password hashing framework supporting over 30 schemes" -groups = ["default"] -dependencies = [ - "bcrypt>=3.1.0", - "passlib==1.7.4", -] -files = [ - {file = "passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1"}, - {file = "passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"}, -] - [[package]] name = "pillow" version = "11.0.0" diff --git a/argilla-server/pyproject.toml b/argilla-server/pyproject.toml index 616e369b95..4a43fdc0c6 100644 --- a/argilla-server/pyproject.toml +++ b/argilla-server/pyproject.toml @@ -39,7 +39,7 @@ dependencies = [ "PyYAML >= 5.4.1,< 6.1.0", # security dependencies "python-jose[cryptography] ~= 3.3.0", - "passlib[bcrypt] ~= 1.7.4", + "bcrypt ~= 4.2.0", # required by fastapi "python-multipart ~= 0.0.16", # OAuth2 integration diff --git a/argilla-server/src/argilla_server/contexts/accounts.py b/argilla-server/src/argilla_server/contexts/accounts.py index 01aa1fa8d5..0b65bdc815 100644 --- a/argilla-server/src/argilla_server/contexts/accounts.py +++ b/argilla-server/src/argilla_server/contexts/accounts.py @@ -15,7 +15,7 @@ from typing import Iterable, List, Sequence, Union from uuid import UUID -from passlib.context import CryptContext +import bcrypt from sqlalchemy import exists, select from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload @@ -27,8 +27,6 @@ from argilla_server.security.authentication.jwt import JWT from argilla_server.security.authentication.userinfo import UserInfo -_CRYPT_CONTEXT = CryptContext(schemes=["bcrypt"], deprecated="auto") - async def create_workspace_user(db: AsyncSession, workspace_user_attrs: dict) -> WorkspaceUser: workspace_id = workspace_user_attrs["workspace_id"] @@ -168,19 +166,21 @@ async def authenticate_user(db: AsyncSession, username: str, password: str): elif user: return else: - _CRYPT_CONTEXT.dummy_verify() + _dummy_verify() def hash_password(password: str) -> str: - return _CRYPT_CONTEXT.hash(password) + return bcrypt.hashpw( + bytes(password, encoding="utf-8"), + bcrypt.gensalt(), + ).decode("utf-8") def verify_password(password: str, password_hash: str) -> bool: - return _CRYPT_CONTEXT.verify(password, password_hash) - - -def _generate_random_password() -> str: - return secrets.token_urlsafe() + return bcrypt.checkpw( + bytes(password, encoding="utf-8"), + bytes(password_hash, encoding="utf-8"), + ) def generate_user_token(user: User) -> str: @@ -192,3 +192,15 @@ def generate_user_token(user: User) -> str: role=user.role, ), ) + + +_DUMMY_SECRET = "dummy_secret" +_DUMMY_HASH = hash_password(_DUMMY_SECRET) + + +def _dummy_verify(): + verify_password(_DUMMY_SECRET, _DUMMY_HASH) + + +def _generate_random_password() -> str: + return secrets.token_urlsafe() From a9bf3df6c2aebff6cb28ed1240376a0279aae74a Mon Sep 17 00:00:00 2001 From: Leire Date: Tue, 19 Nov 2024 11:52:36 +0100 Subject: [PATCH 3/4] [FEATURE] UI - Add language selection in user settings (#5690) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix #5659 --------- Co-authored-by: Damián Pumar --- argilla-frontend/CHANGELOG.md | 1 + .../user-settings/UserSettingsContent.vue | 13 +++- .../user-settings/UserSettingsLanguage.vue | 62 +++++++++++++++++++ .../user-settings/UserSettingsTheme.vue | 4 +- .../useUserSettingsLanguageViewModel.ts | 12 ++++ argilla-frontend/nuxt.config.ts | 3 + argilla-frontend/translation/de.js | 7 +++ argilla-frontend/translation/en.js | 9 ++- argilla-frontend/translation/es.js | 8 +++ .../infrastructure/services/useColorSchema.ts | 7 ++- .../services/useLanguageDetector.test.ts | 47 +++++++++++--- .../services/useLanguageDetector.ts | 29 +++++++-- .../services/useLocalStorage.ts | 7 ++- 13 files changed, 188 insertions(+), 21 deletions(-) create mode 100644 argilla-frontend/components/features/user-settings/UserSettingsLanguage.vue create mode 100644 argilla-frontend/components/features/user-settings/useUserSettingsLanguageViewModel.ts diff --git a/argilla-frontend/CHANGELOG.md b/argilla-frontend/CHANGELOG.md index bd555a2b88..e6f5aad8e0 100644 --- a/argilla-frontend/CHANGELOG.md +++ b/argilla-frontend/CHANGELOG.md @@ -19,6 +19,7 @@ These are the section headers that we use: ### Added - Add a high-contrast theme & improvements for the forced-colors mode. ([#5661](https://github.com/argilla-io/argilla/pull/5661)) +- Add English as the default language and add language selector in the user settings page. ([#5690](https://github.com/argilla-io/argilla/pull/5690)) ## [2.4.1](https://github.com/argilla-io/argilla/compare/v2.4.0...v2.4.1) diff --git a/argilla-frontend/components/features/user-settings/UserSettingsContent.vue b/argilla-frontend/components/features/user-settings/UserSettingsContent.vue index 78c1261ee1..424cd25f27 100644 --- a/argilla-frontend/components/features/user-settings/UserSettingsContent.vue +++ b/argilla-frontend/components/features/user-settings/UserSettingsContent.vue @@ -47,9 +47,6 @@

-

-
- -

+
+

+ +

+
+ +
diff --git a/argilla-frontend/components/features/user-settings/UserSettingsLanguage.vue b/argilla-frontend/components/features/user-settings/UserSettingsLanguage.vue new file mode 100644 index 0000000000..5d175e260b --- /dev/null +++ b/argilla-frontend/components/features/user-settings/UserSettingsLanguage.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/argilla-frontend/components/features/user-settings/UserSettingsTheme.vue b/argilla-frontend/components/features/user-settings/UserSettingsTheme.vue index b1eddbd0a8..0c29ffe7c8 100644 --- a/argilla-frontend/components/features/user-settings/UserSettingsTheme.vue +++ b/argilla-frontend/components/features/user-settings/UserSettingsTheme.vue @@ -14,7 +14,7 @@ /> @@ -25,8 +25,8 @@ import "assets/icons/light-theme"; import "assets/icons/dark-theme"; import "assets/icons/system-theme"; import "assets/icons/high-contrast-theme"; + export default { - name: "ThemeSwitch", data() { return { themes: ["system", "dark", "light", "high-contrast"], diff --git a/argilla-frontend/components/features/user-settings/useUserSettingsLanguageViewModel.ts b/argilla-frontend/components/features/user-settings/useUserSettingsLanguageViewModel.ts new file mode 100644 index 0000000000..30e71e8f32 --- /dev/null +++ b/argilla-frontend/components/features/user-settings/useUserSettingsLanguageViewModel.ts @@ -0,0 +1,12 @@ +import { useContext } from "@nuxtjs/composition-api"; +import { useLanguageChanger } from "~/v1/infrastructure/services"; + +export const useUserSettingsLanguageViewModel = () => { + const context = useContext(); + const { change, languages } = useLanguageChanger(context); + + return { + change, + languages, + }; +}; diff --git a/argilla-frontend/nuxt.config.ts b/argilla-frontend/nuxt.config.ts index 8375d73a82..96a0cfa20c 100644 --- a/argilla-frontend/nuxt.config.ts +++ b/argilla-frontend/nuxt.config.ts @@ -115,14 +115,17 @@ const config: NuxtConfig = { locales: [ { code: "en", + name: "English", file: "en.js", }, { code: "de", + name: "Deutsch", file: "de.js", }, { code: "es", + name: "Español", file: "es.js", }, ], diff --git a/argilla-frontend/translation/de.js b/argilla-frontend/translation/de.js index 6e0810d89a..8226fa127d 100644 --- a/argilla-frontend/translation/de.js +++ b/argilla-frontend/translation/de.js @@ -88,6 +88,7 @@ export default { apiKeyDescription: "API-Keys erlauben es die Datensätze über das Python SDK zu verwalten.", theme: "Theme", + language: "Sprache", copyKey: "API-Key kopieren", }, userAvatarTooltip: { @@ -341,6 +342,12 @@ export default { annotator: "Der persistente Speicher ist nicht aktiviert. Alle Daten gehen verloren, wenn dieser Space neu gestartet wird.", }, + colorSchema: { + system: "System", + light: "Licht", + dark: "Dunkel", + "high-contrast": "Hoher Kontrast", + }, validations: { businessLogic: { missing_vector: { diff --git a/argilla-frontend/translation/en.js b/argilla-frontend/translation/en.js index 009525c13c..448064600b 100644 --- a/argilla-frontend/translation/en.js +++ b/argilla-frontend/translation/en.js @@ -58,7 +58,7 @@ export default { breadcrumbs: { home: "Home", datasetSettings: "settings", - userSettings: "my settings", + userSettings: "My settings", }, datasets: { left: "left", @@ -86,6 +86,7 @@ export default { apiKeyDescription: "API key tokens allow you to manage datasets using the Python SDK.", theme: "Theme", + language: "Language", copyKey: "Copy key", }, userAvatarTooltip: { @@ -345,6 +346,12 @@ export default { annotator: "Persistent storage is not enabled. All data will be lost if this space restarts.", }, + colorSchema: { + system: "System", + light: "Light", + dark: "Dark", + "high-contrast": "High contrast", + }, validations: { businessLogic: { missing_vector: { diff --git a/argilla-frontend/translation/es.js b/argilla-frontend/translation/es.js index ed40c9396e..3bc4d8c922 100644 --- a/argilla-frontend/translation/es.js +++ b/argilla-frontend/translation/es.js @@ -84,6 +84,8 @@ export default { apiKey: "Clave de API", apiKeyDescription: "Los tokens de clave API permiten administrar datasets utilizando el SDK de Python", + theme: "Tema", + language: "Idioma", copyKey: "Copiar clave", }, userAvatarTooltip: { @@ -335,6 +337,12 @@ export default { annotator: "El almacenamiento persistente no está habilitado. Todos los datos se perderán si este espacio se reinicia", }, + colorSchema: { + system: "Sistema", + light: "Claro", + dark: "Oscuro", + "high-contrast": "Alto contraste", + }, validations: { businessLogic: { missing_vector: { diff --git a/argilla-frontend/v1/infrastructure/services/useColorSchema.ts b/argilla-frontend/v1/infrastructure/services/useColorSchema.ts index 0357ca861a..2b5d57cb72 100644 --- a/argilla-frontend/v1/infrastructure/services/useColorSchema.ts +++ b/argilla-frontend/v1/infrastructure/services/useColorSchema.ts @@ -1,14 +1,17 @@ import { ref } from "vue"; +import { useLocalStorage } from "./useLocalStorage"; export const useColorSchema = () => { + const { get, set } = useLocalStorage(); const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; - const currentTheme = ref(localStorage.getItem("theme") || "system"); + const currentTheme = ref(get("theme") || "system"); const setTheme = (theme: string) => { currentTheme.value = theme; - localStorage.setItem("theme", theme); + set("theme", theme); + if (theme !== "system") { document.documentElement.setAttribute("data-theme", theme); } else { diff --git a/argilla-frontend/v1/infrastructure/services/useLanguageDetector.test.ts b/argilla-frontend/v1/infrastructure/services/useLanguageDetector.test.ts index 3bfe47cf24..de6318a0ca 100644 --- a/argilla-frontend/v1/infrastructure/services/useLanguageDetector.test.ts +++ b/argilla-frontend/v1/infrastructure/services/useLanguageDetector.test.ts @@ -1,10 +1,14 @@ import { useLanguageDetector } from "./useLanguageDetector"; +import { useLocalStorage } from "./useLocalStorage"; + +jest.mock("./useLocalStorage"); +const useLocalStorageMock = jest.mocked(useLocalStorage); describe("useLanguageDetector", () => { const context = { app: { i18n: { - locales: [{ code: "en" }, { code: "es" }, { code: "fr-CA" }], + locales: [{ code: "en" }, { code: "es" }, { code: "fr" }], setLocale: jest.fn(), }, }, @@ -15,24 +19,34 @@ describe("useLanguageDetector", () => { }); describe("initialize should", () => { - test("change to the detected language when it exists", () => { + test("set the browser language if the user does not have the language saved and the browser language is supported", () => { Object.defineProperty(window.navigator, "language", { - value: "fr-CA", + value: "es", configurable: true, }); + useLocalStorageMock.mockReturnValue({ + get: jest.fn().mockReturnValue(null), + pop: jest.fn(), + set: jest.fn(), + }); const { initialize } = useLanguageDetector(context); initialize(); - expect(context.app.i18n.setLocale).toHaveBeenCalledWith("fr-CA"); + expect(context.app.i18n.setLocale).toHaveBeenCalledWith("es"); }); - test("change to base language code if not exist the complete code into locales", () => { + test("set the browser language if the user does not have the language saved and the browser language is supported", () => { Object.defineProperty(window.navigator, "language", { value: "es-AR", configurable: true, }); + useLocalStorageMock.mockReturnValue({ + get: jest.fn().mockReturnValue(null), + pop: jest.fn(), + set: jest.fn(), + }); const { initialize } = useLanguageDetector(context); @@ -41,17 +55,36 @@ describe("useLanguageDetector", () => { expect(context.app.i18n.setLocale).toHaveBeenCalledWith("es"); }); - test("not change to the language code when the detected language does not exist", () => { + test("set English if the user does not have the language saved and the browser language is not supported", () => { Object.defineProperty(window.navigator, "language", { value: "de", configurable: true, }); + useLocalStorageMock.mockReturnValue({ + get: jest.fn().mockReturnValue(null), + pop: jest.fn(), + set: jest.fn(), + }); + + const { initialize } = useLanguageDetector(context); + + initialize(); + + expect(context.app.i18n.setLocale).toHaveBeenCalledWith("en"); + }); + + test("set the language saved by the user", () => { + useLocalStorageMock.mockReturnValue({ + get: () => "fr", + pop: jest.fn(), + set: jest.fn(), + }); const { initialize } = useLanguageDetector(context); initialize(); - expect(context.app.i18n.setLocale).toHaveBeenCalledTimes(0); + expect(context.app.i18n.setLocale).toHaveBeenCalledWith("fr"); }); }); }); diff --git a/argilla-frontend/v1/infrastructure/services/useLanguageDetector.ts b/argilla-frontend/v1/infrastructure/services/useLanguageDetector.ts index c2da119991..8482ed6da9 100644 --- a/argilla-frontend/v1/infrastructure/services/useLanguageDetector.ts +++ b/argilla-frontend/v1/infrastructure/services/useLanguageDetector.ts @@ -1,4 +1,5 @@ import { NuxtI18nInstance } from "@nuxtjs/i18n"; +import { useLocalStorage } from "./useLocalStorage"; type Context = { app: { @@ -10,14 +11,13 @@ type Context = { }; export const useLanguageDetector = (context: Context) => { - const { i18n } = context.app; + const { change } = useLanguageChanger(context); + const { get } = useLocalStorage(); - const change = (language: string) => { - i18n.setLocale(language); - }; + const { i18n } = context.app; const detect = () => { - return navigator.language; + return get("language") || navigator.language; }; const exists = (language: string) => { @@ -36,9 +36,28 @@ export const useLanguageDetector = (context: Context) => { if (exists(languageCode)) { return change(languageCode); } + + change("en"); }; return { initialize, }; }; + +export const useLanguageChanger = (context: Context) => { + const { i18n } = context.app; + + const { set } = useLocalStorage(); + + const change = (language: string) => { + i18n.setLocale(language); + + set("language", language); + }; + + return { + change, + languages: i18n.locales.sort((a, b) => a.code.localeCompare(b.code)), + }; +}; diff --git a/argilla-frontend/v1/infrastructure/services/useLocalStorage.ts b/argilla-frontend/v1/infrastructure/services/useLocalStorage.ts index 7d6c8a7483..967bc4f356 100644 --- a/argilla-frontend/v1/infrastructure/services/useLocalStorage.ts +++ b/argilla-frontend/v1/infrastructure/services/useLocalStorage.ts @@ -1,4 +1,9 @@ -type Options = "showShortcutsHelper" | "layout" | "redirectTo"; +type Options = + | "showShortcutsHelper" + | "layout" + | "redirectTo" + | "language" + | "theme"; const STORAGE_KEY = "argilla"; From 53c734c86d66c3bec6eb9473fb79a542f7f04d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Pumar?= Date: Tue, 19 Nov 2024 11:53:09 +0100 Subject: [PATCH 4/4] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Fix=20highlight=20text?= =?UTF-8?q?=20(#5693)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix https://github.com/argilla-io/argilla/issues/5683 --- argilla-frontend/CHANGELOG.md | 4 ++++ .../useSpanAnnotationTextFieldViewModel.ts | 12 ++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/argilla-frontend/CHANGELOG.md b/argilla-frontend/CHANGELOG.md index e6f5aad8e0..e9b929b2cf 100644 --- a/argilla-frontend/CHANGELOG.md +++ b/argilla-frontend/CHANGELOG.md @@ -21,6 +21,10 @@ These are the section headers that we use: - Add a high-contrast theme & improvements for the forced-colors mode. ([#5661](https://github.com/argilla-io/argilla/pull/5661)) - Add English as the default language and add language selector in the user settings page. ([#5690](https://github.com/argilla-io/argilla/pull/5690)) +### Fixed + +- Fixed highlighting on same record ([#5693](https://github.com/argilla-io/argilla/pull/5693)) + ## [2.4.1](https://github.com/argilla-io/argilla/compare/v2.4.0...v2.4.1) ### Added diff --git a/argilla-frontend/components/features/annotation/container/fields/span-annotation/useSpanAnnotationTextFieldViewModel.ts b/argilla-frontend/components/features/annotation/container/fields/span-annotation/useSpanAnnotationTextFieldViewModel.ts index 98f63a9308..1342df139d 100644 --- a/argilla-frontend/components/features/annotation/container/fields/span-annotation/useSpanAnnotationTextFieldViewModel.ts +++ b/argilla-frontend/components/features/annotation/container/fields/span-annotation/useSpanAnnotationTextFieldViewModel.ts @@ -8,17 +8,13 @@ import { Question } from "~/v1/domain/entities/question/Question"; import { SpanQuestionAnswer } from "~/v1/domain/entities/question/QuestionAnswer"; import { SpanAnswer } from "~/v1/domain/entities/IAnswer"; -export const useSpanAnnotationTextFieldViewModel = ({ - name, - spanQuestion, - id, - searchText, -}: { +export const useSpanAnnotationTextFieldViewModel = (props: { name: string; spanQuestion: Question; id: string; searchText: string; }) => { + const { name, spanQuestion, id } = props; const searchTextHighlight = useSearchTextHighlight(name); const spanAnnotationSupported = ref(true); const answer = spanQuestion.answer as SpanQuestionAnswer; @@ -146,7 +142,7 @@ export const useSpanAnnotationTextFieldViewModel = ({ ); watch( - () => searchText, + () => props.searchText, (newValue) => { searchTextHighlight.highlightText(newValue); } @@ -161,7 +157,7 @@ export const useSpanAnnotationTextFieldViewModel = ({ spanAnnotationSupported.value = false; } - searchTextHighlight.highlightText(searchText); + searchTextHighlight.highlightText(props.searchText); }); onUnmounted(() => {