hotfix(dataset): enhance radio button and checkbox components and add arrayContainsTypes validation

- Added checkbox support to the `FormCheckRadio` component.
- Updated the styling of the radio button and checkbox components.
- Added the `arrayContainsTypes` validation rule to ensure that arrays contain specific types.
- Updated the `dataset` validators and controllers to use the new validation rule.
- Updated the `FormCheckRadioGroup` component to correctly handle the `input-value` as a number.
- Removed the default value from the `id` column in the `collections` migration.
- Added the `array_contains_types` rule to the `adonisrc.ts` file.
This commit is contained in:
Kaimbacher 2025-03-28 17:34:46 +01:00
parent 9823364670
commit 09f65359f9
8 changed files with 116 additions and 41 deletions

View file

@ -0,0 +1,80 @@
import { FieldContext } from '@vinejs/vine/types';
import vine, { VineArray } from '@vinejs/vine';
import { SchemaTypes } from '@vinejs/vine/types';
type Options = {
typeA: string;
typeB: string;
};
/**
* Custom rule to validate an array of titles contains at least one title
* with type 'main' and one with type 'translated'.
*
* This rule expects the validated value to be an array of objects,
* where each object has a "type" property.
*/
async function arrayContainsTypes(value: unknown, options: Options, field: FieldContext) {
if (!Array.isArray(value)) {
field.report(`The {{field}} must be an array of titles.`, 'array.titlesContainsMainAndTranslated', field);
return false;
}
const typeAExpected = options.typeA.toLowerCase();
const typeBExpected = options.typeB.toLowerCase();
// const hasMain = value.some((title: any) => {
// return typeof title === 'object' && title !== null && String(title.type).toLowerCase() === 'main';
// });
// const hasTranslated = value.some((title: any) => {
// return typeof title === 'object' && title !== null && String(title.type).toLowerCase() === 'translated';
// });
const hasTypeA = value.some((item: any) => {
return typeof item === 'object' && item !== null && String(item.type).toLowerCase() === typeAExpected;
});
const hasTypeB = value.some((item: any) => {
return typeof item === 'object' && item !== null && String(item.type).toLowerCase() === typeBExpected;
});
if (!hasTypeA || !hasTypeB) {
let errorMessage = `The ${field.getFieldPath()} array must have at least one '${options.typeA}' item and one '${options.typeB}' item.`;
// Check for specific field names to produce a more readable message.
if (field.getFieldPath() === 'titles') {
// For titles we expect one main and minimum one translated title.
if (!hasTypeA && !hasTypeB) {
errorMessage = 'For titles, define one main title and minimum one translated title.';
} else if (!hasTypeA) {
errorMessage = 'For titles, define one main title.';
} else if (!hasTypeB) {
errorMessage = 'For titles, define minimum one translated title.';
}
} else if (field.getFieldPath() === 'descriptions') {
// For descriptions we expect one abstracts description and minimum one translated description.
if (!hasTypeA && !hasTypeB) {
errorMessage = 'For descriptions, define one abstracts description and minimum one translated description.';
} else if (!hasTypeA) {
errorMessage = 'For descriptions, define one abstracts description.';
} else if (!hasTypeB) {
errorMessage = 'For descriptions, define minimum one translated description.';
}
}
field.report(errorMessage, 'array.containsTypes', field, options);
return false;
}
return true;
}
export const arrayContainsMainAndTranslatedRule = vine.createRule(arrayContainsTypes);
declare module '@vinejs/vine' {
interface VineArray<Schema extends SchemaTypes> {
arrayContainsTypes(options: Options): this;
}
}
VineArray.macro('arrayContainsTypes', function <Schema extends SchemaTypes>(this: VineArray<Schema>, options: Options) {
return this.use(arrayContainsMainAndTranslatedRule(options));
});