feat: new layout
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
<script setup lang="ts">
|
||||
import DynamicComponent from "~/components/dynamic-page/page-component/templates/index.vue";
|
||||
import { COLLECTION_QUERY_DROP, getValueStringWithKeyAndColon, getInputValue } from "@/utils/parseSQL";
|
||||
import { isEmpty, groupBy } from "lodash";
|
||||
import { enumPageComponentTemplates } from "@/definitions/enum";
|
||||
|
||||
const _props = defineProps<{
|
||||
dataResult?: any[];
|
||||
dataQuery?: string;
|
||||
layout?: string;
|
||||
label?: string;
|
||||
content?: any;
|
||||
}>();
|
||||
|
||||
const SETTING_OPTIONS = {
|
||||
MAX_ELEMENT: 5,
|
||||
TEMPLATE: "TYPE:Card",
|
||||
LAYOUT: "TYPE:Card_Audio",
|
||||
};
|
||||
|
||||
const COMPONENT = {
|
||||
taxonomy: enumPageComponentTemplates.ARTICLE,
|
||||
};
|
||||
|
||||
const LAYOUT_PARSE = computed(() => {
|
||||
return _props.label ? getInputValue(_props.label, "OBJECT") : {};
|
||||
});
|
||||
|
||||
const _dataResult = computed(() => {
|
||||
let _components = Array(Number(LAYOUT_PARSE.value.MAX) || SETTING_OPTIONS.MAX_ELEMENT).fill(null);
|
||||
const result = getInputValue(_props.dataResult, "ARRAY");
|
||||
result &&
|
||||
result.length > 0 &&
|
||||
_components.map((_: any, index: any) => {
|
||||
_components[index] = result[index] || null;
|
||||
});
|
||||
return _components;
|
||||
});
|
||||
|
||||
const mapActivesToItems = (index: number) => {
|
||||
if (LAYOUT_PARSE.value && LAYOUT_PARSE.value.listCss) {
|
||||
return LAYOUT_PARSE.value.listCss[index] || {};
|
||||
}
|
||||
return {};
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="collection-container border-custom" :class="[LAYOUT_PARSE['div.collection-container_Class'], LAYOUT_PARSE['collection_Class']]" @click="selectComponent" :style="LAYOUT_PARSE['div.collection-container']">
|
||||
<DynamicComponent
|
||||
v-for="(component, index) in _dataResult"
|
||||
:key="index"
|
||||
:settings="{
|
||||
template: SETTING_OPTIONS.TEMPLATE,
|
||||
layout: SETTING_OPTIONS.LAYOUT,
|
||||
label: mapActivesToItems(Number(index)),
|
||||
dataResult: !isEmpty(component) ? { ...component } : null,
|
||||
}"
|
||||
:component="COMPONENT"
|
||||
@drop-data="dropData"
|
||||
/>
|
||||
<div v-html="LAYOUT_PARSE.styleClasses"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.collection-container {
|
||||
display: grid;
|
||||
&.column {
|
||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||
}
|
||||
&.row {
|
||||
grid-template-rows: auto;
|
||||
grid-auto-flow: column;
|
||||
}
|
||||
&.border-pri {
|
||||
gap: 5px;
|
||||
}
|
||||
&.border-custom {
|
||||
border-color: #e5e5e5 !important;
|
||||
}
|
||||
&.borderLeft {
|
||||
border-left: 1px solid;
|
||||
}
|
||||
&.borderRight {
|
||||
border-right: 1px solid;
|
||||
}
|
||||
&.borderTop {
|
||||
border-top: 1px solid;
|
||||
}
|
||||
&.borderBottom {
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
.empty {
|
||||
min-height: 100px;
|
||||
border-radius: 6px;
|
||||
background: #409eff;
|
||||
}
|
||||
&.noData {
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,103 @@
|
||||
<script setup lang="ts">
|
||||
import DynamicComponent from "~/components/dynamic-page/page-component/templates/index.vue";
|
||||
import { COLLECTION_QUERY_DROP, getValueStringWithKeyAndColon, getInputValue } from "@/utils/parseSQL";
|
||||
import { isEmpty, groupBy } from "lodash";
|
||||
import { enumPageComponentTemplates } from "@/definitions/enum";
|
||||
|
||||
const _props = defineProps<{
|
||||
dataResult?: any[];
|
||||
dataQuery?: string;
|
||||
layout?: string;
|
||||
label?: string;
|
||||
content?: any;
|
||||
}>();
|
||||
|
||||
const SETTING_OPTIONS = {
|
||||
MAX_ELEMENT: 5,
|
||||
TEMPLATE: "TYPE:Card",
|
||||
LAYOUT: "TYPE:Card_Default",
|
||||
};
|
||||
|
||||
const COMPONENT = {
|
||||
taxonomy: enumPageComponentTemplates.ARTICLE,
|
||||
};
|
||||
|
||||
const LAYOUT_PARSE = computed(() => {
|
||||
return _props.label ? getInputValue(_props.label, "OBJECT") : {};
|
||||
});
|
||||
|
||||
const _dataResult = computed(() => {
|
||||
let _components = Array(Number(LAYOUT_PARSE.value.MAX) || SETTING_OPTIONS.MAX_ELEMENT).fill(null);
|
||||
const result = getInputValue(_props.dataResult, "ARRAY");
|
||||
result &&
|
||||
result.length > 0 &&
|
||||
_components.map((_: any, index: any) => {
|
||||
_components[index] = result[index] || null;
|
||||
});
|
||||
return _components;
|
||||
});
|
||||
|
||||
const mapActivesToItems = (index: number) => {
|
||||
if (LAYOUT_PARSE.value && LAYOUT_PARSE.value.listCss) {
|
||||
return LAYOUT_PARSE.value.listCss[index] || {};
|
||||
}
|
||||
return {};
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="collection-container border-custom overflow-hidden" :class="[LAYOUT_PARSE['div.collection-container_Class'], LAYOUT_PARSE['collection_Class']]" @click="selectComponent" :style="LAYOUT_PARSE['div.collection-container']">
|
||||
<DynamicComponent
|
||||
v-for="(component, index) in _dataResult"
|
||||
:key="index"
|
||||
:settings="{
|
||||
template: SETTING_OPTIONS.TEMPLATE,
|
||||
layout: SETTING_OPTIONS.LAYOUT,
|
||||
label: mapActivesToItems(Number(index)),
|
||||
dataResult: !isEmpty(component) ? { ...component } : null,
|
||||
}"
|
||||
:component="COMPONENT"
|
||||
@drop-data="dropData"
|
||||
/>
|
||||
<div v-html="LAYOUT_PARSE.styleClasses"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.collection-container {
|
||||
display: grid;
|
||||
&.column {
|
||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||
}
|
||||
&.row {
|
||||
grid-template-rows: auto;
|
||||
grid-auto-flow: column;
|
||||
}
|
||||
&.border-pri {
|
||||
gap: 5px;
|
||||
}
|
||||
&.border-custom {
|
||||
border-color: #e5e5e5 !important;
|
||||
}
|
||||
&.borderLeft {
|
||||
border-left: 1px solid;
|
||||
}
|
||||
&.borderRight {
|
||||
border-right: 1px solid;
|
||||
}
|
||||
&.borderTop {
|
||||
border-top: 1px solid;
|
||||
}
|
||||
&.borderBottom {
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
.empty {
|
||||
min-height: 100px;
|
||||
border-radius: 6px;
|
||||
background: #409eff;
|
||||
}
|
||||
&.noData {
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,2 @@
|
||||
export { default as Default_Collection } from './Default.vue'
|
||||
export { default as Audio_Collection } from './Audio.vue'
|
||||
@@ -0,0 +1,34 @@
|
||||
<script lang="ts" setup>
|
||||
import { enumPageComponentTemplate, enumPageComponentKey, enumPageComponentLayouts } from "@/definitions/enum";
|
||||
import { Default_Collection, Audio_Collection } from "./index";
|
||||
|
||||
const _props = defineProps<{
|
||||
settings: any;
|
||||
component?: any;
|
||||
content?: any;
|
||||
}>();
|
||||
const definedDynamicComponent: Record<string, any> = {
|
||||
[enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.COLLECTION]["ARTICLE"]}`]["ARTICLE_COLLECTION_DEFAULT"]]: Default_Collection,
|
||||
[enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.COLLECTION]["ARTICLE"]}`]["ARTICLE_COLLECTION_AUDIO"]]: Audio_Collection,
|
||||
};
|
||||
|
||||
const getCurrentComponent = computed(() => _props.settings.layout);
|
||||
const GET_PROPS = computed(() => {
|
||||
return () => {
|
||||
let props: any = {};
|
||||
if (_props.settings) {
|
||||
for (const [key, value] of Object.entries(_props.settings)) {
|
||||
props = {
|
||||
...props,
|
||||
[key]: value,
|
||||
};
|
||||
}
|
||||
return props;
|
||||
}
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component :is="definedDynamicComponent[getCurrentComponent]" v-bind="{ ...GET_PROPS(), component: _props.component, settings: _props.settings, content: _props.content }" />
|
||||
</template>
|
||||
@@ -1 +1 @@
|
||||
export { default as Collection_Article } from './layouts/Article.vue'
|
||||
export { default as Article_Collection } from './articles/index.vue'
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
Collection_Article
|
||||
} from "./index";
|
||||
import { enumPageComponentTemplate, enumPageComponentKey, enumPageComponentLayouts } from "@/definitions/enum";
|
||||
import { Article_Collection } from "./index";
|
||||
|
||||
const _props = defineProps<{
|
||||
settings: any;
|
||||
component?: any;
|
||||
content?: any;
|
||||
}>();
|
||||
|
||||
const definedDynamicComponent: Record<string, any> = {
|
||||
'TYPE:Article-LAYOUT:vertical-DATA:HORIZONTAL': Collection_Article,
|
||||
[enumPageComponentTemplate[enumPageComponentKey.COLLECTION]["ARTICLE"]]: Article_Collection,
|
||||
};
|
||||
|
||||
const getCurrentComponent = computed(() => `${_props.settings.layout}`);
|
||||
const getCurrentComponent = computed(() => _props.settings.template);
|
||||
const GET_PROPS = computed(() => {
|
||||
return () => {
|
||||
let props: any = {};
|
||||
@@ -29,5 +29,5 @@ const GET_PROPS = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component :is="definedDynamicComponent[getCurrentComponent]" v-bind="GET_PROPS()" />
|
||||
<component :is="definedDynamicComponent[getCurrentComponent]" v-bind="{ ...GET_PROPS(), component: _props.component, settings: _props.settings, content: _props.content }" />
|
||||
</template>
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import DynamicComponent from "~/components/dynamic-page/page-component/templates/index.vue";
|
||||
import { COLLECTION_QUERY_DROP, getValueStringWithKeyAndColon, getInputValue } from "@/utils/parseSQL";
|
||||
import { breakpoint } from "~/definitions";
|
||||
import { useWindowSize } from "@vueuse/core";
|
||||
const { width } = useWindowSize()
|
||||
const emit = defineEmits(["dropComponent", "dropData", "selectComponent"]);
|
||||
|
||||
// const store = reactive({
|
||||
// section: usePageSectionStore(),
|
||||
// });
|
||||
// const { currentScreenMode } = storeToRefs(useCmsPageStore());
|
||||
|
||||
const _props = defineProps<{
|
||||
dataResult?: any;
|
||||
dataQuery?: string;
|
||||
layout?: string;
|
||||
label?: string;
|
||||
}>();
|
||||
|
||||
const SETTING_OPTIONS = {
|
||||
MAX_ELEMENT: 5,
|
||||
TEMPLATE: "Article",
|
||||
LAYOUT: "TYPE:Card",
|
||||
};
|
||||
|
||||
const LAYOUT_PARSE = computed(() => {
|
||||
const parseLayout = _props.layout?.split("-")?.map((_layout: any) => {
|
||||
const parseItem = _layout.split(":");
|
||||
return {
|
||||
[parseItem[0]]: parseItem[1],
|
||||
};
|
||||
});
|
||||
const designObject = _props.label ? getInputValue(_props.label, "OBJECT") : {};
|
||||
return Object.assign({}, ...parseLayout, designObject);
|
||||
});
|
||||
|
||||
const _dataResult = computed(() => {
|
||||
let _components = Array(Number(LAYOUT_PARSE.value.MAX) || SETTING_OPTIONS.MAX_ELEMENT).fill(null);
|
||||
const result = getInputValue(_props.dataResult, "ARRAY");
|
||||
result &&
|
||||
result.length > 0 &&
|
||||
_components.map((_: any, index: any) => {
|
||||
_components[index] = result[index] || null;
|
||||
});
|
||||
return _components;
|
||||
});
|
||||
|
||||
async function dropData(data: any) {
|
||||
if (data) {
|
||||
const { dataResult, dataType } = data;
|
||||
const checkDataResult = getInputValue(_props.dataResult, "ARRAY");
|
||||
const result = _props.dataResult ? [...checkDataResult, { ...dataResult }] : [{ ...dataResult }];
|
||||
const getDataQuery = _props.dataQuery ? COLLECTION_QUERY_DROP(dataType, getValueStringWithKeyAndColon(_props.dataQuery) + "," + dataResult.id) : COLLECTION_QUERY_DROP(dataType, dataResult.id);
|
||||
|
||||
emit("dropData", {
|
||||
dataResult: result,
|
||||
dataType,
|
||||
dataQuery: getDataQuery,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const selectComponent = () => {
|
||||
emit("selectComponent");
|
||||
};
|
||||
|
||||
const handleActiveItem = (listKey: string[], listKeyActive: string[], index: number, listDefaultValue: any) => {
|
||||
const designObject = _props.label ? getInputValue(_props.label, "OBJECT") : {};
|
||||
const updatedDesignObject = { ...designObject };
|
||||
|
||||
const dataDefault = {
|
||||
fontSizeTitle: "defaultFontSizeTitle",
|
||||
fontWeightTitle: "defaultFontWeightTitle",
|
||||
};
|
||||
|
||||
for (let i = 0; i < listKeyActive.length; i++) {
|
||||
const keyActive = listKeyActive[i];
|
||||
const key = listKey[i];
|
||||
const defaultValue = listDefaultValue[i] || designObject[dataDefault[key]];
|
||||
|
||||
if (Array.isArray(designObject[keyActive])) {
|
||||
const isActive = designObject[keyActive].includes(index + 1);
|
||||
updatedDesignObject[key] = isActive ? designObject[key] : defaultValue;
|
||||
} else {
|
||||
delete updatedDesignObject[key];
|
||||
}
|
||||
}
|
||||
|
||||
return updatedDesignObject;
|
||||
};
|
||||
|
||||
const mapActivesToItems = (index: number) => {
|
||||
const designObject = _props.label ? getInputValue(_props.label, "OBJECT") : {};
|
||||
const output = {};
|
||||
|
||||
designObject.layoutGrid?.forEach((item: any) => {
|
||||
item.actives.forEach((active: any) => {
|
||||
output[active] = { ...item };
|
||||
});
|
||||
});
|
||||
|
||||
return output[index + 1] || {};
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="collection-container border-custom"
|
||||
:class="[LAYOUT_PARSE['LAYOUT_WRAP'] || 'vertical', ...(LAYOUT_PARSE['borderWrap']?.length > 0 ? LAYOUT_PARSE['borderWrap'] : [])]"
|
||||
@click="selectComponent"
|
||||
:style="[`grid-template-columns: repeat(${width < breakpoint.sm ? 1 : LAYOUT_PARSE['COLUMN']}, minmax(0, 1fr))`, LAYOUT_PARSE['background'] && `background: ${LAYOUT_PARSE['background']}`]"
|
||||
>
|
||||
<DynamicComponent
|
||||
v-for="(component, index) in _dataResult"
|
||||
:key="index"
|
||||
:style="[
|
||||
mapActivesToItems(index)['colSpan'] && `grid-column: span ${mapActivesToItems(index)['colSpan']} / span ${mapActivesToItems(index)['colSpan']}`,
|
||||
mapActivesToItems(index)['colStart'] && `grid-column-start: ${mapActivesToItems(index)['colStart']}`,
|
||||
mapActivesToItems(index)['colEnd'] && `grid-column-end: ${mapActivesToItems(index)['colEnd']}`,
|
||||
]"
|
||||
:settings="{
|
||||
template: SETTING_OPTIONS.TEMPLATE,
|
||||
layout: SETTING_OPTIONS.LAYOUT,
|
||||
label: handleActiveItem(['border', 'HIDE', 'fontSizeTitle', 'fontWeightTitle'], ['activesBorder', 'activesHide', 'activesFontSize', 'activesFontWeight'], index, [[], [], null, null]),
|
||||
dataResult: !isEmpty(component) ? { ...component } : null,
|
||||
}"
|
||||
@drop-data="dropData"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.collection-container {
|
||||
display: grid;
|
||||
&.border-custom {
|
||||
border-color: #e5e5e5 !important;
|
||||
}
|
||||
&.borderLeft {
|
||||
border-left: 1px solid;
|
||||
}
|
||||
&.borderRight {
|
||||
border-right: 1px solid;
|
||||
}
|
||||
&.borderTop {
|
||||
border-top: 1px solid;
|
||||
}
|
||||
&.borderBottom {
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
&.vertical {
|
||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||
}
|
||||
&.horizontal {
|
||||
grid-template-rows: auto;
|
||||
grid-auto-flow: column;
|
||||
}
|
||||
|
||||
&.noData {
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user