- added bando preview page;
- added bando form preview;
This commit is contained in:
26
src/pages/BandoFormsEdit/components/BuilderDropzone/index.js
Normal file
26
src/pages/BandoFormsEdit/components/BuilderDropzone/index.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import React, { useRef } from 'react';
|
||||
import { useDrop } from 'react-dnd';
|
||||
import { ItemTypes } from '../ItemTypes';
|
||||
|
||||
// store
|
||||
import { storeSet } from '../../../../store';
|
||||
|
||||
const BuilderDropzone = () => {
|
||||
const dropzoneRef = useRef();
|
||||
|
||||
const [, drop] = useDrop({
|
||||
accept: ItemTypes.FIELD,
|
||||
hover(item, monitor) {
|
||||
storeSet.main.moveElement(-1, 0, item);
|
||||
item.index = 0;
|
||||
},
|
||||
});
|
||||
|
||||
drop(dropzoneRef);
|
||||
|
||||
return (
|
||||
<div ref={dropzoneRef} className="dropzone"></div>
|
||||
)
|
||||
}
|
||||
|
||||
export default BuilderDropzone;
|
||||
@@ -7,8 +7,10 @@ import { storeSet } from '../../../../store';
|
||||
|
||||
// components
|
||||
import { Button } from 'primereact/button';
|
||||
import { Tag } from 'primereact/tag';
|
||||
import BuilderElementProperLabel from '../BuilderElementProperLabel';
|
||||
|
||||
const BuilderElement = ({ id, name, label, index, move }) => {
|
||||
const BuilderElement = ({ id, name, label, index }) => {
|
||||
const ref = useRef(null);
|
||||
|
||||
const [{ handlerId }, drop] = useDrop({
|
||||
@@ -74,17 +76,31 @@ const BuilderElement = ({ id, name, label, index, move }) => {
|
||||
}),
|
||||
});
|
||||
|
||||
const move = (dragIndex, hoverIndex, item) => {
|
||||
storeSet.main.moveElement(dragIndex, hoverIndex, item);
|
||||
}
|
||||
|
||||
const openSettings = (id) => {
|
||||
storeSet.main.activeElement(id);
|
||||
}
|
||||
|
||||
const remove = (id) => {
|
||||
storeSet.main.removeElement(id);
|
||||
}
|
||||
|
||||
const opacity = isDragging ? 0 : 1;
|
||||
drag(drop(ref));
|
||||
|
||||
return (
|
||||
<div ref={ref} className="formBuilder__element" style={{ opacity }} data-handler-id={handlerId}>
|
||||
{label}
|
||||
<Button icon="pi pi-cog" onClick={() => openSettings(id)} outlined />
|
||||
<div className="meta">
|
||||
<Tag value={name} severity="info"/>
|
||||
<BuilderElementProperLabel id={id} defaultLabel={label}/>
|
||||
</div>
|
||||
<div className="actions">
|
||||
<Button icon="pi pi-cog" onClick={() => openSettings(id)} outlined severity="info" />
|
||||
<Button icon="pi pi-trash" onClick={() => remove(id)} outlined severity="danger" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { ItemTypes } from '../ItemTypes';
|
||||
import uniqid from '../../../../helpers/uniqid';
|
||||
|
||||
|
||||
const BuilderElementItem = ({ dbId, name, label, move }) => {
|
||||
const BuilderElementItem = ({ dbId, name, label }) => {
|
||||
const ref = useRef(null);
|
||||
|
||||
const [{ isDragging }, drag] = useDrag(() => ({
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { head } from 'ramda';
|
||||
|
||||
// store
|
||||
import { useStore } from '../../../../store';
|
||||
|
||||
const BuilderElementProperLabel = ({ id, defaultLabel }) => {
|
||||
const elements = useStore().main.formElements();
|
||||
const [label, setLabel] = useState();
|
||||
|
||||
useEffect(() => {
|
||||
const element = head(elements.filter(o => o.id === id));
|
||||
const setting = head(element.settings.filter(o => o.name === 'label'));
|
||||
if (setting.value) {
|
||||
setLabel(setting.value);
|
||||
} else {
|
||||
setLabel(defaultLabel);
|
||||
}
|
||||
}, [elements]);
|
||||
|
||||
return label
|
||||
}
|
||||
|
||||
export default BuilderElementProperLabel;
|
||||
@@ -0,0 +1,67 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { head } from 'ramda';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { klona } from 'klona';
|
||||
|
||||
// store
|
||||
import { storeSet, useStore } from '../../../../store';
|
||||
|
||||
// components
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Tag } from 'primereact/tag';
|
||||
|
||||
const BuilderElementSettings = () => {
|
||||
const elements = useStore().main.elements();
|
||||
const activeElement = useStore().main.activeElement();
|
||||
const [activeElementData, setActiveElementData] = useState({});
|
||||
const [settings, setSettings] = useState([]);
|
||||
|
||||
const onChange = (value, name) => {
|
||||
const newSettings = settings
|
||||
.map(o => {
|
||||
if (o.name === name) {
|
||||
o.value = value;
|
||||
}
|
||||
|
||||
return o;
|
||||
});
|
||||
|
||||
setSettings(newSettings);
|
||||
}
|
||||
|
||||
const saveSettings = () => {
|
||||
activeElementData.settings = settings;
|
||||
const newElements = elements.map(o => o.id === activeElementData.id ? activeElementData : o);
|
||||
storeSet.main.elements(newElements);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const chosen = head(elements.filter(o => o.id === activeElement));
|
||||
if (chosen) {
|
||||
setActiveElementData(klona(chosen));
|
||||
setSettings(klona(chosen.settings));
|
||||
} else {
|
||||
setActiveElementData({});
|
||||
setSettings([]);
|
||||
}
|
||||
}, [activeElement])
|
||||
|
||||
return (activeElementData
|
||||
? <div className="formElementSettings">
|
||||
<Tag value={activeElementData.name} severity="info"/>
|
||||
{settings
|
||||
? settings.map((o) => <div className="formElementSettings__field" key={o.name}>
|
||||
<label htmlFor={o.name}>{o.name}</label>
|
||||
<InputText id={o.name} aria-describedby={`${o.name}-help`}
|
||||
value={o.value}
|
||||
onChange={(e) => onChange(e.target.value, o.name)}/>
|
||||
</div>) : null}
|
||||
|
||||
<Button label={__('Salva', 'gepafin')} onClick={saveSettings}/>
|
||||
</div>
|
||||
: null
|
||||
)
|
||||
}
|
||||
|
||||
export default BuilderElementSettings;
|
||||
@@ -1,38 +1,22 @@
|
||||
import React, { useCallback, useState, useEffect } from 'react'
|
||||
import React, { useCallback } from 'react'
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { head, isEmpty } from 'ramda';
|
||||
import { isEmpty } from 'ramda';
|
||||
|
||||
// store
|
||||
import { storeGet, storeSet, useStore } from '../../../../store';
|
||||
import { storeSet, useStore } from '../../../../store';
|
||||
|
||||
// components
|
||||
import BuilderElement from '../BuilderElement';
|
||||
import BuilderElementItem from '../BuilderElementItem';
|
||||
import { Sidebar } from 'primereact/sidebar';
|
||||
import BuilderElementSettings from '../BuilderElementSettings';
|
||||
import BuilderDropzone from '../BuilderDropzone';
|
||||
|
||||
const FormBuilder = () => {
|
||||
const [fields, setFields] = useState([]);
|
||||
const [items, setItems] = useState([]);
|
||||
const elements = useStore().main.formElements();
|
||||
const elementItems = useStore().main.elementItems();
|
||||
const activeElement = useStore().main.activeElement();
|
||||
|
||||
const moveField = useCallback((dragIndex, hoverIndex, item) => {
|
||||
setFields((prevFields) => {
|
||||
if (dragIndex === -1) {
|
||||
const configs = storeGet.main.elementItems();
|
||||
const itemCfg = head(configs.filter(o => o.id === item.dbId));
|
||||
const newItem = {
|
||||
...itemCfg,
|
||||
id: item.id,
|
||||
dbId: item.dbId
|
||||
}
|
||||
return prevFields.toSpliced(hoverIndex, 0, newItem);
|
||||
} else {
|
||||
let newFields = prevFields.toSpliced(dragIndex, 1);
|
||||
return newFields.toSpliced(hoverIndex, 0, prevFields[dragIndex]);
|
||||
}
|
||||
})
|
||||
}, []);
|
||||
|
||||
const renderField = useCallback((field, index) => {
|
||||
return (
|
||||
<BuilderElement
|
||||
@@ -41,26 +25,17 @@ const FormBuilder = () => {
|
||||
id={field.id}
|
||||
label={field.label}
|
||||
name={field.name}
|
||||
move={moveField}
|
||||
/>
|
||||
)
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const elements = storeGet.main.elements();
|
||||
const elementItems = storeGet.main.elementItems();
|
||||
setFields(elements);
|
||||
setItems(elementItems);
|
||||
}, [])
|
||||
|
||||
const renderItem = useCallback((item, index) => {
|
||||
const renderItem = useCallback((item) => {
|
||||
return (
|
||||
<BuilderElementItem
|
||||
key={item.id}
|
||||
dbId={item.id}
|
||||
label={item.label}
|
||||
name={item.name}
|
||||
move={moveField}
|
||||
/>
|
||||
)
|
||||
}, []);
|
||||
@@ -73,21 +48,21 @@ const FormBuilder = () => {
|
||||
<>
|
||||
<Sidebar visible={!isEmpty(activeElement)} onHide={closeSettings} className="formBuilder__elementSettings">
|
||||
<h2>{__('Impostazioni del campo modulo', 'gepafin')}</h2>
|
||||
<p>
|
||||
Form fields here
|
||||
</p>
|
||||
{!isEmpty(activeElement) ? <BuilderElementSettings/> : null}
|
||||
</Sidebar>
|
||||
<div className="formBuilder">
|
||||
<div className="formBuilder__main">
|
||||
<h2>{__('Trascina qui gli elementi del Form', 'gepafin')}</h2>
|
||||
<div className="formBuilder__content">
|
||||
{fields.map((field, i) => renderField(field, i))}
|
||||
{!isEmpty(elements)
|
||||
? elements.map((field, i) => renderField(field, i))
|
||||
: <BuilderDropzone/>}
|
||||
</div>
|
||||
</div>
|
||||
<div className="formBuilder__aside">
|
||||
<h2>{__('Elementi del Form', 'gepafin')}</h2>
|
||||
<ul className="formBuilder__list">
|
||||
{items.map((item) => renderItem(item))}
|
||||
{elementItems.map((item) => renderItem(item))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user