feat: enhanced dataset management and UI improvements
Some checks failed
CI Pipeline / japa-tests (push) Failing after 1m10s

- Submitter/DatasetController.ts: improved validations for time_absolute, time_min, and time_max.
- validators/dataset.ts: enhanced validations for time_absolute, time_min, and time_max.
- Added new favicon.ico for better branding.
- Improved password-meter.vue component with clearer hint messages.
- Updated checkStrength.ts: enhanced checkStrength() method for password strength validation.
- submitter/Dataset/Create.vue: added form controls for time_min, time_max, and/or time_absolute fields.
- submitter/Dataset/Edit.vue: introduced a loading spinner during file upload for better UX.
This commit is contained in:
Kaimbacher 2025-01-08 11:45:03 +01:00
parent f67b736a88
commit d1480b1240
17 changed files with 2682 additions and 1446 deletions

View file

@ -115,16 +115,6 @@ export default class DatasetController {
const projects = await Project.query().pluck('label', 'id');
// const doctypes = {
// analysisdata: { label: 'Analysis', value: 'analysisdata' },
// measurementdata: { label: 'Measurements', value: 'measurementdata' },
// monitoring: 'Monitoring',
// remotesensing: 'Remote Sensing',
// gis: 'GIS',
// models: 'Models',
// mixedtype: 'Mixed Type',
// vocabulary: 'Vocabulary',
// };
return inertia.render('Submitter/Dataset/Create', {
licenses: licenses,
doctypes: DatasetTypes,
@ -358,6 +348,17 @@ export default class DatasetController {
depth_absolut: vine.number().negative().optional(),
depth_min: vine.number().negative().optional().requiredIfExists('depth_max'),
depth_max: vine.number().negative().optional().requiredIfExists('depth_min'),
time_abolute: vine.date({ formats: { utc: true } }).optional(),
time_min: vine
.date({ formats: { utc: true } })
.beforeField('time_max')
.optional()
.requiredIfExists('time_max'),
time_max: vine
.date({ formats: { utc: true } })
.afterField('time_min')
.optional()
.requiredIfExists('time_min'),
}),
references: vine
.array(
@ -647,11 +648,13 @@ export default class DatasetController {
'required': '{{ field }} is required',
'unique': '{{ field }} must be unique, and this value is already taken',
// 'confirmed': '{{ field }} is not correct',
'licenses.minLength': 'at least {{ min }} permission must be defined',
'licenses.array.minLength': 'at least {{ min }} licence must be defined',
'licenses.*.number': 'Define roles as valid numbers',
'rights.in': 'you must agree to continue',
// 'titles.array.minLength': 'Main Title is required',
'titles.0.value.minLength': 'Main Title must be at least {{ min }} characters long',
'titles.0.value.maxLength': 'Main Title must be less than {{ max }} characters long',
'titles.0.value.required': 'Main Title is required',
'titles.*.value.required': 'Additional title is required, if defined',
'titles.*.type.required': 'Additional title type is required',
@ -668,7 +671,7 @@ export default class DatasetController {
'The language of the translated description must be different from the language of the dataset',
'authors.array.minLength': 'at least {{ min }} author must be defined',
'authors.distinct': 'The {{ field }} array must have unique values based on the {{ fields }} attribute.',
'authors.array.distinct': 'The {{ field }} array must have unique values based on the {{ fields }} attribute.',
'authors.*.email.isUnique': 'the email of the new creator already exists in the database',
'contributors.*.pivot_contributor_type.required': 'contributor type is required, if defined',
'contributors.distinct': 'The {{ field }} array must have unique values based on the {{ fields }} attribute.',

View file

@ -110,6 +110,17 @@ export const createDatasetValidator = vine.compile(
depth_absolut: vine.number().negative().optional(),
depth_min: vine.number().negative().optional().requiredIfExists('depth_max'),
depth_max: vine.number().negative().optional().requiredIfExists('depth_min'),
time_abolute: vine.date({ formats: { utc: true } }).optional(),
time_min: vine
.date({ formats: { utc: true } })
.beforeField('time_max')
.optional()
.requiredIfExists('time_max'),
time_max: vine
.date({ formats: { utc: true } })
.afterField('time_min')
.optional()
.requiredIfExists('time_min'),
}),
references: vine
.array(
@ -246,6 +257,17 @@ export const updateDatasetValidator = vine.compile(
depth_absolut: vine.number().negative().optional(),
depth_min: vine.number().negative().optional().requiredIfExists('depth_max'),
depth_max: vine.number().negative().optional().requiredIfExists('depth_min'),
time_abolute: vine.date({ formats: { utc: true } }).optional(),
time_min: vine
.date({ formats: { utc: true } })
.beforeField('time_max')
.optional()
.requiredIfExists('time_max'),
time_max: vine
.date({ formats: { utc: true } })
.afterField('time_min')
.optional()
.requiredIfExists('time_min'),
}),
references: vine
.array(
@ -269,23 +291,22 @@ export const updateDatasetValidator = vine.compile(
.distinct('value'),
// last step
files: vine
.array(
vine
.myfile({
size: '512mb',
//extnames: extensions,
})
.allowedMimetypeExtensions()
.filenameLength({ clientNameSizeLimit: 100 })
.fileScan({ removeInfected: true }),
).dependentArrayMinLength({ dependentArray: 'fileInputs', min: 1}),
fileInputs: vine
.array(
vine
.object({
label: vine.string().trim().maxLength(100),
//extnames: extensions,
})
.array(
vine
.myfile({
size: '512mb',
//extnames: extensions,
})
.allowedMimetypeExtensions()
.filenameLength({ clientNameSizeLimit: 100 })
.fileScan({ removeInfected: true }),
)
.dependentArrayMinLength({ dependentArray: 'fileInputs', min: 1 }),
fileInputs: vine.array(
vine.object({
label: vine.string().trim().maxLength(100),
//extnames: extensions,
}),
),
}),
);

View file

@ -128,12 +128,12 @@ export class VanillaErrorReporter implements ErrorReporterContract {
const error: SimpleError = {
message,
rule,
field: field.wildCardPath ?field.wildCardPath.split('.')[0] : field.getFieldPath(),
field: field.getFieldPath(), // ?field.wildCardPath.split('.')[0] : field.getFieldPath(),
};
// field: 'titles.0.value'
// message: 'Main Title is required'
// rule: 'required' "required"
if (meta) {
error.meta = meta;
}
@ -141,14 +141,16 @@ export class VanillaErrorReporter implements ErrorReporterContract {
// error.index = field.name;
// }
this.hasErrors = true;
var test = field.getFieldPath();
// this.errors.push(error);
// if (this.errors[error.field]) {
// this.errors[error.field]?.push(message);
// }
// }
if (field.isArrayMember) {
// Check if the field has wildCardPath and if the error field already exists
if (this.errors[error.field] && field.wildCardPath) {
if (this.errors[error.field]) {
// Do nothing, as we don't want to push further messages
} else {
// If the error field already exists, push the message
@ -159,10 +161,18 @@ export class VanillaErrorReporter implements ErrorReporterContract {
}
}
} else {
// normal field
this.errors[error.field] = [message];
if (this.errors[error.field]) {
this.errors[error.field]?.push(message);
} else {
this.errors[error.field] = [message];
}
}
// } else {
// // normal field
// this.errors[field.field] = [message];
// }
/**
* Collecting errors as per the JSONAPI spec
*/