128 lines
3.6 KiB
Svelte
128 lines
3.6 KiB
Svelte
<script lang="ts">
|
|
import Composite from './Composite.svelte';
|
|
import components from '$lib/componentLoader';
|
|
import services from '$lib/servicesLoader';
|
|
import { createComponentStore, getComponentStore } from '$lib/stores/componentStores.ts';
|
|
|
|
export let componentsData = {
|
|
layout: '',
|
|
children: []
|
|
};
|
|
|
|
function initializeComponentState(child) {
|
|
child.store = createComponentStore(child.id, child.state || {});
|
|
|
|
if (child.children) {
|
|
child.children.forEach(initializeComponentState);
|
|
}
|
|
}
|
|
|
|
$: if (componentsData && componentsData.children) {
|
|
componentsData.children.forEach(initializeComponentState);
|
|
}
|
|
|
|
function mapAndSubscribe(component) {
|
|
console.log('Mapping and subscribing for:', component.id); // Debug line
|
|
|
|
if (component.map) {
|
|
const localStore = getComponentStore(component.id);
|
|
|
|
for (const [localKey, external] of Object.entries(component.map)) {
|
|
const [externalID, externalKey] = external.split('.').map((item) => item.trim());
|
|
const externalStore = getComponentStore(externalID);
|
|
if (externalStore) {
|
|
externalStore.subscribe((externalState) => {
|
|
console.log('External state:', externalState); // Debug line
|
|
if (externalState && externalKey in externalState) {
|
|
localStore.update((storeValue) => {
|
|
storeValue = storeValue || {};
|
|
if (storeValue[localKey] !== externalState[externalKey]) {
|
|
storeValue[localKey] = externalState[externalKey];
|
|
return storeValue;
|
|
}
|
|
return storeValue;
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
if (component.children) {
|
|
component.children.forEach(mapAndSubscribe);
|
|
}
|
|
}
|
|
|
|
$: if (componentsData && componentsData.children) {
|
|
componentsData.children.forEach(mapAndSubscribe);
|
|
}
|
|
|
|
async function getComponent(componentName) {
|
|
if (components[componentName]) {
|
|
const module = await components[componentName]();
|
|
return module.default;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
async function loadService(serviceName) {
|
|
if (services[serviceName]) {
|
|
const module = await services[serviceName]();
|
|
return module.default || module;
|
|
}
|
|
return null;
|
|
}
|
|
async function getServiceProps(component) {
|
|
const loadedServices = [];
|
|
if (component.services) {
|
|
for (const serviceName of component.services) {
|
|
const loadedService = await loadService(serviceName);
|
|
if (loadedService) {
|
|
loadedServices.push(loadedService);
|
|
}
|
|
}
|
|
}
|
|
return loadedServices;
|
|
}
|
|
</script>
|
|
|
|
<div class="grid w-full h-full" style="display: grid; {componentsData.layout || ''}">
|
|
{#each componentsData.children as component (component.id)}
|
|
{#await Promise.all( [getComponent(component.componentName), getServiceProps(component)] ) then [Component, serviceProps]}
|
|
{#if Component}
|
|
<div class="w-full h-full overflow-hidden {component.slot}">
|
|
<svelte:component
|
|
this={Component}
|
|
id={component.id}
|
|
{...component.props}
|
|
{...serviceProps.reduce((acc, currServiceModule, idx) => {
|
|
acc[component.services[idx]] = currServiceModule;
|
|
return acc;
|
|
}, {})}
|
|
/>
|
|
|
|
{#if component.actions}
|
|
<div class="flex justify-end p-4">
|
|
{#each component.actions as action}
|
|
{#await getComponent(action) then ActionComponent}
|
|
{#if ActionComponent}
|
|
<svelte:component this={ActionComponent} {...component.props} />
|
|
{:else}
|
|
<p>Action {action} not found.</p>
|
|
{/if}
|
|
{/await}
|
|
{/each}
|
|
</div>
|
|
{/if}
|
|
|
|
{#if component.children && component.children.length}
|
|
<Composite componentsData={component} />
|
|
{/if}
|
|
</div>
|
|
{:else}
|
|
<p>Component {component.componentName} not found.</p>
|
|
{/if}
|
|
{/await}
|
|
{/each}
|
|
</div>
|