chore: refactor form label helper

This commit is contained in:
Eli Bosley
2025-04-22 15:48:11 -04:00
parent 54b0bc0837
commit af5ffec13d
4 changed files with 82 additions and 74 deletions

View File

@@ -0,0 +1,6 @@
---
description:
globs:
alwaysApply: true
---
Never add comments for obvious things, and avoid commenting when starting and ending code blocks

View File

@@ -33,6 +33,7 @@ import {
WAN_ACCESS_TYPE,
WAN_FORWARD_TYPE,
} from '@app/unraid-api/graph/resolvers/connect/connect.model.js';
import { createLabeledControl } from '@app/unraid-api/graph/utils/form-utils.js';
import { mergeSettingSlices } from '@app/unraid-api/types/json-forms.js';
import { csvStringToArray } from '@app/utils.js';
@@ -346,15 +347,15 @@ export class ConnectSettingsService {
/** shown when preconditions are met */
const formControls: UIElement[] = [
{
type: 'Control',
createLabeledControl({
scope: '#/properties/accessType',
label: 'Allow Remote Access',
},
{
type: 'Control',
controlOptions: {},
}),
createLabeledControl({
scope: '#/properties/forwardType',
label: 'Remote Access Forward Type',
controlOptions: {},
rule: {
effect: RuleEffect.DISABLE,
condition: {
@@ -364,12 +365,11 @@ export class ConnectSettingsService {
},
} as SchemaBasedCondition,
},
},
{
type: 'Control',
}),
createLabeledControl({
scope: '#/properties/port',
label: 'Remote Access WAN Port',
options: {
controlOptions: {
format: 'short',
formatOptions: {
useGrouping: false,
@@ -390,7 +390,7 @@ export class ConnectSettingsService {
},
} as Omit<SchemaBasedCondition, 'scope'>,
},
},
}),
];
/** shape of the data associated with remote access settings, as json schema properties*/
@@ -438,15 +438,14 @@ export class ConnectSettingsService {
},
},
elements: [
{
type: 'Control',
createLabeledControl({
scope: '#/properties/sandbox',
label: 'Enable Developer Sandbox:',
options: {
description: sandbox ? description : undefined,
controlOptions: {
toggle: true,
description: sandbox ? description : undefined,
},
},
}),
],
};
}
@@ -489,14 +488,17 @@ export class ConnectSettingsService {
},
},
elements: [
{
type: 'Control',
createLabeledControl({
scope: '#/properties/extraOrigins',
options: {
label: 'Allowed Origins (CORS)',
description:
'Provide a comma-separated list of URLs allowed to access the API (e.g., https://myapp.example.com).',
controlOptions: {
inputType: 'url',
placeholder: 'https://example.com',
format: 'array',
},
},
}),
],
};
}
@@ -513,18 +515,20 @@ export class ConnectSettingsService {
type: 'string',
},
title: 'Unraid API SSO Users',
description: `Provide a list of Unique Unraid Account ID's. Find yours at <a href="https://account.unraid.net/settings" target="_blank">account.unraid.net/settings</a>`,
description: `Provide a list of Unique Unraid Account ID's. Find yours at <a href="https://account.unraid.net/settings" target="_blank" rel="noopener noreferrer">account.unraid.net/settings</a>. Requires restart if adding first user.`,
},
},
elements: [
{
type: 'Control',
createLabeledControl({
scope: '#/properties/ssoUserIds',
options: {
label: 'Unraid Connect SSO Users',
description: `Provide a list of Unique Unraid Account IDs. Find yours at <a href="https://account.unraid.net/settings" target="_blank" rel="noopener noreferrer">account.unraid.net/settings</a>. Requires restart if adding first user.`,
controlOptions: {
inputType: 'text',
placeholder: 'UUID',
format: 'array',
},
},
}),
],
};
}

View File

@@ -1,58 +1,11 @@
import type { ControlElement, LabelElement, Layout, Rule, SchemaBasedCondition } from '@jsonforms/core';
import type { LabelElement, Layout, Rule, SchemaBasedCondition } from '@jsonforms/core';
import { JsonSchema7, RuleEffect } from '@jsonforms/core';
import { filter } from 'rxjs';
import type { DataSlice, SettingSlice, UIElement } from '@app/unraid-api/types/json-forms.js';
import { RCloneProviderOptionResponse } from '@app/unraid-api/graph/resolvers/rclone/rclone.model.js';
import { createLabeledControl } from '@app/unraid-api/graph/utils/form-utils.js';
import { mergeSettingSlices } from '@app/unraid-api/types/json-forms.js';
// --- START: Added Helper Function ---
/**
* Creates a HorizontalLayout containing a Label and a Control element.
*/
function createLabeledControl({
scope,
label,
description,
controlOptions,
labelOptions,
layoutOptions,
rule,
}: {
scope: string;
label: string;
description?: string;
controlOptions: ControlElement['options'];
labelOptions?: LabelElement['options'];
layoutOptions?: Layout['options'];
rule?: Rule;
}): Layout {
const layout: Layout & { scope?: string } = {
type: 'UnraidSettingsLayout',
scope: scope, // Apply scope to the layout for potential rules/visibility based on the field itself
options: layoutOptions,
elements: [
{
type: 'Label',
text: label,
scope: scope, // Scope might be needed for specific label behaviors
options: { ...labelOptions, description },
} as LabelElement,
{
type: 'Control',
scope: scope,
options: controlOptions,
} as ControlElement,
],
};
// Conditionally add the rule to the layout if provided
if (rule) {
layout.rule = rule;
}
return layout;
}
// --- END: Added Helper Function ---
/**
* Translates RClone config option to JsonSchema properties
*/
@@ -384,7 +337,6 @@ export function getProviderConfigSlice({
uniqueOptionsByName.forEach((option) => {
if (option) {
paramProperties[option.Name] = translateRCloneOptionToJsonSchema({ option });
console.log('paramProperties', option.Name, paramProperties[option.Name]);
}
});

View File

@@ -0,0 +1,46 @@
import type { ControlElement, LabelElement, Layout, Rule } from '@jsonforms/core';
/**
* Creates a Layout (typically UnraidSettingsLayout) containing a Label and a Control element.
*/
export function createLabeledControl({
scope,
label,
description,
controlOptions,
labelOptions,
layoutOptions,
rule,
}: {
scope: string;
label: string;
description?: string;
controlOptions: ControlElement['options'];
labelOptions?: LabelElement['options'];
layoutOptions?: Layout['options'];
rule?: Rule;
}): Layout {
const layout: Layout & { scope?: string } = {
type: 'UnraidSettingsLayout', // Use the specific Unraid layout type
scope: scope, // Apply scope to the layout for potential rules/visibility
options: layoutOptions,
elements: [
{
type: 'Label',
text: label,
scope: scope, // Scope might be needed for specific label behaviors
options: { ...labelOptions, description },
} as LabelElement,
{
type: 'Control',
scope: scope,
options: controlOptions,
} as ControlElement,
],
};
// Conditionally add the rule to the layout if provided
if (rule) {
layout.rule = rule;
}
return layout;
}