-
+
diff --git a/argilla-frontend/pages/oauth/_provider/useOAuthViewModel.ts b/argilla-frontend/pages/oauth/_provider/useOAuthViewModel.ts
index 91ccd6104d..1cbb722af7 100644
--- a/argilla-frontend/pages/oauth/_provider/useOAuthViewModel.ts
+++ b/argilla-frontend/pages/oauth/_provider/useOAuthViewModel.ts
@@ -2,7 +2,11 @@ import { useFetch, useRoute } from "@nuxtjs/composition-api";
import { useResolve } from "ts-injecty";
import { ProviderType } from "~/v1/domain/entities/oauth/OAuthProvider";
import { OAuthLoginUseCase } from "~/v1/domain/usecases/oauth-login-use-case";
-import { useRoutes, useTranslate } from "~/v1/infrastructure/services";
+import {
+ useRoutes,
+ useTranslate,
+ useLocalStorage,
+} from "~/v1/infrastructure/services";
import { useNotifications } from "~/v1/infrastructure/services/useNotifications";
export const useOAuthViewModel = () => {
@@ -11,11 +15,17 @@ export const useOAuthViewModel = () => {
const routes = useRoute();
const router = useRoutes();
const oauthLoginUseCase = useResolve(OAuthLoginUseCase);
+ const { pop } = useLocalStorage();
useFetch(async () => {
await tryLogin();
});
+ const redirect = () => {
+ const redirect = pop("redirectTo");
+ router.go(redirect || "/");
+ };
+
const tryLogin = async () => {
const { params, query } = routes.value;
@@ -23,12 +33,12 @@ export const useOAuthViewModel = () => {
try {
await oauthLoginUseCase.login(provider, query);
+ redirect();
} catch {
notification.notify({
message: t("argilla.api.errors::UnauthorizedError"),
type: "danger",
});
- } finally {
router.go("/");
}
};
diff --git a/argilla-frontend/pages/sign-in.vue b/argilla-frontend/pages/sign-in.vue
index 6d5d0f71ce..f804223a01 100644
--- a/argilla-frontend/pages/sign-in.vue
+++ b/argilla-frontend/pages/sign-in.vue
@@ -98,18 +98,8 @@ export default {
},
},
methods: {
- nextRedirect() {
- const redirect_url = this.$nuxt.$route.query.redirect || "/";
- this.$router.push({
- path: redirect_url,
- });
- },
async loginUser({ username, password }) {
await this.login(username, password);
-
- this.$notification.clear();
-
- this.nextRedirect();
},
async onLoginUser() {
try {
diff --git a/argilla-frontend/pages/useNewDatasetViewModel.ts b/argilla-frontend/pages/useNewDatasetViewModel.ts
index a66fb469f3..8cce1d4f3a 100644
--- a/argilla-frontend/pages/useNewDatasetViewModel.ts
+++ b/argilla-frontend/pages/useNewDatasetViewModel.ts
@@ -1,15 +1,20 @@
import { useResolve } from "ts-injecty";
-import { ref, useRoute } from "@nuxtjs/composition-api";
+import { ref, useRoute, useContext } from "@nuxtjs/composition-api";
import { GetDatasetCreationUseCase } from "~/v1/domain/usecases/get-dataset-creation-use-case";
export const useNewDatasetViewModel = () => {
+ const { error } = useContext();
const datasetConfig = ref();
const getDatasetCreationUseCase = useResolve(GetDatasetCreationUseCase);
const getNewDatasetByRepoId = async (repositoryId: string) => {
- datasetConfig.value = await getDatasetCreationUseCase.execute(
- decodeURI(repositoryId)
- );
+ try {
+ datasetConfig.value = await getDatasetCreationUseCase.execute(
+ repositoryId
+ );
+ } catch (e) {
+ error({ statusCode: 404, message: "Cannot fetch the dataset" });
+ }
};
const getNewDatasetByRepoIdFromUrl = async () => {
diff --git a/argilla-frontend/pages/useSignInViewModel.ts b/argilla-frontend/pages/useSignInViewModel.ts
index 12075594be..b2d5f6f2ee 100644
--- a/argilla-frontend/pages/useSignInViewModel.ts
+++ b/argilla-frontend/pages/useSignInViewModel.ts
@@ -1,11 +1,23 @@
import { useResolve } from "ts-injecty";
import { AuthLoginUseCase } from "~/v1/domain/usecases/auth-login-use-case";
+import { useRoutes, useLocalStorage } from "~/v1/infrastructure/services";
+import { useNotifications } from "~/v1/infrastructure/services/useNotifications";
export const useSignInViewModel = () => {
const useCase = useResolve(AuthLoginUseCase);
+ const router = useRoutes();
+ const notification = useNotifications();
+ const { pop } = useLocalStorage();
+
+ const redirect = () => {
+ const redirect = pop("redirectTo");
+ router.go(redirect || "/");
+ };
const login = async (username: string, password: string) => {
await useCase.login(username, password);
+ notification.clear();
+ redirect();
};
return {
diff --git a/argilla-frontend/plugins/directives/required-field.directive.js b/argilla-frontend/plugins/directives/required-field.directive.js
index 163fff4c04..c478d96c18 100644
--- a/argilla-frontend/plugins/directives/required-field.directive.js
+++ b/argilla-frontend/plugins/directives/required-field.directive.js
@@ -5,22 +5,19 @@ import Vue from "vue";
// => color (String) the color of the asterisk : black by default
Vue.directive("required-field", {
- bind: (element, binding, node) => {
- if (binding?.value) {
- const { color, show } = binding?.value ?? { show: true, color: "black" };
-
- if (!show) return;
-
- const text = document.createTextNode(" *");
- const textWrapper = document.createElement("span");
- textWrapper.setAttribute("title", "Required response");
- textWrapper.setAttribute("role", "mark");
- textWrapper.style.color = color;
- textWrapper.appendChild(text);
-
- node.context.$nextTick(() => {
- element.insertAdjacentElement("afterEnd", textWrapper);
- });
+ bind(element, binding) {
+ const span = document.createElement("span");
+ span.textContent = " *";
+ span.style.color = binding.value.color;
+ span.setAttribute("title", "Required response");
+ span.setAttribute("role", "mark");
+ element.appendChild(span);
+ span.style.display = binding.value.show ? "inline" : "none";
+ },
+ update(element, binding) {
+ const span = element.querySelector("span");
+ if (span) {
+ span.style.display = binding.value.show ? "inline" : "none";
}
},
});
diff --git a/argilla-frontend/translation/en.js b/argilla-frontend/translation/en.js
index caf52c564a..009525c13c 100644
--- a/argilla-frontend/translation/en.js
+++ b/argilla-frontend/translation/en.js
@@ -282,6 +282,9 @@ export default {
atLeastTwoOptions: "At least two options are required",
optionsWithoutLabel: "Empty options are not allowed",
},
+ rating: {
+ atLeastTwoOptions: "At least two options are required",
+ },
},
atLeastOneQuestion: "At least one question is required.",
atLeastOneRequired: "At least one required question is needed.",
@@ -327,6 +330,14 @@ export default {
span: "Span",
"no mapping": "No mapping",
},
+ questionId: {
+ text: "text",
+ rating: "rating",
+ label_selection: "label",
+ ranking: "ranking",
+ multi_label_selection: "multi-label",
+ span: "span",
+ },
},
persistentStorage: {
adminOrOwner:
diff --git a/argilla-frontend/translation/es.js b/argilla-frontend/translation/es.js
index fc00604f26..ed40c9396e 100644
--- a/argilla-frontend/translation/es.js
+++ b/argilla-frontend/translation/es.js
@@ -280,6 +280,9 @@ export default {
atLeastTwoOptions: "Se requieren al menos dos opciones",
optionsWithoutLabel: "No se permiten opciones vacĂas",
},
+ rating: {
+ atLeastTwoOptions: "Se requieren al menos dos opciones",
+ },
},
atLeastOneQuestion: "Se requiere al menos una pregunta.",
atLeastOneRequired: "Se requiere al menos una pregunta obligatoria.",
diff --git a/argilla-frontend/v1/domain/entities/hub/DatasetCreation.test.ts b/argilla-frontend/v1/domain/entities/hub/DatasetCreation.test.ts
index ff21d2aedf..802a863dc7 100644
--- a/argilla-frontend/v1/domain/entities/hub/DatasetCreation.test.ts
+++ b/argilla-frontend/v1/domain/entities/hub/DatasetCreation.test.ts
@@ -29,6 +29,10 @@ const datasetInfo = {
dtype: "string",
_type: "Value",
},
+ extra: {
+ dtype: "int32",
+ _type: "Value",
+ },
},
],
metadata: {
@@ -160,6 +164,35 @@ describe("DatasetCreation", () => {
expect(chatField.required).toBeFalsy();
});
+ it("skip other list feature from chat fields", () => {
+ const builder = new DatasetCreationBuilder("FAKE", {
+ default: {
+ ...datasetInfo.default,
+ features: {
+ some_list_feature: [
+ {
+ other: {
+ dtype: "string",
+ _type: "Value",
+ },
+ value: {
+ dtype: "string",
+ _type: "Value",
+ },
+ },
+ ],
+ },
+ },
+ });
+
+ const datasetCreation = builder.build();
+
+ expect(
+ datasetCreation.fields.filter((f) => f.type.value === "no mapping")
+ .length
+ ).toBe(1);
+ });
+
it("get no mapped feature", () => {
const builder = new DatasetCreationBuilder("FAKE", {
default: {
diff --git a/argilla-frontend/v1/domain/entities/hub/QuestionCreation.ts b/argilla-frontend/v1/domain/entities/hub/QuestionCreation.ts
index 2d23e49ed4..c8ff905aa0 100644
--- a/argilla-frontend/v1/domain/entities/hub/QuestionCreation.ts
+++ b/argilla-frontend/v1/domain/entities/hub/QuestionCreation.ts
@@ -64,6 +64,10 @@ export class QuestionCreation {
this.required = true;
}
+ get isRequired(): boolean {
+ return this.required;
+ }
+
get isTextType(): boolean {
return this.type.isTextType;
}
@@ -111,6 +115,11 @@ export class QuestionCreation {
);
}
}
+ if (this.isRatingType) {
+ if (this.options.length < 2) {
+ errors.push("datasetCreation.questions.rating.atLeastTwoOptions");
+ }
+ }
return errors;
}
diff --git a/argilla-frontend/v1/domain/entities/hub/Subset.ts b/argilla-frontend/v1/domain/entities/hub/Subset.ts
index f0cc82b0b7..ba72804400 100644
--- a/argilla-frontend/v1/domain/entities/hub/Subset.ts
+++ b/argilla-frontend/v1/domain/entities/hub/Subset.ts
@@ -7,6 +7,8 @@ import { QuestionCreation } from "./QuestionCreation";
type Structure = {
name: string;
options?: string[];
+ role?: string;
+ content?: string;
structure?: Structure[];
kindObject?: "Value" | "Image" | "ClassLabel" | "Sequence";
type?: "string" | MetadataTypes;
@@ -33,6 +35,7 @@ export class Subset {
for (const [name, value] of Object.entries
(datasetInfo.features)) {
if (Array.isArray(value)) {
+ const { role, content } = value[0];
this.structures.push({
name,
structure: value.map((v) => {
@@ -42,6 +45,8 @@ export class Subset {
name: key,
kindObject: value._type,
type: value.dtype,
+ role,
+ content,
};
}),
});
@@ -134,8 +139,12 @@ export class Subset {
return "text";
if (structure.kindObject === "Image") return "image";
-
- if (structure.structure?.length > 0) return "chat";
+ if (
+ structure.structure?.length > 0 &&
+ structure.structure[0].content &&
+ structure.structure[0].role
+ )
+ return "chat";
};
const field = FieldCreation.from(
@@ -193,7 +202,11 @@ export class Subset {
}
}
- public addQuestion(name: string, settings: QuestionPrototype) {
+ public addQuestion(
+ name: string,
+ settings: QuestionPrototype,
+ position?: number
+ ) {
const { type } = settings;
if (type === "label_selection") {
settings.options = [
@@ -257,6 +270,10 @@ export class Subset {
return;
}
- this.questions.push(new QuestionCreation(name, settings));
+ this.questions.splice(
+ position ?? this.questions.length,
+ 0,
+ new QuestionCreation(name, settings)
+ );
}
}
diff --git a/argilla-frontend/v1/infrastructure/repositories/HubRepository.ts b/argilla-frontend/v1/infrastructure/repositories/HubRepository.ts
index 82ef090e67..7ca3528929 100644
--- a/argilla-frontend/v1/infrastructure/repositories/HubRepository.ts
+++ b/argilla-frontend/v1/infrastructure/repositories/HubRepository.ts
@@ -2,6 +2,10 @@ import { type NuxtAxiosInstance } from "@nuxtjs/axios";
import { PublicNuxtAxiosInstance } from "../services";
import { DatasetCreation } from "~/v1/domain/entities/hub/DatasetCreation";
+export const enum HUB_REPOSITORY_ERRORS {
+ NOT_EXIST = "ERROR_FETCHING_DATASET",
+}
+
export class HubRepository {
private axios: NuxtAxiosInstance;
constructor(axios: PublicNuxtAxiosInstance) {
@@ -19,8 +23,10 @@ export class HubRepository {
);
return data.dataset_info;
- } catch {
- return {};
+ } catch (e) {
+ throw {
+ response: HUB_REPOSITORY_ERRORS.NOT_EXIST,
+ };
}
}
diff --git a/argilla-frontend/v1/infrastructure/services/useLocalStorage.ts b/argilla-frontend/v1/infrastructure/services/useLocalStorage.ts
index f3331172bb..7d6c8a7483 100644
--- a/argilla-frontend/v1/infrastructure/services/useLocalStorage.ts
+++ b/argilla-frontend/v1/infrastructure/services/useLocalStorage.ts
@@ -1,4 +1,4 @@
-type Options = "showShortcutsHelper" | "layout";
+type Options = "showShortcutsHelper" | "layout" | "redirectTo";
const STORAGE_KEY = "argilla";
@@ -34,8 +34,15 @@ export const useLocalStorage = () => {
} catch {}
};
+ const pop = (key: Options) => {
+ const value = get(key);
+ set(key, null);
+ return value;
+ };
+
return {
get,
set,
+ pop,
};
};
diff --git a/argilla-frontend/v1/infrastructure/services/useRoutes.ts b/argilla-frontend/v1/infrastructure/services/useRoutes.ts
index b4f1c2ba45..b604e62484 100644
--- a/argilla-frontend/v1/infrastructure/services/useRoutes.ts
+++ b/argilla-frontend/v1/infrastructure/services/useRoutes.ts
@@ -133,9 +133,9 @@ export const useRoutes = () => {
} else {
window.location.href = where;
}
+ } else {
+ router.push(where);
}
-
- router.push(where);
};
const getQuery = () => {
diff --git a/argilla-server/CHANGELOG.md b/argilla-server/CHANGELOG.md
index 9c385b82a2..695155f8e8 100644
--- a/argilla-server/CHANGELOG.md
+++ b/argilla-server/CHANGELOG.md
@@ -16,6 +16,12 @@ These are the section headers that we use:
## [Unreleased]()
+## [2.4.1](https://github.com/argilla-io/argilla/compare/v2.4.0...v2.4.1)
+
+### Fixed
+
+- Fixed error so now `_touch_dataset_last_activity_at` function is not updating dataset's `updated_at` column. ([#5656](https://github.com/argilla-io/argilla/pull/5656))
+
## [2.4.0](https://github.com/argilla-io/argilla/compare/v2.3.1...v2.4.0)
### Added
diff --git a/argilla-server/src/argilla_server/_version.py b/argilla-server/src/argilla_server/_version.py
index cbb95518ab..0cb36e7d0f 100644
--- a/argilla-server/src/argilla_server/_version.py
+++ b/argilla-server/src/argilla_server/_version.py
@@ -15,4 +15,4 @@
# coding: utf-8
#
-__version__ = "2.4.0"
+__version__ = "2.4.1"
diff --git a/argilla-server/src/argilla_server/contexts/datasets.py b/argilla-server/src/argilla_server/contexts/datasets.py
index 131904307b..b31aafe3b4 100644
--- a/argilla-server/src/argilla_server/contexts/datasets.py
+++ b/argilla-server/src/argilla_server/contexts/datasets.py
@@ -100,7 +100,12 @@
async def _touch_dataset_last_activity_at(db: AsyncSession, dataset: Dataset) -> None:
await db.execute(
- sqlalchemy.update(Dataset).where(Dataset.id == dataset.id).values(last_activity_at=datetime.utcnow())
+ sqlalchemy.update(Dataset)
+ .where(Dataset.id == dataset.id)
+ .values(
+ last_activity_at=datetime.utcnow(),
+ updated_at=Dataset.__table__.c.updated_at,
+ )
)
diff --git a/argilla-server/tests/unit/api/handlers/v1/test_oauth2.py b/argilla-server/tests/unit/api/handlers/v1/test_oauth2.py
index 7f8d6ddee1..b5a3d87477 100644
--- a/argilla-server/tests/unit/api/handlers/v1/test_oauth2.py
+++ b/argilla-server/tests/unit/api/handlers/v1/test_oauth2.py
@@ -89,7 +89,7 @@ async def test_provider_huggingface_authentication(
):
with mock.patch("argilla_server.security.settings.Settings.oauth", new_callable=lambda: default_oauth_settings):
response = await async_client.get(
- "/api/v1/oauth2/providers/huggingface/authentication", headers=owner_auth_header
+ "/api/v1/oauth2/providers/huggingface/authentication?extra=params", headers=owner_auth_header
)
assert response.status_code == 303
@@ -97,6 +97,7 @@ async def test_provider_huggingface_authentication(
assert redirect_url.scheme == b"https"
assert redirect_url.host == b"huggingface.co"
assert b"/oauth/authorize?response_type=code&client_id=client_id" in redirect_url.target
+ assert b"&extra=params" in redirect_url.target
async def test_provider_authentication_with_oauth_disabled(
self,
diff --git a/argilla-server/tests/unit/api/handlers/v1/test_responses.py b/argilla-server/tests/unit/api/handlers/v1/test_responses.py
index ceddf5201d..547e6faef4 100644
--- a/argilla-server/tests/unit/api/handlers/v1/test_responses.py
+++ b/argilla-server/tests/unit/api/handlers/v1/test_responses.py
@@ -102,6 +102,7 @@ async def test_update_response(
"updated_at": datetime.fromisoformat(resp_body["updated_at"]).isoformat(),
}
+ await db.refresh(dataset)
assert dataset.last_activity_at > dataset_previous_last_activity_at
assert dataset.updated_at == dataset_previous_updated_at
@@ -421,6 +422,7 @@ async def test_delete_response(
assert resp.status_code == 200
assert (await db.execute(select(func.count(Response.id)))).scalar() == 0
+ await db.refresh(dataset)
assert dataset.last_activity_at > dataset_previous_last_activity_at
assert dataset.updated_at == dataset_previous_updated_at