replace div with buttons
add code editor handle new settings
This commit is contained in:
parent
b9566853ef
commit
3f5bd4f950
|
@ -777,7 +777,6 @@ label.required::after {
|
|||
.block-header-item {
|
||||
font-size: 12px;
|
||||
display: inline-block;
|
||||
margin-bottom: 10px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
margin-right: 2px;
|
||||
|
@ -812,15 +811,18 @@ label.required::after {
|
|||
padding: 3px 5px;
|
||||
}
|
||||
|
||||
.block-settings-inverse {
|
||||
background: none;
|
||||
border: 1px solid map-get($theme-colors, 'dark-blue');
|
||||
color: map-get($theme-colors, 'dark-blue');
|
||||
}
|
||||
|
||||
.block-settings {
|
||||
padding: 4px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.form-control {
|
||||
margin-top: 0.5rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
.block[class*="block-depth"] .block {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.block-id {
|
||||
|
@ -833,4 +835,10 @@ label.required::after {
|
|||
min-height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
dialog {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<Draggable
|
||||
v-if="Object.keys(widgets).length"
|
||||
v-if="Object.keys(widgets).length && value !== null"
|
||||
v-model="value"
|
||||
:key="blockKey"
|
||||
:animation="200"
|
||||
|
@ -24,14 +24,66 @@
|
|||
@drag-end="dragEnd"
|
||||
/>
|
||||
<div class="container">
|
||||
<BuilderBlockCreate
|
||||
:container="value"
|
||||
:widgets="widgets"
|
||||
:openedBlocks="openedBlocks"
|
||||
:allowedWidgets="[]"
|
||||
/>
|
||||
<div class="d-flex justify-content-between">
|
||||
<BuilderBlockCreate
|
||||
:container="value"
|
||||
:widgets="widgets"
|
||||
:openedBlocks="openedBlocks"
|
||||
:allowedWidgets="[]"
|
||||
/>
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm"
|
||||
v-on:click="openCodeEditor"
|
||||
>
|
||||
<i class="fas fa-code"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<textarea :name="name" class="d-none">{{ toJson(value) }}</textarea>
|
||||
<dialog ref="dialog" class="modal-dialog modal-dialog-large">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Code editor</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
v-on:click="closeCodeEditor"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<textarea
|
||||
class="form-control"
|
||||
rows="10"
|
||||
ref="codeEditor"
|
||||
v-model="nextValue"
|
||||
>
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary"
|
||||
v-on:click="closeCodeEditor"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
v-on:click="checkAndSaveNextValue"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
</Draggable>
|
||||
</template>
|
||||
|
||||
|
@ -63,7 +115,8 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
value: this.initialValue,
|
||||
value: null,
|
||||
nextValue: null,
|
||||
widgets: {},
|
||||
openedBlocks: {},
|
||||
blockKey: 0,
|
||||
|
@ -77,6 +130,72 @@ export default {
|
|||
triggerBuilderBlockEvent() {
|
||||
document.querySelector('body').dispatchEvent(new Event('builder_block.update'))
|
||||
},
|
||||
openCodeEditor() {
|
||||
this.nextValue = this.toJson(this.value)
|
||||
this.$refs.dialog.showModal()
|
||||
},
|
||||
closeCodeEditor() {
|
||||
this.$refs.dialog.close()
|
||||
},
|
||||
isNextValueItemValueValid(item) {
|
||||
const hasId = typeof item.id === 'string'
|
||||
const hasWidget = typeof item.widget === 'string' && this.widgets[item.widget]
|
||||
const hasSettings = typeof item.settings === 'object'
|
||||
const hasChildren = Array.isArray(item.children)
|
||||
|
||||
if (!hasId || !hasWidget || !hasSettings || !hasChildren) {
|
||||
return false
|
||||
}
|
||||
|
||||
for (let child of item.children) {
|
||||
if (!this.isNextValueItemValueValid(child)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
updateNextValueRecursiveIds(data) {
|
||||
if (Array.isArray(data)) {
|
||||
data.forEach((value, key) => {
|
||||
data[key] = this.updateNextValueRecursiveIds(value)
|
||||
})
|
||||
} else {
|
||||
data.id = this.makeId()
|
||||
data.children = this.updateNextValueRecursiveIds(data.children)
|
||||
}
|
||||
|
||||
return data
|
||||
},
|
||||
checkAndSaveNextValue() {
|
||||
this.$refs.codeEditor.classList.toggle('is-invalid', false)
|
||||
let hasError = false
|
||||
|
||||
try {
|
||||
let data = JSON.parse(this.nextValue)
|
||||
|
||||
if (!Array.isArray(data)) {
|
||||
hasError = true
|
||||
} else {
|
||||
for (let item of data) {
|
||||
if (!this.isNextValueItemValueValid(item)) {
|
||||
hasError = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasError) {
|
||||
this.value = this.updateNextValueRecursiveIds(data)
|
||||
++this.blockKey
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
hasError = true
|
||||
}
|
||||
|
||||
return this.$refs.codeEditor.classList.toggle('is-invalid', hasError)
|
||||
},
|
||||
removeBlock(key) {
|
||||
let newValue = []
|
||||
|
||||
|
@ -98,6 +217,45 @@ export default {
|
|||
|
||||
++this.blockKey
|
||||
},
|
||||
fixSettings(data) {
|
||||
if (Array.isArray(data)) {
|
||||
data.forEach((value, key) => {
|
||||
data[key] = this.fixSettings(value)
|
||||
})
|
||||
} else {
|
||||
const widget = this.widgets[data.widget]
|
||||
|
||||
if (!widget) {
|
||||
return data
|
||||
}
|
||||
|
||||
const nextSettings = {}
|
||||
|
||||
for (let setting in widget.settings) {
|
||||
if (data.settings.hasOwnProperty(setting)) {
|
||||
nextSettings[setting] = data.settings[setting]
|
||||
} else {
|
||||
nextSettings[setting] = widget.settings[setting].default
|
||||
}
|
||||
}
|
||||
|
||||
data.settings = nextSettings
|
||||
data.children = this.fixSettings(data.children)
|
||||
}
|
||||
|
||||
return data
|
||||
},
|
||||
makeId() {
|
||||
let result = ''
|
||||
const characters = 'abcdefghijklmnopqrstuvwxyz0123456789'
|
||||
const charactersLength = characters.length
|
||||
|
||||
for (let i = 0; i < 7; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength))
|
||||
}
|
||||
|
||||
return `block-${result}`
|
||||
},
|
||||
},
|
||||
components: {
|
||||
BuilderBlockItem,
|
||||
|
@ -105,12 +263,12 @@ export default {
|
|||
Draggable,
|
||||
},
|
||||
mounted() {
|
||||
this.triggerBuilderBlockEvent()
|
||||
const that = this
|
||||
|
||||
axios.get(Routing.generate('admin_editor_builder_block_widgets'))
|
||||
.then((response) => {
|
||||
that.widgets = response.data
|
||||
that.value = that.fixSettings(that.initialValue)
|
||||
})
|
||||
},
|
||||
created() {
|
||||
|
|
|
@ -43,9 +43,9 @@
|
|||
|
||||
<template>
|
||||
<div class="builder-add">
|
||||
<span class="btn btn-secondary" v-on:click="togglePicker">
|
||||
<button type="button" class="btn btn-secondary" v-on:click="togglePicker">
|
||||
<span class="fa fa-plus"></span>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<div class="builder-block-picker mt-2 row" :class="{'d-none': !showPicker}">
|
||||
<div class="col-auto builder-block-picker-menu">
|
||||
|
|
|
@ -5,33 +5,44 @@
|
|||
v-if="widget"
|
||||
:key="blockKey"
|
||||
>
|
||||
<div class="block-header">
|
||||
<div class="float-right">
|
||||
<div class="block-header d-flex justify-content-between">
|
||||
<div>
|
||||
<div
|
||||
class="block-header-item block-label"
|
||||
:title="item.widget"
|
||||
>
|
||||
{{ widget.label }}
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="block-header-item btn btn-sm btn-outline-secondary"
|
||||
v-on:click="toggleSettings"
|
||||
v-if="Object.keys(widget.settings).length"
|
||||
>
|
||||
<span class="fa fa-cog"></span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="block-header-item btn btn-sm btn-outline-secondary dragger"
|
||||
>
|
||||
<span class="fa fa-arrows-alt"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span class="block-id">
|
||||
{{ item.id }}
|
||||
</span>
|
||||
<div class="block-header-item text-white bg-danger" v-on:click="removeMe(item)">
|
||||
<button
|
||||
type="button"
|
||||
class="block-header-item btn btn-sm text-white bg-danger"
|
||||
v-on:click="removeMe(item)"
|
||||
>
|
||||
<span class="fa fa-trash"></span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="block-header-item block-label"
|
||||
:title="item.widget"
|
||||
>
|
||||
{{ widget.label }}
|
||||
</div>
|
||||
<div
|
||||
class="block-header-item block-settings-inverse"
|
||||
v-on:click="toggleSettings"
|
||||
v-if="Object.keys(widget.settings).length"
|
||||
>
|
||||
<span class="fa fa-cog"></span>
|
||||
</div>
|
||||
<div
|
||||
class="block-header-item block-settings-inverse dragger"
|
||||
>
|
||||
<span class="fa fa-arrows-alt"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block-settings" v-if="Object.keys(widget.settings).length" :class="{'d-none': !showSettings}">
|
||||
|
|
Loading…
Reference in a new issue