replace div with buttons

add code editor

handle new settings
This commit is contained in:
Simon Vieille 2024-05-23 23:58:39 +02:00
parent b9566853ef
commit 3f5bd4f950
Signed by: deblan
GPG key ID: 579388D585F70417
4 changed files with 217 additions and 40 deletions

View file

@ -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;
}
}

View file

@ -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() {

View file

@ -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">

View file

@ -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}">