hot-fix: Add ORCID validation and improve dataset editing UX
### 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
This commit is contained in:
parent
06ed2f3625
commit
8f67839f93
16 changed files with 2657 additions and 1168 deletions
|
@ -38,32 +38,82 @@ const props = defineProps({
|
|||
},
|
||||
});
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
const computedValue = computed({
|
||||
// get: () => props.modelValue,
|
||||
get: () => {
|
||||
// const ids = props.modelValue.map((obj) => obj.id);
|
||||
// return ids;
|
||||
if (Array.isArray(props.modelValue)) {
|
||||
if (props.modelValue.every((item) => typeof item === 'number')) {
|
||||
return props.modelValue;
|
||||
} else if (props.modelValue.every((item) => hasIdAttribute(item))) {
|
||||
const ids = props.modelValue.map((obj) => obj.id);
|
||||
return ids;
|
||||
}
|
||||
return props.modelValue;
|
||||
}
|
||||
// return props.modelValue;
|
||||
},
|
||||
set: (value) => {
|
||||
emit('update:modelValue', value);
|
||||
},
|
||||
});
|
||||
// const computedValue = computed({
|
||||
// // get: () => props.modelValue,
|
||||
// get: () => {
|
||||
// // const ids = props.modelValue.map((obj) => obj.id);
|
||||
// // return ids;
|
||||
// if (Array.isArray(props.modelValue)) {
|
||||
// if (props.modelValue.every((item) => typeof item === 'number')) {
|
||||
// return props.modelValue;
|
||||
// } else if (props.modelValue.every((item) => hasIdAttribute(item))) {
|
||||
// const ids = props.modelValue.map((obj) => obj.id);
|
||||
// return ids;
|
||||
// }
|
||||
// return props.modelValue;
|
||||
// }
|
||||
// // return props.modelValue;
|
||||
// },
|
||||
// set: (value) => {
|
||||
// emit('update:modelValue', value);
|
||||
// },
|
||||
// });
|
||||
|
||||
// Define a type guard to check if an object has an 'id' attribute
|
||||
// function hasIdAttribute(obj: any): obj is { id: any } {
|
||||
// return typeof obj === 'object' && 'id' in obj;
|
||||
// }
|
||||
|
||||
const computedValue = computed({
|
||||
get: () => {
|
||||
if (!props.modelValue) return props.modelValue;
|
||||
|
||||
if (Array.isArray(props.modelValue)) {
|
||||
// Handle empty array
|
||||
if (props.modelValue.length === 0) return [];
|
||||
|
||||
// If all items are objects with id property
|
||||
if (props.modelValue.every((item) => hasIdAttribute(item))) {
|
||||
return props.modelValue.map((obj) => {
|
||||
// Ensure we return the correct type based on the options keys
|
||||
const id = obj.id;
|
||||
// Check if options keys are numbers or strings
|
||||
const optionKeys = Object.keys(props.options);
|
||||
if (optionKeys.length > 0) {
|
||||
// If option keys are numeric strings, return number
|
||||
if (optionKeys.every(key => !isNaN(Number(key)))) {
|
||||
return Number(id);
|
||||
}
|
||||
}
|
||||
return String(id);
|
||||
});
|
||||
}
|
||||
|
||||
// If all items are numbers
|
||||
if (props.modelValue.every((item) => typeof item === 'number')) {
|
||||
return props.modelValue;
|
||||
}
|
||||
|
||||
// If all items are strings that represent numbers
|
||||
if (props.modelValue.every((item) => typeof item === 'string' && !isNaN(Number(item)))) {
|
||||
// Convert to numbers if options keys are numeric
|
||||
const optionKeys = Object.keys(props.options);
|
||||
if (optionKeys.length > 0 && optionKeys.every(key => !isNaN(Number(key)))) {
|
||||
return props.modelValue.map(item => Number(item));
|
||||
}
|
||||
return props.modelValue;
|
||||
}
|
||||
|
||||
// Return as-is for other cases
|
||||
return props.modelValue;
|
||||
}
|
||||
|
||||
return props.modelValue;
|
||||
},
|
||||
set: (value) => {
|
||||
emit('update:modelValue', value);
|
||||
},
|
||||
});
|
||||
const hasIdAttribute = (obj: any): obj is { id: any } => {
|
||||
return typeof obj === 'object' && 'id' in obj;
|
||||
};
|
||||
|
@ -110,7 +160,7 @@ const inputElClass = computed(() => {
|
|||
</div>
|
||||
<!-- <FormCheckRadio v-for="(value, key) in options" :key="key" v-model="computedValue" :type="type"
|
||||
:name="name" :input-value="key" :label="value" :class="componentClass" /> -->
|
||||
<FormCheckRadio v-for="(value, key) in options" :key="key" v-model="computedValue" :type="type"
|
||||
<FormCheckRadio v-for="(value, key) in options" key="`${name}-${key}-${JSON.stringify(computedValue)}`" v-model="computedValue" :type="type"
|
||||
:name="name" :input-value="isNaN(Number(key)) ? key : Number(key)" :label="value" :class="componentClass" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
Loading…
Add table
editor.link_modal.header
Reference in a new issue