diff --git a/frontend/src/app/boards/[boardId]/page.tsx b/frontend/src/app/boards/[boardId]/page.tsx index 84bd785d..01c95282 100644 --- a/frontend/src/app/boards/[boardId]/page.tsx +++ b/frontend/src/app/boards/[boardId]/page.tsx @@ -580,17 +580,15 @@ const formatCustomFieldDetailValue = ( const trimmed = value.trim(); if (!trimmed) return "—"; try { - // Validate URL before rendering as a link. - // eslint-disable-next-line no-new - new URL(trimmed); + const parsedUrl = new URL(trimmed); return ( - {trimmed} + {parsedUrl.toString()} ); @@ -601,8 +599,7 @@ const formatCustomFieldDetailValue = ( if (fieldType === "json") { try { - const normalized = - typeof value === "string" ? JSON.parse(value) : value; + const normalized = typeof value === "string" ? JSON.parse(value) : value; return (
           {JSON.stringify(normalized, null, 2)}
@@ -615,7 +612,11 @@ const formatCustomFieldDetailValue = (
 
   if (fieldType === "text_long") {
     const text = customFieldInputText(value);
-    return text ? {text} : "—";
+    return text ? (
+      {text}
+    ) : (
+      "—"
+    );
   }
 
   return customFieldInputText(value) || "—";
@@ -634,7 +635,8 @@ const isCustomFieldVisible = (
   value: unknown,
 ): boolean => {
   if (definition.ui_visibility === "hidden") return false;
-  if (definition.ui_visibility === "if_set") return isCustomFieldValueSet(value);
+  if (definition.ui_visibility === "if_set")
+    return isCustomFieldValueSet(value);
   return true;
 };
 
@@ -644,7 +646,10 @@ const parseCustomFieldInputValue = (
 ): unknown | null => {
   const trimmed = text.trim();
   if (!trimmed) return null;
-  if (definition.field_type === "text" || definition.field_type === "text_long") {
+  if (
+    definition.field_type === "text" ||
+    definition.field_type === "text_long"
+  ) {
     return trimmed;
   }
   if (definition.field_type === "integer") {
@@ -739,7 +744,10 @@ const customFieldPatchPayload = (
 ): TaskCustomFieldValues =>
   definitions.reduce((acc, definition) => {
     const key = definition.field_key;
-    const currentValue = Object.prototype.hasOwnProperty.call(currentValues, key)
+    const currentValue = Object.prototype.hasOwnProperty.call(
+      currentValues,
+      key,
+    )
       ? currentValues[key]
       : null;
     const nextValue = Object.prototype.hasOwnProperty.call(nextValues, key)
@@ -2855,7 +2863,10 @@ export default function BoardDetailPage() {
       if (dueDateChanged) {
         updatePayload.due_at = localDateInputToUtcIso(editDueDate);
       }
-      if (customFieldValuesChanged && Object.keys(editCustomFieldPatch).length > 0) {
+      if (
+        customFieldValuesChanged &&
+        Object.keys(editCustomFieldPatch).length > 0
+      ) {
         updatePayload.custom_field_values = editCustomFieldPatch;
       }
 
@@ -4343,7 +4354,8 @@ export default function BoardDetailPage() {
               ) : (
                 
{boardCustomFieldDefinitions.map((definition) => { - const fieldValue = editCustomFieldValues[definition.field_key]; + const fieldValue = + editCustomFieldValues[definition.field_key]; if (!isCustomFieldVisible(definition, fieldValue)) { return null; } @@ -4371,7 +4383,9 @@ export default function BoardDetailPage() { value === "unset" ? null : value === "true", })) } - disabled={!selectedTask || isSavingTask || !canWrite} + disabled={ + !selectedTask || isSavingTask || !canWrite + } > @@ -4389,10 +4403,11 @@ export default function BoardDetailPage() { onChange={(event) => setEditCustomFieldValues((prev) => ({ ...prev, - [definition.field_key]: parseCustomFieldInputValue( - definition, - event.target.value, - ), + [definition.field_key]: + parseCustomFieldInputValue( + definition, + event.target.value, + ), })) } placeholder={ @@ -4402,7 +4417,9 @@ export default function BoardDetailPage() { : "Optional" } rows={definition.field_type === "text_long" ? 3 : 4} - disabled={!selectedTask || isSavingTask || !canWrite} + disabled={ + !selectedTask || isSavingTask || !canWrite + } /> ) : ( setEditCustomFieldValues((prev) => ({ ...prev, - [definition.field_key]: parseCustomFieldInputValue( - definition, - event.target.value, - ), + [definition.field_key]: + parseCustomFieldInputValue( + definition, + event.target.value, + ), })) } placeholder={ @@ -4435,7 +4457,9 @@ export default function BoardDetailPage() { ? `Default: ${customFieldInputText(definition.default_value)}` : "Optional" } - disabled={!selectedTask || isSavingTask || !canWrite} + disabled={ + !selectedTask || isSavingTask || !canWrite + } /> )} {definition.description ? ( @@ -4833,10 +4857,11 @@ export default function BoardDetailPage() { onChange={(event) => setCreateCustomFieldValues((prev) => ({ ...prev, - [definition.field_key]: parseCustomFieldInputValue( - definition, - event.target.value, - ), + [definition.field_key]: + parseCustomFieldInputValue( + definition, + event.target.value, + ), })) } placeholder={ @@ -4862,15 +4887,20 @@ export default function BoardDetailPage() { ? "url" : "text" } - step={definition.field_type === "decimal" ? "any" : undefined} + step={ + definition.field_type === "decimal" + ? "any" + : undefined + } value={customFieldInputText(fieldValue)} onChange={(event) => setCreateCustomFieldValues((prev) => ({ ...prev, - [definition.field_key]: parseCustomFieldInputValue( - definition, - event.target.value, - ), + [definition.field_key]: + parseCustomFieldInputValue( + definition, + event.target.value, + ), })) } placeholder={ diff --git a/frontend/src/app/custom-fields/[fieldId]/edit/page.tsx b/frontend/src/app/custom-fields/[fieldId]/edit/page.tsx index 21ebcf70..cd287a40 100644 --- a/frontend/src/app/custom-fields/[fieldId]/edit/page.tsx +++ b/frontend/src/app/custom-fields/[fieldId]/edit/page.tsx @@ -67,7 +67,13 @@ type EditCustomFieldFormProps = { onSubmit: (updates: TaskCustomFieldDefinitionUpdate) => Promise; }; -const STRING_FIELD_TYPES = new Set(["text", "text_long", "date", "date_time", "url"]); +const STRING_FIELD_TYPES = new Set([ + "text", + "text_long", + "date", + "date_time", + "url", +]); const parseDefaultValue = ( fieldType: FormState["fieldType"], @@ -92,11 +98,14 @@ const parseDefaultValue = ( } if (fieldType === "boolean") { if (trimmed.toLowerCase() === "true") return { value: true, error: null }; - if (trimmed.toLowerCase() === "false") - return { value: false, error: null }; + if (trimmed.toLowerCase() === "false") return { value: false, error: null }; return { value: null, error: "Default value must be true or false." }; } - if (fieldType === "date" || fieldType === "date_time" || fieldType === "url") { + if ( + fieldType === "date" || + fieldType === "date_time" || + fieldType === "url" + ) { return { value: trimmed, error: null }; } if (fieldType === "json") { @@ -198,7 +207,9 @@ function EditCustomFieldForm({ trimmedValidationRegex && !STRING_FIELD_TYPES.has(formState.fieldType) ) { - setSaveError("Validation regex is only supported for string field types."); + setSaveError( + "Validation regex is only supported for string field types.", + ); return; } const parsedDefaultValue = parseDefaultValue( @@ -455,7 +466,9 @@ function EditCustomFieldForm({ Loading boards…
) : boardsError ? ( -
{boardsError}
+
+ {boardsError} +
) : filteredBoards.length === 0 ? (
No boards found. diff --git a/frontend/src/app/custom-fields/new/page.tsx b/frontend/src/app/custom-fields/new/page.tsx index f42cd9c2..095e1a16 100644 --- a/frontend/src/app/custom-fields/new/page.tsx +++ b/frontend/src/app/custom-fields/new/page.tsx @@ -63,7 +63,13 @@ const defaultFormState: FormState = { defaultValue: "", }; -const STRING_FIELD_TYPES = new Set(["text", "text_long", "date", "date_time", "url"]); +const STRING_FIELD_TYPES = new Set([ + "text", + "text_long", + "date", + "date_time", + "url", +]); const parseDefaultValue = ( fieldType: FormState["fieldType"], @@ -88,11 +94,14 @@ const parseDefaultValue = ( } if (fieldType === "boolean") { if (trimmed.toLowerCase() === "true") return { value: true, error: null }; - if (trimmed.toLowerCase() === "false") - return { value: false, error: null }; + if (trimmed.toLowerCase() === "false") return { value: false, error: null }; return { value: null, error: "Default value must be true or false." }; } - if (fieldType === "date" || fieldType === "date_time" || fieldType === "url") { + if ( + fieldType === "date" || + fieldType === "date_time" || + fieldType === "url" + ) { return { value: trimmed, error: null }; } if (fieldType === "json") {