adding server side builder component and fix bugs

This commit is contained in:
F4ilji
2025-05-07 13:15:36 +05:00
parent 313eea406b
commit 76deaf75f3
3 changed files with 113 additions and 5 deletions
@@ -9,7 +9,7 @@
<BasicIcon class="size-5" name="home" />
</Link>
</li>
<li v-if="breadcrumbs.mainSection.data.title" class="text-sm">
<li v-if="breadcrumbs?.mainSection?.data?.title" class="text-sm">
<span class="flex items-center text-gray-500 hover:text-primary-hover cursor-pointer" @click.prevent="handleSectionClick(breadcrumbs.mainSection)">
<svg class="flex-shrink-0 mx-2 overflow-visible h-2.5 w-2.5 text-gray-400"
width="16" height="16"
@@ -20,7 +20,7 @@
{{ textLimit(breadcrumbs.mainSection.data.title, 25) }}
</span>
</li>
<li v-if="breadcrumbs.subSection.data.title" class="text-sm">
<li v-if="breadcrumbs?.subSection?.data?.title" class="text-sm">
<span class="flex items-center text-gray-500 hover:text-primary-hover cursor-pointer" @click.prevent="handleSubSectionClick(breadcrumbs.mainSection, breadcrumbs.subSection)">
<svg class="flex-shrink-0 mx-2 overflow-visible h-2.5 w-2.5 text-gray-400"
width="16" height="16"
@@ -1,5 +1,8 @@
<template>
<div>
<div v-if="isServer && serverSideBuilder">
<component :is="serverSideBuilder" :blocks="blocks" />
</div>
<div v-else>
<transition name="fade" mode="out-in">
<PageSkeleton v-if="loading" key="skeleton" />
<div class="space-y-6" v-else key="content">
@@ -17,13 +20,16 @@
<script>
import { defineAsyncComponent } from 'vue';
import PageSkeleton from "@/componentss/shared/builder/pageBuilder/skeletons/PageSkeleton.vue";
import ServerSideBuilder from "@/componentss/shared/builder/pageBuilder/ServerSideBuilder.vue";
export default {
name: "Builder",
components: {PageSkeleton},
components: {ServerSideBuilder, PageSkeleton},
data() {
return {
loading: true,
isServer: typeof window === 'undefined',
serverSideBuilder: null,
componentMap: {
heading: () => import('@/componentss/shared/builder/pageBuilder/blocks/HeadingBlock.vue'),
paragraph: () => import('@/componentss/shared/builder/pageBuilder/blocks/ParagraphBlock.vue'),
@@ -42,7 +48,7 @@ export default {
contact: () => import('@/componentss/shared/builder/pageBuilder/blocks/contacts/ContactSectionBlock.vue'),
slider: () => import('@/componentss/features/sliders/shared/SliderBlock.vue')
},
};
};
},
methods: {
async loadAllComponents() {
@@ -64,6 +70,11 @@ export default {
},
},
async created() {
if (this.isServer) {
// Динамически импортируем только на сервере
const module = await import('@/componentss/shared/builder/pageBuilder/ServerSideBuilder.vue');
this.serverSideBuilder = module.default;
}
await this.loadAllComponents(); // Загрузить все компоненты при создании
},
}
@@ -0,0 +1,97 @@
<template>
<div>
<component
v-for="(block, index) in blocks"
:key="index"
:is="componentMapSSR[block.type]"
:block="block"
/>
</div>
</template>
<script>
import { defineAsyncComponent } from 'vue';
import ParagraphBlock from "@/componentss/shared/builder/pageBuilder/blocks/ParagraphBlock.vue";
import BasicImageSlider from "@/componentss/shared/builder/pageBuilder/blocks/BasicImageSlider.vue";
import ImageBlock from "@/componentss/shared/builder/pageBuilder/blocks/ImageBlock.vue";
import FileBlock from "@/componentss/shared/builder/pageBuilder/blocks/FileBlock.vue";
import PersonBlock from "@/componentss/shared/builder/pageBuilder/blocks/PersonBlock.vue";
import StepperBlock from "@/componentss/shared/builder/pageBuilder/blocks/StepperBlock.vue";
import VideoBlock from "@/componentss/shared/builder/pageBuilder/blocks/VideoBlock.vue";
import TabBlock from "@/componentss/shared/builder/pageBuilder/blocks/TabBlock.vue";
import PostListBlock from "@/componentss/shared/builder/pageBuilder/blocks/PostListBlock.vue";
import PostItemBlock from "@/componentss/shared/builder/pageBuilder/blocks/PostItemBlock.vue";
import PageItemBlock from "@/componentss/shared/builder/pageBuilder/blocks/PageItemBlock.vue";
import FormBlock from "@/componentss/shared/builder/pageBuilder/blocks/FormBlock.vue";
import PageResourceList from "@/componentss/shared/builder/pageBuilder/blocks/PageResourceList.vue";
import ContactSectionBlock from "@/componentss/shared/builder/pageBuilder/blocks/contacts/ContactSectionBlock.vue";
import SliderBlock from "@/componentss/features/sliders/shared/SliderBlock.vue";
import HeadingBlock from "@/componentss/shared/builder/pageBuilder/blocks/HeadingBlock.vue";
export default {
name: "ServerSideBuilder",
components: {
HeadingBlock,
ParagraphBlock,
BasicImageSlider,
ImageBlock,
FileBlock,
PersonBlock,
StepperBlock,
VideoBlock,
TabBlock,
PostListBlock,
PostItemBlock,
PageItemBlock,
FormBlock,
PageResourceList,
ContactSectionBlock,
SliderBlock
},
data() {
return {
loading: true,
componentMapSSR: {
heading: HeadingBlock,
paragraph: ParagraphBlock,
images: BasicImageSlider,
image: ImageBlock,
files: FileBlock,
person: PersonBlock,
stepper: StepperBlock,
video: VideoBlock,
tabs: TabBlock,
postsList: PostListBlock,
postItem: PostItemBlock,
pageItem: PageItemBlock,
customForm: FormBlock,
pageResourceList: PageResourceList,
contact: ContactSectionBlock,
slider: SliderBlock
},
};
},
methods: {
},
props: {
blocks: {
type: Object,
required: true,
},
},
}
</script>
<style scoped>
/* Анимация появления */
.fade-enter-active, .fade-leave-active {
transition: opacity 0.15s ease;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
</style>