add drag and drop in the block builder
This commit is contained in:
parent
857fcd9897
commit
dfbe282d0e
|
@ -17,7 +17,7 @@ class ColumnBlock extends BootstrapBlock
|
|||
->setLabel('Column')
|
||||
->setIsContainer(true)
|
||||
->setOrder(3)
|
||||
->setClass('col-12 col-md-2 pr-md-1')
|
||||
->setClass('col-12 col-lg-2 pr-md-1')
|
||||
->setTemplate('@Core/builder_block/bootstrap/column.html.twig')
|
||||
->setIcon('<i class="fas fa-columns"></i>')
|
||||
->addSetting(name: 'size', label: 'Extra small', type: 'number', attributes: ['min' => 0, 'max' => 12])
|
||||
|
|
|
@ -16,7 +16,7 @@ class ContainerBlock extends BootstrapBlock
|
|||
->setName('bsContainer')
|
||||
->setLabel('Container')
|
||||
->setIsContainer(true)
|
||||
->setOrder(2)
|
||||
->setOrder(1)
|
||||
->setTemplate('@Core/builder_block/bootstrap/container.html.twig')
|
||||
->setIcon('<i class="fas fa-th"></i>')
|
||||
->addSetting(name: 'isFluid', label: 'Fluid', type: 'checkbox')
|
||||
|
|
|
@ -15,7 +15,7 @@ class RowBlock extends BootstrapBlock
|
|||
$this
|
||||
->setName('bsRow')
|
||||
->setLabel('Row')
|
||||
->setOrder(1)
|
||||
->setOrder(2)
|
||||
->setIsContainer(true)
|
||||
->setIcon('<i class="fas fa-align-justify"></i>')
|
||||
->setTemplate('@Core/builder_block/bootstrap/row.html.twig')
|
||||
|
|
|
@ -799,10 +799,17 @@ label.required::after {
|
|||
|
||||
.block-settings {
|
||||
padding: 4px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.block-id {
|
||||
font-size: 12px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.block-show-dropzone {
|
||||
.block-dropzone {
|
||||
min-height: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,25 @@
|
|||
<template>
|
||||
<div class="block" :key="blockKey" v-if="Object.keys(widgets).length">
|
||||
<Draggable
|
||||
v-if="Object.keys(widgets).length"
|
||||
v-model="value"
|
||||
:key="blockKey"
|
||||
:animation="200"
|
||||
group="children"
|
||||
ghost-class="ghost"
|
||||
@start="dragStart"
|
||||
@end="dragEnd"
|
||||
handle=".dragger"
|
||||
:class="{'block-show-dropzone': showDragDrop}"
|
||||
class="block"
|
||||
>
|
||||
<BuilderBlockItem
|
||||
v-for="(block, key) in value"
|
||||
:key="block.id + '-' + key"
|
||||
:item="block"
|
||||
:widgets="widgets"
|
||||
:isFirst="key === 0"
|
||||
:isLast="key == Object.keys(value)[Object.keys(value).length -1]"
|
||||
@remove-item="removeBlock(key)"
|
||||
@move-item-up="moveBlockUp(key)"
|
||||
@move-item-down="moveBlockDown(key)"
|
||||
@drag-start="dragStart"
|
||||
@drag-end="dragEnd"
|
||||
/>
|
||||
<div class="container">
|
||||
<BuilderBlockCreate
|
||||
|
@ -19,13 +29,14 @@
|
|||
/>
|
||||
</div>
|
||||
<textarea :name="name" class="d-none">{{ toJson(value) }}</textarea>
|
||||
</div>
|
||||
</Draggable>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BuilderBlockItem from './BuilderBlockItem'
|
||||
import BuilderBlockCreate from './BuilderBlockCreate'
|
||||
import Routing from '../../../../../../../../../friendsofsymfony/jsrouting-bundle/Resources/public/js/router.min.js'
|
||||
import Draggable from 'vuedraggable'
|
||||
|
||||
const axios = require('axios').default
|
||||
const routes = require('../../../../../../../../../../public/js/fos_js_routes.json')
|
||||
|
@ -51,7 +62,8 @@ export default {
|
|||
return {
|
||||
value: this.initialValue,
|
||||
widgets: {},
|
||||
blockKey: 0
|
||||
blockKey: 0,
|
||||
showDragDrop: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -61,26 +73,6 @@ export default {
|
|||
triggerBuilderBlockEvent() {
|
||||
document.querySelector('body').dispatchEvent(new Event('builder_block.update'))
|
||||
},
|
||||
moveBlockUp(key) {
|
||||
let newValue = this.value.map((x) => x)
|
||||
|
||||
newValue[key-1] = this.value[key]
|
||||
newValue[key] = this.value[key-1]
|
||||
|
||||
this.value = newValue
|
||||
|
||||
++this.blockKey
|
||||
},
|
||||
moveBlockDown(key) {
|
||||
let newValue = this.value.map((x) => x)
|
||||
|
||||
newValue[key+1] = this.value[key]
|
||||
newValue[key] = this.value[key+1]
|
||||
|
||||
this.value = newValue
|
||||
|
||||
++this.blockKey
|
||||
},
|
||||
removeBlock(key) {
|
||||
let newValue = []
|
||||
|
||||
|
@ -92,12 +84,21 @@ export default {
|
|||
|
||||
this.value = newValue
|
||||
|
||||
// ++this.blockKey
|
||||
++this.blockKey
|
||||
},
|
||||
dragStart() {
|
||||
this.showDragDrop = true
|
||||
},
|
||||
dragEnd() {
|
||||
this.showDragDrop = false
|
||||
|
||||
++this.blockKey
|
||||
},
|
||||
},
|
||||
components: {
|
||||
BuilderBlockItem,
|
||||
BuilderBlockCreate,
|
||||
Draggable,
|
||||
},
|
||||
mounted() {
|
||||
this.triggerBuilderBlockEvent()
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
}
|
||||
|
||||
.widget {
|
||||
display: inline-block;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.widget-content {
|
||||
|
@ -48,22 +48,22 @@
|
|||
<span class="fa fa-plus"></span>
|
||||
</span>
|
||||
|
||||
<div class="categories mt-2 list-group" :class="{'d-none': !showPicker}">
|
||||
<div class="categories mt-2" :class="{'d-none': !showPicker}">
|
||||
<div
|
||||
v-for="category in categories()"
|
||||
v-if="Object.keys(category.widgets).length"
|
||||
class="category"
|
||||
class="category row"
|
||||
>
|
||||
<div
|
||||
v-if="category.label != 'none'"
|
||||
v-text="category.label"
|
||||
class="category-label row"
|
||||
class="category-label col-12"
|
||||
></div>
|
||||
|
||||
<div
|
||||
v-for="(widget, name) in category.widgets"
|
||||
v-on:click="add(name, widget)"
|
||||
class="widget col-3"
|
||||
class="widget col-auto"
|
||||
>
|
||||
<div class="widget-content">
|
||||
<div class="widget-label">
|
||||
|
|
|
@ -22,26 +22,17 @@
|
|||
>
|
||||
<span class="fa fa-cog"></span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="!isFirst"
|
||||
v-on:click="moveMeUp"
|
||||
class="block-header-item block-settings-inverse"
|
||||
class="block-header-item block-settings-inverse dragger"
|
||||
>
|
||||
<span class="fas fa-arrow-up"></span>
|
||||
</div>
|
||||
<div
|
||||
v-if="!isLast"
|
||||
v-on:click="moveMeDown"
|
||||
class="block-header-item block-settings-inverse"
|
||||
>
|
||||
<span class="fas fa-arrow-down"></span>
|
||||
<span class="fa fa-arrows-alt"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block-settings" v-if="Object.keys(widget.settings).length" :class="{'d-none': !showSettings}">
|
||||
<div class="row">
|
||||
<BuilderBlockSetting
|
||||
class="mb-0"
|
||||
v-for="(params, setting) in widget.settings"
|
||||
:key="item.id + '-' + setting"
|
||||
:class="widget.class"
|
||||
|
@ -52,18 +43,28 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<BuilderBlockItem
|
||||
v-if="item.children !== null && item.children.length > 0"
|
||||
v-for="(child, key) in item.children"
|
||||
:key="child.id"
|
||||
:item="child"
|
||||
:widgets="widgets"
|
||||
:isFirst="key === 0"
|
||||
:isLast="key == Object.keys(item.children)[Object.keys(item.children).length -1]"
|
||||
@remove-item="removeBlock(key)"
|
||||
@move-item-up="moveBlockUp(key)"
|
||||
@move-item-down="moveBlockDown(key)"
|
||||
/>
|
||||
<Draggable
|
||||
v-if="widget.isContainer"
|
||||
v-model="item.children"
|
||||
ghost-class="ghost"
|
||||
group="children"
|
||||
@start="dragStart"
|
||||
@end="dragEnd"
|
||||
:animation="200"
|
||||
handle=".dragger"
|
||||
class="block-dropzone"
|
||||
>
|
||||
<BuilderBlockItem
|
||||
v-if="item.children !== null && item.children.length > 0"
|
||||
v-for="(child, key) in item.children"
|
||||
:key="child.id"
|
||||
:item="child"
|
||||
:widgets="widgets"
|
||||
@remove-item="removeBlock(key)"
|
||||
@drag-start="dragStart"
|
||||
@drag-end="dragEnd"
|
||||
/>
|
||||
</Draggable>
|
||||
|
||||
<div v-if="widget.isContainer" class="container">
|
||||
<BuilderBlockCreate
|
||||
|
@ -78,6 +79,7 @@
|
|||
<script>
|
||||
import BuilderBlockCreate from './BuilderBlockCreate'
|
||||
import BuilderBlockSetting from './BuilderBlockSetting'
|
||||
import Draggable from 'vuedraggable'
|
||||
|
||||
export default {
|
||||
name: 'BuilderBlockItem',
|
||||
|
@ -90,20 +92,12 @@ export default {
|
|||
type: Object,
|
||||
required: true
|
||||
},
|
||||
isFirst: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
isLast: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
widget: null,
|
||||
showSettings: false,
|
||||
blockKey: 0
|
||||
blockKey: 0,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -113,32 +107,6 @@ export default {
|
|||
removeMe() {
|
||||
this.$emit('remove-item')
|
||||
},
|
||||
moveMeUp() {
|
||||
this.$emit('move-item-up')
|
||||
},
|
||||
moveMeDown() {
|
||||
this.$emit('move-item-down')
|
||||
},
|
||||
moveBlockUp(key) {
|
||||
let newValue = this.item.children.map((x) => x)
|
||||
|
||||
newValue[key-1] = this.item.children[key]
|
||||
newValue[key] = this.item.children[key-1]
|
||||
|
||||
this.item.children = newValue
|
||||
|
||||
++this.blockKey
|
||||
},
|
||||
moveBlockDown(key) {
|
||||
let newValue = this.item.children.map((x) => x)
|
||||
|
||||
newValue[key+1] = this.item.children[key]
|
||||
newValue[key] = this.item.children[key+1]
|
||||
|
||||
this.item.children = newValue
|
||||
|
||||
++this.blockKey
|
||||
},
|
||||
removeBlock(key) {
|
||||
let children = []
|
||||
|
||||
|
@ -151,10 +119,18 @@ export default {
|
|||
this.item.children = children
|
||||
++this.blockKey
|
||||
},
|
||||
dragStart() {
|
||||
this.$emit('drag-start')
|
||||
},
|
||||
dragEnd() {
|
||||
this.$emit('drag-end')
|
||||
++this.blockKey
|
||||
},
|
||||
},
|
||||
components: {
|
||||
BuilderBlockCreate,
|
||||
BuilderBlockSetting,
|
||||
Draggable,
|
||||
},
|
||||
mounted() {
|
||||
this.widget = this.widgets[this.item.widget]
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
<template>
|
||||
<div class="form-group">
|
||||
<label
|
||||
v-if="params.label && params.type !== 'checkbox'"
|
||||
v-text="params.label"
|
||||
>
|
||||
</label>
|
||||
<label class="form-group mb-2">
|
||||
<span v-if="params.label && params.type !== 'checkbox'" v-text="params.label"></span>
|
||||
|
||||
<input
|
||||
v-if="['number', 'checkbox', 'text'].includes(params.type)"
|
||||
|
@ -14,11 +10,7 @@
|
|||
:class="{'form-control': params.type !== 'checkbox'}"
|
||||
/>
|
||||
|
||||
<label
|
||||
v-if="params.label && params.type == 'checkbox'"
|
||||
v-text="params.label"
|
||||
>
|
||||
</label>
|
||||
<span v-if="params.label && params.type == 'checkbox'" v-text="params.label"></span>
|
||||
|
||||
<textarea
|
||||
v-if="params.type == 'textarea'"
|
||||
|
@ -37,7 +29,7 @@
|
|||
{{ v.text }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -59,3 +51,9 @@ export default {
|
|||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
label > span {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in a new issue