All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 6s
- Implemented `useDatasetChangeDetection` for tracking unsaved changes in dataset forms, including comparisons for licenses, basic properties, files, coverage, and more. - Added `useDatasetFormSubmission` for handling dataset form submissions with validation, success/error handling, and auto-save functionality.
217 lines
No EOL
6 KiB
TypeScript
217 lines
No EOL
6 KiB
TypeScript
// ====================================================================
|
|
// FILE: composables/useDatasetFormSubmission.ts
|
|
// ====================================================================
|
|
|
|
import { Ref } from 'vue';
|
|
import type { Dataset, License } from '@/Dataset';
|
|
import { InertiaForm } from '@inertiajs/vue3';
|
|
import { stardust } from '@eidellev/adonis-stardust/client';
|
|
import { notify } from '@/notiwind';
|
|
|
|
interface SubmissionOptions {
|
|
onSuccess?: (updatedDataset: Dataset) => void;
|
|
onError?: (errors: any) => void;
|
|
showNotification?: boolean;
|
|
}
|
|
|
|
export function useDatasetFormSubmission(
|
|
form: InertiaForm<Dataset>,
|
|
originalDataset: Ref<Dataset>
|
|
) {
|
|
/**
|
|
* Check if object has id attribute (type guard)
|
|
*/
|
|
const hasIdAttribute = (obj: License | number): obj is License => {
|
|
return typeof obj === 'object' && 'id' in obj;
|
|
};
|
|
|
|
/**
|
|
* Transform licenses for submission
|
|
*/
|
|
const transformLicenses = (): string[] => {
|
|
return form.licenses.map((obj) => {
|
|
if (hasIdAttribute(obj)) {
|
|
return obj.id.toString();
|
|
}
|
|
return String(obj);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Validate form before submission
|
|
*/
|
|
const validateForm = (): { valid: boolean; errors: string[] } => {
|
|
const errors: string[] = [];
|
|
|
|
// Required field validations
|
|
if (!form.language) {
|
|
errors.push('Language is required');
|
|
}
|
|
if (!form.type) {
|
|
errors.push('Dataset type is required');
|
|
}
|
|
if (!form.creating_corporation) {
|
|
errors.push('Creating corporation is required');
|
|
}
|
|
if (!form.titles || !form.titles[0]?.value) {
|
|
errors.push('Main title is required');
|
|
}
|
|
if (!form.descriptions || !form.descriptions[0]?.value) {
|
|
errors.push('Main abstract is required');
|
|
}
|
|
|
|
return {
|
|
valid: errors.length === 0,
|
|
errors,
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Handle successful submission
|
|
*/
|
|
const handleSubmitSuccess = (
|
|
updatedDataset: Dataset,
|
|
showNotification: boolean = true
|
|
) => {
|
|
// Clear deletion arrays
|
|
if (updatedDataset.subjectsToDelete) {
|
|
updatedDataset.subjectsToDelete = [];
|
|
}
|
|
if (updatedDataset.referencesToDelete) {
|
|
updatedDataset.referencesToDelete = [];
|
|
}
|
|
|
|
// Update form with fresh data from server
|
|
Object.keys(updatedDataset).forEach((key) => {
|
|
if (key !== 'licenses' && key in form) {
|
|
form[key] = updatedDataset[key];
|
|
}
|
|
});
|
|
|
|
// Clear form errors
|
|
form.clearErrors();
|
|
|
|
// Update original dataset reference
|
|
originalDataset.value = JSON.parse(JSON.stringify(updatedDataset));
|
|
|
|
// Show success notification
|
|
if (showNotification) {
|
|
notify(
|
|
{
|
|
type: 'success',
|
|
title: 'Success',
|
|
text: 'Dataset updated successfully',
|
|
},
|
|
4000,
|
|
);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Handle submission errors
|
|
*/
|
|
const handleSubmitError = (errors: any) => {
|
|
console.error('Submission errors:', errors);
|
|
|
|
notify(
|
|
{
|
|
type: 'error',
|
|
title: 'Error',
|
|
text: 'Failed to update dataset. Please check the form for errors.',
|
|
},
|
|
5000,
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Submit form with auto-save behavior
|
|
*/
|
|
const submitWithAutoSave = async (
|
|
options: SubmissionOptions = {}
|
|
): Promise<void> => {
|
|
try {
|
|
const route = stardust.route('editor.dataset.update', [form.id]);
|
|
const licenses = transformLicenses();
|
|
|
|
await form
|
|
.transform((data) => ({
|
|
...data,
|
|
licenses,
|
|
rights: 'true',
|
|
}))
|
|
.put(route, {
|
|
onSuccess: (page) => {
|
|
const updatedDataset = page.props.dataset || form.data();
|
|
handleSubmitSuccess(
|
|
updatedDataset,
|
|
options.showNotification ?? true
|
|
);
|
|
|
|
if (options.onSuccess) {
|
|
options.onSuccess(updatedDataset);
|
|
}
|
|
},
|
|
onError: (errors) => {
|
|
handleSubmitError(errors);
|
|
|
|
if (options.onError) {
|
|
options.onError(errors);
|
|
}
|
|
},
|
|
});
|
|
} catch (error) {
|
|
console.error('Unexpected error during submission:', error);
|
|
notify(
|
|
{
|
|
type: 'error',
|
|
title: 'Error',
|
|
text: 'An unexpected error occurred. Please try again.',
|
|
},
|
|
5000,
|
|
);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Standard submit with validation
|
|
*/
|
|
const submit = async (
|
|
options: SubmissionOptions = {}
|
|
): Promise<void> => {
|
|
// Validate form first
|
|
const validation = validateForm();
|
|
if (!validation.valid) {
|
|
notify(
|
|
{
|
|
type: 'error',
|
|
title: 'Validation Error',
|
|
text: validation.errors.join(', '),
|
|
},
|
|
5000,
|
|
);
|
|
return;
|
|
}
|
|
|
|
await submitWithAutoSave({
|
|
...options,
|
|
showNotification: true,
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Silent submit without notification (for auto-save)
|
|
*/
|
|
const submitSilently = async (): Promise<void> => {
|
|
await submitWithAutoSave({
|
|
showNotification: false,
|
|
});
|
|
};
|
|
|
|
return {
|
|
submit,
|
|
submitWithAutoSave,
|
|
submitSilently,
|
|
validateForm,
|
|
transformLicenses,
|
|
};
|
|
} |