diff --git a/app/packages/core/src/components/ViewBar/ViewStage/utils.ts b/app/packages/core/src/components/ViewBar/ViewStage/utils.ts index e876433faae..8c30922b1b3 100644 --- a/app/packages/core/src/components/ViewBar/ViewStage/utils.ts +++ b/app/packages/core/src/components/ViewBar/ViewStage/utils.ts @@ -21,3 +21,27 @@ export const getMatch = (options, value) => { } return null; }; + +export const cleanCSV = (values: string) => { + return ( + values + // replace spaces with a single space (to allow search by words with spaces) + .replace(/[\s\'\"\[\]]+/g, " ") + // replace comma followed by trailing spaces with a single comma + .replace(/,\s*/g, ",") + // remove trailing spaces + .replace(/[ \t]+$/, "") + ); +}; + +export const getArray = (value: string | unknown[]): unknown[] => { + if (typeof value === "string") { + try { + return JSON.parse(value); + } catch { + return value.replace(/[\s]/g, "").split(","); + } + } + + return value; +}; diff --git a/app/packages/core/src/components/ViewBar/ViewStage/viewStageParameterMachine.ts b/app/packages/core/src/components/ViewBar/ViewStage/viewStageParameterMachine.ts index a6ef668c4af..a0a31bb4a59 100644 --- a/app/packages/core/src/components/ViewBar/ViewStage/viewStageParameterMachine.ts +++ b/app/packages/core/src/components/ViewBar/ViewStage/viewStageParameterMachine.ts @@ -1,7 +1,8 @@ import { v4 as uuid } from "uuid"; import { actions, Machine, sendParent } from "xstate"; -import { computeBestMatchString, getMatch } from "./utils"; +import { isObjectIdString } from "@fiftyone/utilities"; +import { cleanCSV, computeBestMatchString, getArray, getMatch } from "./utils"; const { assign } = actions; @@ -85,7 +86,7 @@ export const PARSER = { castFrom: (value) => value, castTo: (value) => value, parse: (value) => value, - validate: (value) => /[0-9A-Fa-f]{24}/g.test(value), + validate: (value) => isObjectIdString(value), }, int: { castFrom: (value) => String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ","), @@ -113,66 +114,25 @@ export const PARSER = { "list": { castFrom: (value) => value.join(","), castTo: (value) => value.split(","), - parse: (value) => value.replace(/[\s\'\"\[\]]/g, ""), + parse: (value) => cleanCSV(value), validate: (value, fields) => { - const stripped = value.replace(/[\s]/g, ""); - let array = null; - try { - array = JSON.parse(stripped); - } catch { - array = stripped.split(","); - } - return ( - typeof value !== "string" && - Array.isArray(array) && - array.every((e) => PARSER.field.validate(e, fields)) - ); + return getArray(value).every((e) => PARSER.field.validate(e, fields)); }, }, "list": { castFrom: (value) => value.join(","), castTo: (value) => value.split(","), - parse: (value) => value.replace(/[\s\'\"\[\]]/g, ""), + parse: (value) => cleanCSV(value), validate: (value) => { - const stripped = value.replace(/[\s]/g, ""); - let array = null; - try { - array = JSON.parse(stripped); - } catch { - array = stripped.split(","); - } - return ( - typeof value !== "string" && - Array.isArray(array) && - array.every((e) => PARSER.id.validate(e)) - ); + return getArray(value).every((e) => PARSER.id.validate(e)); }, }, "list": { castFrom: (value) => value.join(","), castTo: (value) => value.split(","), - parse: (value) => - value - // replace spaces with a single space (to allow search by words with spaces) - .replace(/[\s\'\"\[\]]+/g, " ") - // replace comma followed by trailing spaces with a single comma - .replace(/,\s*/g, ",") - // remove trailing spaces - .replace(/[ \t]+$/, ""), + parse: (value) => cleanCSV(value), validate: (value) => { - const stripped = value.replace(/[\s]/g, ""); - let array = null; - try { - array = JSON.parse(stripped); - } catch { - // ex: exclude_fields('a, b'). 'a,b' => ['a', 'b'] - array = stripped.split(","); - } - return ( - typeof array !== "string" && - Array.isArray(array) && - array.every((e) => PARSER.str.validate(e)) - ); + return getArray(value).every((e) => PARSER.str.validate(e)); }, }, NoneType: { diff --git a/app/packages/utilities/src/type-check.ts b/app/packages/utilities/src/type-check.ts index f43c2dd7508..b818f64cad6 100644 --- a/app/packages/utilities/src/type-check.ts +++ b/app/packages/utilities/src/type-check.ts @@ -11,7 +11,7 @@ export function isPrimitiveType(type: string) { } export function isHex(value: string) { - return parseInt(value, 16).toString(16) === value; + return /[0-9a-f]{24}/g.test(value); } export function isObjectIdString(value: string) {