- updates;
This commit is contained in:
4
src/assets/scss/components/reactFlow.scss
Normal file
4
src/assets/scss/components/reactFlow.scss
Normal file
@@ -0,0 +1,4 @@
|
||||
.reactFlow__wrapper {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
}
|
||||
@@ -35,4 +35,5 @@
|
||||
@import "./components/pageBando.scss";
|
||||
@import "./components/formBuilder.scss";
|
||||
@import "./components/misc.scss";
|
||||
@import "./components/login.scss";
|
||||
@import "./components/login.scss";
|
||||
@import "./components/reactFlow.scss";
|
||||
95
src/components/FlowBuilder/index.js
Normal file
95
src/components/FlowBuilder/index.js
Normal file
@@ -0,0 +1,95 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {
|
||||
ReactFlow,
|
||||
Background,
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
addEdge,
|
||||
getIncomers,
|
||||
getOutgoers,
|
||||
getConnectedEdges,
|
||||
} from '@xyflow/react';
|
||||
import { isEmpty } from 'ramda';
|
||||
|
||||
import '@xyflow/react/dist/style.css';
|
||||
|
||||
const FlowBuilder = ({ initialForm = 0, finalForm = 0, forms = [], updateFn }) => {
|
||||
const [nodes, setNodes] = useState([]);
|
||||
const [edges, setEdges] = useState([]);
|
||||
|
||||
const range = (start, stop, step) => {
|
||||
return Array.from(
|
||||
{ length: (stop - start) / step + 1 },
|
||||
(_, i) => start + i * step
|
||||
);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (initialForm && finalForm && forms.length) {
|
||||
const total = (forms.length - 2) * (200 - 90);
|
||||
let coordinates = range(total * -1, total, 200);
|
||||
|
||||
const initialNodes = forms.map(o => {
|
||||
let obj;
|
||||
|
||||
if (o.id === initialForm) {
|
||||
obj = {
|
||||
id: String(o.id),
|
||||
type: 'input',
|
||||
data: { label: o.label },
|
||||
position: { x: 0, y: 0 },
|
||||
}
|
||||
} else if (o.id === finalForm) {
|
||||
obj = {
|
||||
id: String(o.id),
|
||||
type: 'output',
|
||||
data: { label: o.label },
|
||||
position: { x: 0, y: 300 },
|
||||
}
|
||||
} else {
|
||||
const x = coordinates.splice(0, 1);
|
||||
obj = {
|
||||
id: String(o.id),
|
||||
data: { label: o.label },
|
||||
position: { x, y: 150 },
|
||||
}
|
||||
}
|
||||
return obj
|
||||
});
|
||||
|
||||
let edges = [];
|
||||
forms.map(o => {
|
||||
if (o.id !== initialForm && o.id !== finalForm) {
|
||||
edges.push({ id: `${initialForm}->${o.id}`, source: String(initialForm), target: String(o.id) });
|
||||
edges.push({ id: `${o.id}->${finalForm}`, source: String(o.id), target: String(finalForm) });
|
||||
}
|
||||
});
|
||||
|
||||
setNodes(initialNodes);
|
||||
setEdges(edges);
|
||||
updateFn(edges);
|
||||
} else {
|
||||
setNodes([]);
|
||||
setEdges([]);
|
||||
}
|
||||
}, [initialForm, finalForm, forms]);
|
||||
|
||||
return (
|
||||
!isEmpty(nodes) && !isEmpty(edges)
|
||||
? <div className="reactFlow__wrapper">
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
nodesDraggable={false}
|
||||
nodesConnectable={false}
|
||||
fitView
|
||||
attributionPosition="top-right"
|
||||
>
|
||||
<Background variant="dots" gap={12} size={1}/>
|
||||
</ReactFlow>
|
||||
</div>
|
||||
: null
|
||||
);
|
||||
}
|
||||
|
||||
export default FlowBuilder;
|
||||
@@ -17,9 +17,9 @@ const ProtectedRoute = () => {
|
||||
return (<Navigate to={'/login?redirectReason=auth_required'} replace/>);
|
||||
}
|
||||
|
||||
if (window.location.pathname === '/') {
|
||||
/*if (window.location.pathname === '/') {
|
||||
return (<Navigate to={'/'} replace/>);
|
||||
}
|
||||
}*/
|
||||
|
||||
return <Outlet/>;
|
||||
}
|
||||
|
||||
128
src/pages/BandoFlowEdit/index.js
Normal file
128
src/pages/BandoFlowEdit/index.js
Normal file
@@ -0,0 +1,128 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
|
||||
// store
|
||||
import { storeSet, useStore } from '../../store';
|
||||
|
||||
// components
|
||||
import { Button } from 'primereact/button';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
import FormsService from '../../service/forms-service';
|
||||
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
|
||||
import FlowBuilder from '../../components/FlowBuilder';
|
||||
|
||||
const BandoFlowEdit = () => {
|
||||
const { id } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [forms, setForms] = useState([]);
|
||||
const [formOptions, setFormOptions] = useState([]);
|
||||
const [initialForm, setInitialForm] = useState(0);
|
||||
const [finalForm, setFinalForm] = useState(0);
|
||||
const isAsyncRequest = useStore().main.isAsyncRequest();
|
||||
|
||||
const getBandoId = () => {
|
||||
const parsed = parseInt(id)
|
||||
return !isNaN(parsed) ? parsed : 0;
|
||||
}
|
||||
|
||||
const goBack = () => {
|
||||
const bandoId = getBandoId();
|
||||
navigate(`/bandi/${bandoId}/forms`);
|
||||
}
|
||||
|
||||
const doSave = () => {
|
||||
console.log('doSave');
|
||||
}
|
||||
|
||||
const updateEdges = (data) => {
|
||||
|
||||
}
|
||||
|
||||
const getFormsCallback = (data) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
const formOptions = data.data.map(o => ({label: o.label, value: o.id}))
|
||||
setForms(data.data);
|
||||
setFormOptions(formOptions);
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errGetFormsCallback = (data) => {
|
||||
set404FromErrorResponse(data);
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const bandoId = getBandoId();
|
||||
storeSet.main.setAsyncRequest();
|
||||
FormsService.getFormsForCall(bandoId, getFormsCallback, errGetFormsCallback);
|
||||
}, [id]);
|
||||
|
||||
return (
|
||||
<div className="appPage">
|
||||
<div className="appPage__pageHeader">
|
||||
<h1>{__('Gestisci flusso dei form', 'gepafin')}</h1>
|
||||
<p>
|
||||
{__('Scegli un form iniziale e li form finale e aggiungi i form intermedi per questo bando', 'gepafin')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<div className="row">
|
||||
<div className="appForm__field">
|
||||
<label htmlFor="initialForm">{__('Scegli form iniziale', 'gepafin')}</label>
|
||||
<Dropdown
|
||||
id="initialForm"
|
||||
value={initialForm}
|
||||
onChange={(e) => setInitialForm(e.value)}
|
||||
optionDisabled={(opt) => finalForm === opt.value}
|
||||
options={formOptions}
|
||||
optionLabel="label"
|
||||
optionValue="value"
|
||||
placeholder={__('Scegli il form', 'gepafin')} />
|
||||
</div>
|
||||
|
||||
<div className="appForm__field">
|
||||
<label htmlFor="finalForm">{__('Scegli form finale', 'gepafin')}</label>
|
||||
<Dropdown
|
||||
id="finalForm"
|
||||
value={finalForm}
|
||||
onChange={(e) => setFinalForm(e.value)}
|
||||
optionDisabled={(opt) => initialForm === opt.value}
|
||||
options={formOptions}
|
||||
optionLabel="label"
|
||||
optionValue="value"
|
||||
placeholder={__('Scegli il form', 'gepafin')} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<FlowBuilder forms={forms} initialForm={initialForm} finalForm={finalForm} updateFn={updateEdges}/>
|
||||
</div>
|
||||
|
||||
<div className="appPage__spacer"></div>
|
||||
|
||||
<div className="appPageSection">
|
||||
<div className="appPageSection__actions">
|
||||
<Button
|
||||
onClick={goBack}
|
||||
outlined
|
||||
label={__('Indietro', 'gepafin')} icon="pi pi-arrow-left" iconPos="left"/>
|
||||
<Button
|
||||
onClick={doSave}
|
||||
label={__('Salva', 'gepafin')} icon="pi pi-save" iconPos="right"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default BandoFlowEdit;
|
||||
@@ -35,7 +35,7 @@ const BandoFormsEdit = () => {
|
||||
navigate(`/bandi/${bandoId}/forms`);
|
||||
}
|
||||
|
||||
const doSave = () => {
|
||||
const doSave = (shouldRedirect = false) => {
|
||||
const content = storeGet.main.formElements();
|
||||
const bandoId = getBandoId();
|
||||
const parsedFormId = parseInt(formId)
|
||||
@@ -47,21 +47,25 @@ const BandoFormsEdit = () => {
|
||||
|
||||
storeSet.main.setAsyncRequest();
|
||||
if (bandoFormId === 0) {
|
||||
FormsService.createFormForCall(bandoId, formData, formCreateCallback, errFormCreateCallback);
|
||||
FormsService.createFormForCall(bandoId, formData, (data) => formCreateCallback(data, shouldRedirect), errFormCreateCallback);
|
||||
} else {
|
||||
FormsService.updateForm(bandoFormId, formData, formCreateCallback, errFormCreateCallback);
|
||||
FormsService.updateForm(bandoFormId, formData, (data) => formCreateCallback(data, shouldRedirect), errFormCreateCallback);
|
||||
}
|
||||
}
|
||||
|
||||
const formCreateCallback = (data) => {
|
||||
const formCreateCallback = (data, shouldRedirect) => {
|
||||
if (data.status === 'SUCCESS') {
|
||||
const parsed = parseInt(id)
|
||||
const bandoId = !isNaN(parsed) ? parsed : 0;
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
const bandoId = getBandoId();
|
||||
|
||||
if (shouldRedirect) {
|
||||
navigate(`/bandi/${bandoId}/forms/${data.data.id}/preview`);
|
||||
return;
|
||||
}
|
||||
if (data.data.id) {
|
||||
navigate(`/bandi/${bandoId}/forms/${data.data.id}`);
|
||||
}
|
||||
}
|
||||
storeSet.main.unsetAsyncRequest();
|
||||
}
|
||||
|
||||
const errFormCreateCallback = (data) => {
|
||||
@@ -70,8 +74,7 @@ const BandoFormsEdit = () => {
|
||||
}
|
||||
|
||||
const openPreview = () => {
|
||||
const bandoId = getBandoId();
|
||||
navigate(`/bandi/${bandoId}/forms/${formId}/preview`);
|
||||
doSave(true);
|
||||
}
|
||||
|
||||
const confirmDelete = (event) => {
|
||||
|
||||
@@ -13,6 +13,7 @@ import BandoView from './pages/BandoView';
|
||||
import BandoFormsEdit from './pages/BandoFormsEdit';
|
||||
import BandoForms from './pages/BandoForms';
|
||||
import BandoFormsPreview from './pages/BandoFormsPreview';
|
||||
import BandoFlowEdit from './pages/BandoFlowEdit';
|
||||
|
||||
const routes = ({ role }) => {
|
||||
return (
|
||||
@@ -43,6 +44,9 @@ const routes = ({ role }) => {
|
||||
<Route path="/bandi/:id/forms/:formId/preview" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <BandoFormsPreview/> : null}
|
||||
</DefaultLayout>}/>
|
||||
<Route path="/bandi/:id/flow" element={<DefaultLayout>
|
||||
{'ROLE_SUPER_ADMIN' === role ? <BandoFlowEdit/> : null}
|
||||
</DefaultLayout>}/>
|
||||
</Route>
|
||||
<Route exact path="/login" element={<Login/>}/>
|
||||
{/*<Route exact path="/forgot-password" element={<ForgotPassword/>}/>*/}
|
||||
|
||||
Reference in New Issue
Block a user