Skip to content

Commit 3fa2c1e

Browse files
authored
Merge pull request #13 from ruchamahabal/editing-slots
2 parents c80b903 + baca562 commit 3fa2c1e

24 files changed

+991
-216
lines changed

frontend/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@
1111
"extract-studio-types": "tsx src/scripts/tsToJSONGenerator.ts studio"
1212
},
1313
"dependencies": {
14-
"@vitejs/plugin-vue": "^4.2.3",
14+
"@vitejs/plugin-vue": "^5.2.0",
1515
"@vueuse/components": "^10.11.1",
1616
"@vueuse/core": "^10.11.1",
1717
"ace-builds": "^1.36.2",
1818
"autoprefixer": "^10.4.2",
1919
"feather-icons": "^4.28.0",
2020
"frappe-ui": "0.1.87",
21-
"lucide-vue-next": "^0.427.0",
21+
"lucide-vue-next": "^0.468.0",
2222
"pinia": "^2.2.1",
23-
"vite": "^4.4.9",
23+
"vite": "^5.4.11",
2424
"vue": "^3.4.12",
2525
"vue-router": "^4.2.2",
2626
"vuedraggable": "^4.1.0",

frontend/src/components/AppComponent.vue

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,23 @@
77
:style="styles"
88
v-on="componentEvents"
99
>
10+
<!-- Dynamically render named slots -->
11+
<template v-for="(slot, slotName) in block.componentSlots" :key="slotName" v-slot:[slotName]>
12+
<template v-if="Array.isArray(slot.slotContent)">
13+
<AppComponent
14+
v-for="slotBlock in slot.slotContent"
15+
:block="slotBlock"
16+
:key="slotBlock.componentId"
17+
/>
18+
</template>
19+
<template v-else-if="isHTML(slot.slotContent)">
20+
<component :is="{ template: slot.slotContent }" />
21+
</template>
22+
<template v-else>
23+
{{ slot.slotContent }}
24+
</template>
25+
</template>
26+
1027
<AppComponent v-for="child in block?.children" :key="child.componentId" :block="child" />
1128
</component>
1229
</template>
@@ -17,7 +34,7 @@ import { computed, onMounted, ref, useAttrs } from "vue"
1734
import { useRouter, useRoute } from "vue-router"
1835
import { createResource } from "frappe-ui"
1936
import components from "@/data/components"
20-
import { getComponentRoot, isDynamicValue, getDynamicValue } from "@/utils/helpers"
37+
import { getComponentRoot, isDynamicValue, getDynamicValue, isHTML } from "@/utils/helpers"
2138
2239
import useAppStore from "@/stores/appStore"
2340

frontend/src/components/AppLayout/TextBlock.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ withDefaults(defineProps<TextBlockProps>(), {
1313
fontWeight: "font-normal",
1414
lineHeight: "leading-normal",
1515
textColor: "text-gray-900",
16-
text: "This is a text block",
16+
text: "Text Block",
1717
})
1818
</script>

frontend/src/components/ComponentContextMenu.vue

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<template>
22
<div>
3-
<slot :onContextMenu="showContextMenu" />
43
<ContextMenu
54
v-if="contextMenuVisible"
65
v-on-click-outside="() => (contextMenuVisible = false)"
@@ -13,27 +12,24 @@
1312
</template>
1413

1514
<script setup lang="ts">
16-
import { ref, nextTick } from "vue"
15+
import { ref, Ref } from "vue"
1716
import { vOnClickOutside } from "@vueuse/components"
1817
import ContextMenu from "@/components/ContextMenu.vue"
1918
import Block from "@/utils/block"
2019
import useStudioStore from "@/stores/studioStore"
2120
import { ContextMenuOption } from "@/types"
22-
import { getComponentBlock } from "@/utils/helpers"
23-
24-
const props = defineProps<{
25-
block: Block
26-
editable: boolean
27-
}>()
21+
import { getComponentBlock, isObjectEmpty } from "@/utils/helpers"
2822
2923
const store = useStudioStore()
3024
3125
const contextMenuVisible = ref(false)
3226
const posX = ref(0)
3327
const posY = ref(0)
3428
35-
const showContextMenu = (e: MouseEvent) => {
36-
if (props.block.isRoot() || props.editable) return
29+
const block = ref(null) as unknown as Ref<Block>
30+
const showContextMenu = (e: MouseEvent, refBlock: Block) => {
31+
block.value = refBlock
32+
if (block.value.isRoot()) return
3733
contextMenuVisible.value = true
3834
posX.value = e.pageX
3935
posY.value = e.pageY
@@ -49,24 +45,28 @@ const handleContextMenuSelect = (action: CallableFunction) => {
4945
const contextMenuOptions: ContextMenuOption[] = [
5046
{
5147
label: "Duplicate",
52-
action: () => props.block.duplicateBlock(),
48+
action: () => block.value.duplicateBlock(),
5349
},
5450
{
5551
label: "Delete",
5652
action: () => {
57-
props.block.getParentBlock()?.removeChild(props.block)
53+
block.value.deleteBlock()
5854
},
5955
condition: () => {
60-
return !props.block.isRoot() && Boolean(props.block.getParentBlock())
56+
return !block.value.isRoot() && Boolean(block.value.getParentBlock())
6157
},
6258
},
6359
{
6460
label: "Wrap In Container",
6561
action: () => {
66-
const newBlockObj = getComponentBlock("FitContainer")
67-
const parentBlock = props.block.getParentBlock()
62+
const parentBlock = block.value.getParentBlock()
6863
if (!parentBlock) return
6964
65+
const newBlockObj = getComponentBlock("FitContainer")
66+
if (block.value.isSlotBlock()) {
67+
newBlockObj.parentSlotName = block.value.parentSlotName
68+
}
69+
7070
const selectedBlocks = store.selectedBlocks || []
7171
const blockPosition = Math.min(...selectedBlocks.map(parentBlock.getChildIndex.bind(parentBlock)))
7272
const newBlock = parentBlock?.addChild(newBlockObj, blockPosition)
@@ -77,6 +77,9 @@ const contextMenuOptions: ContextMenuOption[] = [
7777
.sort((a, b) => parentBlock.getChildIndex(a) - parentBlock.getChildIndex(b))
7878
.forEach((block) => {
7979
parentBlock?.removeChild(block)
80+
if (block.parentSlotName) {
81+
delete block.parentSlotName
82+
}
8083
newBlock?.addChild(block)
8184
if (!width) {
8285
const blockWidth = block.getStyle("width") as string | undefined
@@ -95,5 +98,17 @@ const contextMenuOptions: ContextMenuOption[] = [
9598
}
9699
},
97100
},
101+
{
102+
label: "Edit Slot",
103+
action: () => {
104+
store.showSlotEditorDialog = true
105+
},
106+
condition: () =>
107+
!isObjectEmpty(block.value.componentSlots) && block.value.isSlotEditable(store.selectedSlot),
108+
},
98109
]
110+
111+
defineExpose({
112+
showContextMenu,
113+
})
99114
</script>

0 commit comments

Comments
 (0)