### Major Features - Add comprehensive ORCID validation with checksum verification - Implement unsaved changes detection and auto-save functionality - Enhanced form component reactivity and state management ### ORCID Implementation - Create custom VineJS ORCID validation rule with MOD-11-2 algorithm - Add ORCID fields to Person model and TablePersons component - Update dataset validators to include ORCID validation - Add descriptive placeholder text for ORCID input fields ### UI/UX Improvements - Add UnsavedChangesWarning component with detailed change tracking - Improve FormCheckRadio and FormCheckRadioGroup reactivity - Enhanced BaseButton with proper disabled state handling - Better error handling and user feedback in file validation ### Data Management - Implement sophisticated change detection for all dataset fields - Add proper handling of array ordering for authors/contributors - Improve license selection with better state management - Enhanced subject/keyword processing with duplicate detection ### Technical Improvements - Optimize search indexing with conditional updates based on modification dates - Update person model column mapping for ORCID - Improve validation error messages and user guidance - Better handling of file uploads and deletion tracking ### Dependencies - Update various npm packages (AWS SDK, Babel, Vite, etc.) - Add baseline-browser-mapping for better browser compatibility ### Bug Fixes - Fix form reactivity issues with checkbox/radio groups - Improve error handling in file validation rules - Better handling of edge cases in change detection
97 lines
No EOL
3.5 KiB
TypeScript
97 lines
No EOL
3.5 KiB
TypeScript
/*
|
|
|--------------------------------------------------------------------------
|
|
| Preloaded File - node ace make:preload rules/dependentArrayMinLength
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
import { FieldContext } from '@vinejs/vine/types';
|
|
import vine, { VineArray } from '@vinejs/vine';
|
|
import { SchemaTypes } from '@vinejs/vine/types';
|
|
|
|
/**
|
|
* Options accepted by the dependentArrayMinLength rule
|
|
*/
|
|
type Options = {
|
|
min: number;
|
|
dependentArray: string;
|
|
};
|
|
|
|
async function dependentArrayMinLength(value: unknown, options: Options, field: FieldContext) {
|
|
const dependentArrayValue = field.data[options.dependentArray];
|
|
|
|
// Both values can be null/undefined or arrays, but not other types
|
|
const isMainValueValid = value === null || value === undefined || Array.isArray(value);
|
|
const isDependentValueValid = dependentArrayValue === null || dependentArrayValue === undefined || Array.isArray(dependentArrayValue);
|
|
|
|
if (!isMainValueValid || !isDependentValueValid) {
|
|
field.report(
|
|
`Invalid file data format. Please contact support if this error persists.`,
|
|
'array.dependentArrayMinLength',
|
|
field,
|
|
options,
|
|
);
|
|
return false;
|
|
}
|
|
|
|
// Convert null/undefined to empty arrays for length checking
|
|
const mainArray = Array.isArray(value) ? value : [];
|
|
const dependentArray = Array.isArray(dependentArrayValue) ? dependentArrayValue : [];
|
|
|
|
// Calculate total count across both arrays
|
|
const totalCount = mainArray.length + dependentArray.length;
|
|
|
|
// Check if minimum requirement is met
|
|
if (totalCount >= options.min) {
|
|
return true;
|
|
}
|
|
|
|
// Special case: if dependent array has items, main array can be empty/null
|
|
if (dependentArray.length >= options.min && mainArray.length === 0) {
|
|
return true;
|
|
}
|
|
|
|
// Determine appropriate error message based on context
|
|
const hasExistingFiles = dependentArray.length > 0;
|
|
const hasNewFiles = mainArray.length > 0;
|
|
|
|
if (!hasExistingFiles && !hasNewFiles) {
|
|
// No files at all
|
|
field.report(
|
|
`Your dataset must include at least {{ min }} file. Please upload a new file to continue.`,
|
|
'array.dependentArrayMinLength',
|
|
field,
|
|
options,
|
|
);
|
|
} else if (hasExistingFiles && !hasNewFiles && dependentArray.length < options.min) {
|
|
// Has existing files but marked for deletion, no new files
|
|
field.report(
|
|
`You have marked all existing files for deletion. Please upload at least {{ min }} new file or keep some existing files.`,
|
|
'array.dependentArrayMinLength',
|
|
field,
|
|
options,
|
|
);
|
|
} else {
|
|
// Generic fallback message
|
|
field.report(
|
|
`Your dataset must have at least {{ min }} file. You can either upload new files or keep existing ones.`,
|
|
'array.dependentArrayMinLength',
|
|
field,
|
|
options,
|
|
);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
export const dependentArrayMinLengthRule = vine.createRule(dependentArrayMinLength);
|
|
|
|
// Extend the VineArray interface
|
|
declare module '@vinejs/vine' {
|
|
interface VineArray<Schema extends SchemaTypes> {
|
|
dependentArrayMinLength(options: Options): this;
|
|
}
|
|
}
|
|
|
|
VineArray.macro('dependentArrayMinLength', function <Schema extends SchemaTypes>(this: VineArray<Schema>, options: Options) {
|
|
return this.use(dependentArrayMinLengthRule(options));
|
|
}); |