Files
michaelschiemer/resources/js/modules/admin/metadata-form-sync.js
2025-11-24 21:28:25 +01:00

136 lines
4.2 KiB
JavaScript

/**
* MetaData Form Auto-Sync
*
* Automatically syncs metadata from MetaDataFormComponent to ContentFormComponent
* when metadata fields are updated.
*/
export class MetaDataFormSync {
constructor(metaDataFormElement, contentFormComponentId) {
this.metaDataFormElement = metaDataFormElement;
this.contentFormComponentId = contentFormComponentId;
this.syncDebounceTimer = null;
this.SYNC_DEBOUNCE_MS = 500; // Debounce sync calls by 500ms
this.init();
}
init() {
// Listen for LiveComponent update events
this.metaDataFormElement.addEventListener('livecomponent:updated', (e) => {
this.handleMetaDataFormUpdate(e);
});
// Also listen for custom metadata events
document.addEventListener('livecomponent:event', (e) => {
const eventData = e.detail;
if (eventData && eventData.component_id) {
const metaDataFormId = this.metaDataFormElement.dataset.liveComponent;
if (eventData.component_id === metaDataFormId) {
// Check if it's a metadata-related event
if (eventData.event_name && eventData.event_name.includes('metadata:')) {
this.scheduleSync();
}
}
}
});
}
/**
* Handle MetaDataFormComponent update
*/
handleMetaDataFormUpdate(e) {
// Debounce sync to avoid too many requests
this.scheduleSync();
}
/**
* Schedule sync with debouncing
*/
scheduleSync() {
if (this.syncDebounceTimer) {
clearTimeout(this.syncDebounceTimer);
}
this.syncDebounceTimer = setTimeout(() => {
this.syncMetaData();
}, this.SYNC_DEBOUNCE_MS);
}
/**
* Sync metadata from MetaDataFormComponent to ContentFormComponent
*/
async syncMetaData() {
if (!this.contentFormComponentId) {
console.warn('MetaDataFormSync: No content form component ID');
return;
}
// Find ContentFormComponent element
const contentFormElement = document.querySelector(
`[data-live-component="${this.contentFormComponentId}"]`
);
if (!contentFormElement) {
console.warn('MetaDataFormSync: ContentFormComponent not found');
return;
}
// Get LiveComponent instance
const liveComponent = window.LiveComponents?.getComponent?.(this.contentFormComponentId);
if (!liveComponent) {
console.warn('MetaDataFormSync: LiveComponent instance not found');
return;
}
// Call syncMetaDataFromForm action on ContentFormComponent
try {
await liveComponent.action('syncMetaDataFromForm');
} catch (error) {
console.error('MetaDataFormSync: Failed to sync metadata', error);
}
}
/**
* Initialize all metadata form syncs on the page
*/
static initializeAll() {
const instances = [];
// Find all MetaDataFormComponents
const metaDataFormElements = document.querySelectorAll(
'[data-live-component^="admin-metadata-form:"]'
);
metaDataFormElements.forEach(metaDataFormElement => {
// Find parent ContentFormComponent
const contentFormElement = metaDataFormElement.closest(
'[data-live-component^="admin-content-form:"]'
);
if (contentFormElement) {
const contentFormComponentId = contentFormElement.dataset.liveComponent;
instances.push(new MetaDataFormSync(metaDataFormElement, contentFormComponentId));
}
});
return instances;
}
}
// Auto-initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
MetaDataFormSync.initializeAll();
});
} else {
MetaDataFormSync.initializeAll();
}
// Re-initialize when LiveComponents are loaded dynamically
document.addEventListener('livecomponent:loaded', () => {
MetaDataFormSync.initializeAll();
});