- added spreadsheet form element;
This commit is contained in:
@@ -176,6 +176,19 @@
|
|||||||
width: 40rem;
|
width: 40rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.formBuilder__elementSettings--wide {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Univer renders context menus / popups with position:fixed and z-index:1070,
|
||||||
|
// but PrimeReact Sidebar (modal type) sits at z-index ~1100, hiding them.
|
||||||
|
// Raise all Univer popup/floating layers above the sidebar.
|
||||||
|
.univer-popup,
|
||||||
|
.univer-z-\[1020\],
|
||||||
|
.univer-z-\[1080\] {
|
||||||
|
z-index: 9999 !important;
|
||||||
|
}
|
||||||
|
|
||||||
.formElementSettings {
|
.formElementSettings {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
84
src/components/FormField/components/Spreadsheet/index.js
Normal file
84
src/components/FormField/components/Spreadsheet/index.js
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import React, { useEffect, useRef } from 'react';
|
||||||
|
import { createUniver, LocaleType, mergeLocales } from '@univerjs/presets';
|
||||||
|
import { UniverSheetsCorePreset } from '@univerjs/preset-sheets-core';
|
||||||
|
import UniverPresetSheetsCoreEnUS from '@univerjs/preset-sheets-core/locales/en-US';
|
||||||
|
import '@univerjs/preset-sheets-core/lib/index.css';
|
||||||
|
|
||||||
|
const parseWorkbook = (val) => {
|
||||||
|
if (!val) return null;
|
||||||
|
if (typeof val === 'object' && val.sheets) return val;
|
||||||
|
if (typeof val === 'string') {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(val);
|
||||||
|
return parsed && parsed.sheets ? parsed : null;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Spreadsheet = ({ fieldName, defaultValue, setDataFn, template }) => {
|
||||||
|
const containerRef = useRef(null);
|
||||||
|
const univerRef = useRef(null);
|
||||||
|
const univerAPIRef = useRef(null);
|
||||||
|
const saveTimerRef = useRef(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!containerRef.current) return;
|
||||||
|
|
||||||
|
const { univer, univerAPI } = createUniver({
|
||||||
|
locale: LocaleType.EN_US,
|
||||||
|
locales: {
|
||||||
|
[LocaleType.EN_US]: mergeLocales(UniverPresetSheetsCoreEnUS),
|
||||||
|
},
|
||||||
|
presets: [
|
||||||
|
UniverSheetsCorePreset({
|
||||||
|
container: containerRef.current,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
univerRef.current = univer;
|
||||||
|
univerAPIRef.current = univerAPI;
|
||||||
|
|
||||||
|
const initialData = parseWorkbook(defaultValue) || parseWorkbook(template) || { name: 'Sheet' };
|
||||||
|
univerAPI.createWorkbook(initialData);
|
||||||
|
|
||||||
|
univerAPI.addEvent(univerAPI.Event.BeforeCommandExecute, () => {
|
||||||
|
clearTimeout(saveTimerRef.current);
|
||||||
|
saveTimerRef.current = setTimeout(() => {
|
||||||
|
const wb = univerAPIRef.current?.getActiveWorkbook();
|
||||||
|
if (wb) {
|
||||||
|
setDataFn(fieldName, wb.save());
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearTimeout(saveTimerRef.current);
|
||||||
|
if (univerRef.current) {
|
||||||
|
univerRef.current.dispose();
|
||||||
|
univerRef.current = null;
|
||||||
|
univerAPIRef.current = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const el = containerRef.current;
|
||||||
|
if (!el) return;
|
||||||
|
const handler = (e) => { e.stopPropagation(); e.preventDefault(); };
|
||||||
|
el.addEventListener('wheel', handler, { passive: false });
|
||||||
|
return () => el.removeEventListener('wheel', handler);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={containerRef}
|
||||||
|
style={{ width: '100%', height: '500px' }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Spreadsheet;
|
||||||
@@ -19,6 +19,7 @@ import Table from './components/Table';
|
|||||||
import PasswordField from './components/PasswordField';
|
import PasswordField from './components/PasswordField';
|
||||||
import CriteriaTable from './components/CriteriaTable';
|
import CriteriaTable from './components/CriteriaTable';
|
||||||
import FileSelect from './components/FileSelect';
|
import FileSelect from './components/FileSelect';
|
||||||
|
import Spreadsheet from './components/Spreadsheet';
|
||||||
|
|
||||||
const FormField = (props) => {
|
const FormField = (props) => {
|
||||||
const fields = {
|
const fields = {
|
||||||
@@ -38,6 +39,7 @@ const FormField = (props) => {
|
|||||||
criteria_table: CriteriaTable,
|
criteria_table: CriteriaTable,
|
||||||
password: PasswordField,
|
password: PasswordField,
|
||||||
fileselect: FileSelect,
|
fileselect: FileSelect,
|
||||||
|
spreadsheet: Spreadsheet,
|
||||||
}
|
}
|
||||||
const Comp = !isNil(fields[props.type]) ? fields[props.type] : null;
|
const Comp = !isNil(fields[props.type]) ? fields[props.type] : null;
|
||||||
|
|
||||||
|
|||||||
@@ -730,6 +730,7 @@ const BandoApplication = () => {
|
|||||||
if (!tableColumns) {
|
if (!tableColumns) {
|
||||||
tableColumns = head(o.settings.filter(o => o.name === 'criteria_table_columns'));
|
tableColumns = head(o.settings.filter(o => o.name === 'criteria_table_columns'));
|
||||||
}
|
}
|
||||||
|
const template = head(o.settings.filter(s => s.name === 'template'));
|
||||||
const step = head(o.settings.filter(o => o.name === 'step'));
|
const step = head(o.settings.filter(o => o.name === 'step'));
|
||||||
const mime = head(o.settings.filter(o => o.name === 'mime'));
|
const mime = head(o.settings.filter(o => o.name === 'mime'));
|
||||||
const documentCategories = head(o.settings.filter(o => o.name === 'documentCategories'));
|
const documentCategories = head(o.settings.filter(o => o.name === 'documentCategories'));
|
||||||
@@ -794,6 +795,7 @@ const BandoApplication = () => {
|
|||||||
sourceId={getApplicationId()}
|
sourceId={getApplicationId()}
|
||||||
useGrouping={false}
|
useGrouping={false}
|
||||||
tableColumns={tableColumns ? tableColumns.value : {}}
|
tableColumns={tableColumns ? tableColumns.value : {}}
|
||||||
|
template={template ? template.value : null}
|
||||||
/>
|
/>
|
||||||
})
|
})
|
||||||
: null}
|
: null}
|
||||||
|
|||||||
@@ -378,6 +378,7 @@ const BandoApplicationPreview = () => {
|
|||||||
if (!tableColumns) {
|
if (!tableColumns) {
|
||||||
tableColumns = head(o.settings.filter(o => o.name === 'criteria_table_columns'));
|
tableColumns = head(o.settings.filter(o => o.name === 'criteria_table_columns'));
|
||||||
}
|
}
|
||||||
|
const template = head(o.settings.filter(s => s.name === 'template'));
|
||||||
const step = head(o.settings.filter(o => o.name === 'step'));
|
const step = head(o.settings.filter(o => o.name === 'step'));
|
||||||
const mime = head(o.settings.filter(o => o.name === 'mime'));
|
const mime = head(o.settings.filter(o => o.name === 'mime'));
|
||||||
const formula = head(o.settings.filter(o => o.name === 'formula'));
|
const formula = head(o.settings.filter(o => o.name === 'formula'));
|
||||||
@@ -435,6 +436,7 @@ const BandoApplicationPreview = () => {
|
|||||||
sourceId={getApplicationId()}
|
sourceId={getApplicationId()}
|
||||||
useGrouping={false}
|
useGrouping={false}
|
||||||
tableColumns={tableColumns ? tableColumns.value : {}}
|
tableColumns={tableColumns ? tableColumns.value : {}}
|
||||||
|
template={template ? template.value : null}
|
||||||
/>
|
/>
|
||||||
})}
|
})}
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,29 @@ const BandoEditFormStep3 = forwardRef(function () {
|
|||||||
storeSet('unsetAsyncRequest');
|
storeSet('unsetAsyncRequest');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getFormsCallback = (resp) => {
|
||||||
|
if (resp.status === 'SUCCESS') {
|
||||||
|
const EXCLUDED_TYPES = new Set(['fileupload', 'fileselect', 'table', 'criteria_table', 'spreadsheet']);
|
||||||
|
const raw = (resp.data ?? []).flatMap(form =>
|
||||||
|
(form.content ?? [])
|
||||||
|
.filter(f => !EXCLUDED_TYPES.has(f.name))
|
||||||
|
.map(f => ({
|
||||||
|
id: f.id,
|
||||||
|
label: f.label,
|
||||||
|
placeholder: f.settings?.find(s => s.name === 'placeholder')?.value ?? ''
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
const byLabel = new Map();
|
||||||
|
raw.forEach(f => {
|
||||||
|
if (!byLabel.has(f.label)) byLabel.set(f.label, { label: f.label, ids: [], placeholder: f.placeholder });
|
||||||
|
byLabel.get(f.label).ids.push(f.id);
|
||||||
|
});
|
||||||
|
storeSet('callFormFields', Array.from(byLabel.values()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const errGetFormsCallback = () => {}
|
||||||
|
|
||||||
const getFormCallback = (resp) => {
|
const getFormCallback = (resp) => {
|
||||||
if (resp.status === 'SUCCESS') {
|
if (resp.status === 'SUCCESS') {
|
||||||
storeSet('formId', resp.data.id);
|
storeSet('formId', resp.data.id);
|
||||||
@@ -117,12 +140,14 @@ const BandoEditFormStep3 = forwardRef(function () {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
storeSet('setAsyncRequest');
|
storeSet('setAsyncRequest');
|
||||||
FormsService.getElementItems(getElementItemsCallback, errGetElementItemsCallbacks);
|
FormsService.getElementItems(getElementItemsCallback, errGetElementItemsCallbacks);
|
||||||
|
FormsService.getFormsForCall(id, getFormsCallback, errGetFormsCallback);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
storeSet('formId', 0);
|
storeSet('formId', 0);
|
||||||
storeSet('formElements', []);
|
storeSet('formElements', []);
|
||||||
storeSet('activeElement', '');
|
storeSet('activeElement', '');
|
||||||
storeSet('selectedElement', '');
|
storeSet('selectedElement', '');
|
||||||
|
storeSet('callFormFields', []);
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ import BandoEditFormStep2 from './components/BandoEditFormStep2';
|
|||||||
import { Messages } from 'primereact/messages';
|
import { Messages } from 'primereact/messages';
|
||||||
import BlockingOverlay from '../../components/BlockingOverlay';
|
import BlockingOverlay from '../../components/BlockingOverlay';
|
||||||
import { Toast } from 'primereact/toast';
|
import { Toast } from 'primereact/toast';
|
||||||
import BandoEditFormStep3Excel from './components/BandoEditFormStep3Excel';
|
|
||||||
import { ConfirmPopup, confirmPopup } from 'primereact/confirmpopup';
|
import { ConfirmPopup, confirmPopup } from 'primereact/confirmpopup';
|
||||||
|
import BandoEditFormStep3 from './components/BandoEditFormStep3';
|
||||||
|
|
||||||
const BandoEdit = () => {
|
const BandoEdit = () => {
|
||||||
const isAsyncRequest = useStoreValue('isAsyncRequest');
|
const isAsyncRequest = useStoreValue('isAsyncRequest');
|
||||||
@@ -375,11 +375,8 @@ const BandoEdit = () => {
|
|||||||
? <BandoEditFormStep2 initialData={data} setInitialData={setData} ref={formRef}
|
? <BandoEditFormStep2 initialData={data} setInitialData={setData} ref={formRef}
|
||||||
status={data.status}/>
|
status={data.status}/>
|
||||||
: null}
|
: null}
|
||||||
{/*{activeStep === 2 && data.evaluationVersion === 'V2'
|
|
||||||
? <BandoEditFormStep3/>
|
|
||||||
: null}*/}
|
|
||||||
{activeStep === 2 && data.evaluationVersion === 'V2'
|
{activeStep === 2 && data.evaluationVersion === 'V2'
|
||||||
? <BandoEditFormStep3Excel/>
|
? <BandoEditFormStep3/>
|
||||||
: null}
|
: null}
|
||||||
|
|
||||||
<div className="appPageSection">
|
<div className="appPageSection">
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { InputSwitch } from 'primereact/inputswitch';
|
|||||||
import ElementSettingChips from '../ElementSettingChips';
|
import ElementSettingChips from '../ElementSettingChips';
|
||||||
import ElementSettingCriteriaTableColumns from '../ElementSettingCriteriaTableColumns';
|
import ElementSettingCriteriaTableColumns from '../ElementSettingCriteriaTableColumns';
|
||||||
import ElementSettingTableColumnsForCsv from '../ElementSettingTableColumnsForCsv';
|
import ElementSettingTableColumnsForCsv from '../ElementSettingTableColumnsForCsv';
|
||||||
|
import ElementSettingSpreadsheet from '../ElementSettingSpreadsheet';
|
||||||
|
|
||||||
import { mimeTypes } from '../../../../../../configData';
|
import { mimeTypes } from '../../../../../../configData';
|
||||||
import ElementSettingReportHeader from '../ElementSettingReportHeader';
|
import ElementSettingReportHeader from '../ElementSettingReportHeader';
|
||||||
@@ -47,7 +48,8 @@ const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => {
|
|||||||
isChecklistItem: __('Fa parte di "checklist"?', 'gepafin'),
|
isChecklistItem: __('Fa parte di "checklist"?', 'gepafin'),
|
||||||
reportEnable: __('Aggiungere nel report CSV?', 'gepafin'),
|
reportEnable: __('Aggiungere nel report CSV?', 'gepafin'),
|
||||||
reportHeader: __('Nome della colonna nel CSV', 'gepafin'),
|
reportHeader: __('Nome della colonna nel CSV', 'gepafin'),
|
||||||
reportColumns: __('', 'gepafin')
|
reportColumns: __('', 'gepafin'),
|
||||||
|
template: __('Template foglio', 'gepafin')
|
||||||
}
|
}
|
||||||
|
|
||||||
const settingDescription = {
|
const settingDescription = {
|
||||||
@@ -156,6 +158,11 @@ const ElementSetting = ({ setting, changeFn, updateDataFn, bandoStatus }) => {
|
|||||||
name={setting.name}
|
name={setting.name}
|
||||||
bandoStatus={bandoStatus}
|
bandoStatus={bandoStatus}
|
||||||
setDataFn={updateDataFn}/>
|
setDataFn={updateDataFn}/>
|
||||||
|
} else if (setting.name === 'template') {
|
||||||
|
return <ElementSettingSpreadsheet
|
||||||
|
value={setting.value}
|
||||||
|
name={setting.name}
|
||||||
|
setDataFn={updateDataFn}/>;
|
||||||
} else if (setting.name === 'formula') {
|
} else if (setting.name === 'formula') {
|
||||||
const isInvalid = invalidFormula(setting.value);
|
const isInvalid = invalidFormula(setting.value);
|
||||||
return <>
|
return <>
|
||||||
|
|||||||
@@ -0,0 +1,215 @@
|
|||||||
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { isEmpty } from 'ramda';
|
||||||
|
import { createUniver, LocaleType, mergeLocales } from '@univerjs/presets';
|
||||||
|
import { UniverSheetsCorePreset } from '@univerjs/preset-sheets-core';
|
||||||
|
import UniverPresetSheetsCoreEnUS from '@univerjs/preset-sheets-core/locales/en-US';
|
||||||
|
import '@univerjs/preset-sheets-core/lib/index.css';
|
||||||
|
|
||||||
|
// store
|
||||||
|
import { useStoreValue } from '../../../../../../store';
|
||||||
|
|
||||||
|
// tools
|
||||||
|
import { xlsxToWorkbookData } from '../../../../../BandoEdit/components/BandoEditFormStep3Excel/xlsxToWorkbookData';
|
||||||
|
|
||||||
|
const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => {
|
||||||
|
const callFormFields = useStoreValue('callFormFields');
|
||||||
|
const [tagTooltip, setTagTooltip] = useState(null);
|
||||||
|
const containerRef = useRef(null);
|
||||||
|
const univerRef = useRef(null);
|
||||||
|
const univerAPIRef = useRef(null);
|
||||||
|
const formFieldsRef = useRef([]);
|
||||||
|
const mousePos = useRef({ x: 0, y: 0 });
|
||||||
|
const fileInputRef = useRef(null);
|
||||||
|
|
||||||
|
const insertFieldTag = (ids, type, field) => {
|
||||||
|
const api = univerAPIRef.current;
|
||||||
|
if (!api) return;
|
||||||
|
const range = api.getActiveWorkbook()?.getActiveSheet()?.getActiveRange();
|
||||||
|
if (!range) return;
|
||||||
|
const displayValue = type === 'value' ? (field.placeholder || '') : field.label;
|
||||||
|
range.setValues([[{
|
||||||
|
v: displayValue,
|
||||||
|
f: `{{gepafin_field:${ids.join(',')}|${type}}}`
|
||||||
|
}]]);
|
||||||
|
range.setBackground('#dbeafe');
|
||||||
|
};
|
||||||
|
|
||||||
|
const initializeUniver = useCallback((workbookData) => {
|
||||||
|
if (univerRef.current) {
|
||||||
|
univerRef.current.dispose();
|
||||||
|
univerRef.current = null;
|
||||||
|
univerAPIRef.current = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!containerRef.current) return;
|
||||||
|
|
||||||
|
const { univer, univerAPI } = createUniver({
|
||||||
|
locale: LocaleType.EN_US,
|
||||||
|
locales: {
|
||||||
|
[LocaleType.EN_US]: mergeLocales(UniverPresetSheetsCoreEnUS),
|
||||||
|
},
|
||||||
|
presets: [
|
||||||
|
UniverSheetsCorePreset({
|
||||||
|
container: containerRef.current,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
univerAPI.createWorkbook(workbookData || { name: 'Sheet' });
|
||||||
|
univerRef.current = univer;
|
||||||
|
univerAPIRef.current = univerAPI;
|
||||||
|
|
||||||
|
// Disable adding new sheets
|
||||||
|
univerAPI.addEvent(univerAPI.Event.BeforeCommandExecute, (event) => {
|
||||||
|
if (event.id === 'sheet.command.insert-sheet') {
|
||||||
|
event.cancel = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Context menu: "Inserisci variabile GEPAFIN"
|
||||||
|
const fields = formFieldsRef.current;
|
||||||
|
if (fields.length > 0) {
|
||||||
|
const submenu = univerAPI.createSubmenu({
|
||||||
|
id: 'gepafin-insert-variable',
|
||||||
|
title: 'Inserisci variabile GEPAFIN',
|
||||||
|
});
|
||||||
|
|
||||||
|
fields.forEach((field, index) => {
|
||||||
|
if (index > 0) submenu.addSeparator();
|
||||||
|
|
||||||
|
const menuKey = field.ids[0];
|
||||||
|
const countLabel = field.ids.length > 1 ? ` [${field.ids.length}]` : '';
|
||||||
|
|
||||||
|
submenu.addSubmenu(univerAPI.createMenu({
|
||||||
|
id: `gepafin-field-${menuKey}-label`,
|
||||||
|
title: `${field.label}${countLabel} (etichetta)`,
|
||||||
|
action: () => insertFieldTag(field.ids, 'label', field),
|
||||||
|
}));
|
||||||
|
|
||||||
|
submenu.addSubmenu(univerAPI.createMenu({
|
||||||
|
id: `gepafin-field-${menuKey}-value`,
|
||||||
|
title: `${field.label}${countLabel} (valore)`,
|
||||||
|
action: () => insertFieldTag(field.ids, 'value', field),
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
submenu.appendTo(['contextMenu.mainArea', 'contextMenu.others']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tooltip on hover over tagged cells — read formula field to detect tag
|
||||||
|
univerAPI.addEvent(univerAPI.Event.CellHover, (params) => {
|
||||||
|
const { row, column, worksheet } = params;
|
||||||
|
const formula = worksheet?.getRange(row, column)?.getFormulas()?.[0]?.[0];
|
||||||
|
if (typeof formula === 'string' && formula.startsWith('{{gepafin_field:')) {
|
||||||
|
const match = formula.match(/\{\{gepafin_field:([^|]+)\|([^}]+)\}\}/);
|
||||||
|
if (match) {
|
||||||
|
const tagIds = match[1].split(',');
|
||||||
|
const field = formFieldsRef.current.find(f => f.ids.some(fid => tagIds.includes(fid)));
|
||||||
|
const countSuffix = tagIds.length > 1 ? ` — ${tagIds.length} moduli` : '';
|
||||||
|
setTagTooltip({ label: `${field ? field.label : match[1]} (${match[2]})${countSuffix}` });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setTagTooltip(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, []); // refs are stable
|
||||||
|
|
||||||
|
// Keep formFieldsRef in sync with store value
|
||||||
|
useEffect(() => {
|
||||||
|
formFieldsRef.current = callFormFields;
|
||||||
|
}, [callFormFields]);
|
||||||
|
|
||||||
|
// Initialize Univer on mount
|
||||||
|
useEffect(() => {
|
||||||
|
const workbook = value && !isEmpty(value) && value.sheets ? value : null;
|
||||||
|
initializeUniver(workbook);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (univerRef.current) {
|
||||||
|
univerRef.current.dispose();
|
||||||
|
univerRef.current = null;
|
||||||
|
univerAPIRef.current = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, []); // run once on mount
|
||||||
|
|
||||||
|
// Prevent page scroll while hovering over the spreadsheet
|
||||||
|
useEffect(() => {
|
||||||
|
const el = containerRef.current;
|
||||||
|
if (!el) return;
|
||||||
|
const handler = (e) => { e.stopPropagation(); e.preventDefault(); };
|
||||||
|
el.addEventListener('wheel', handler, { passive: false });
|
||||||
|
return () => el.removeEventListener('wheel', handler);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleImport = (e) => {
|
||||||
|
const file = e.target.files?.[0];
|
||||||
|
if (!file) return;
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = (ev) => {
|
||||||
|
const data = xlsxToWorkbookData(ev.target.result);
|
||||||
|
initializeUniver(data);
|
||||||
|
};
|
||||||
|
reader.readAsArrayBuffer(file);
|
||||||
|
e.target.value = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSave = () => {
|
||||||
|
const workbookData = univerAPIRef.current?.getActiveWorkbook()?.save() ?? {};
|
||||||
|
setDataFn(name, workbookData);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ width: '100%' }}>
|
||||||
|
<div style={{ marginBottom: '8px', display: 'flex', gap: '8px', justifyContent: 'flex-end' }}>
|
||||||
|
<input
|
||||||
|
ref={fileInputRef}
|
||||||
|
type="file"
|
||||||
|
accept=".xlsx,.xls,.csv,.ods"
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
onChange={handleImport}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="p-button p-button-outlined p-button-sm"
|
||||||
|
onClick={() => fileInputRef.current?.click()}
|
||||||
|
>
|
||||||
|
{__('Importa foglio', 'gepafin')}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="p-button p-button-sm"
|
||||||
|
onClick={handleSave}
|
||||||
|
>
|
||||||
|
{__('Salva template', 'gepafin')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
ref={containerRef}
|
||||||
|
style={{ width: '100%', height: '500px' }}
|
||||||
|
onMouseMove={(e) => { mousePos.current = { x: e.clientX, y: e.clientY }; }}
|
||||||
|
onMouseLeave={() => setTagTooltip(null)}
|
||||||
|
/>
|
||||||
|
{tagTooltip && (
|
||||||
|
<div style={{
|
||||||
|
position: 'fixed',
|
||||||
|
top: mousePos.current.y - 36,
|
||||||
|
left: mousePos.current.x + 12,
|
||||||
|
background: '#1e293b',
|
||||||
|
color: '#fff',
|
||||||
|
padding: '4px 8px',
|
||||||
|
borderRadius: '4px',
|
||||||
|
fontSize: '12px',
|
||||||
|
pointerEvents: 'none',
|
||||||
|
zIndex: 9999,
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
}}>
|
||||||
|
{tagTooltip.label}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ElementSettingSpreadsheet;
|
||||||
@@ -18,6 +18,7 @@ const FormBuilder = ({ callStatus, context }) => {
|
|||||||
const elementItems = useStoreValue('elementItems');
|
const elementItems = useStoreValue('elementItems');
|
||||||
const activeElement = useStoreValue('activeElement');
|
const activeElement = useStoreValue('activeElement');
|
||||||
const isAsyncRequest = useStoreValue('isAsyncRequest');
|
const isAsyncRequest = useStoreValue('isAsyncRequest');
|
||||||
|
const isSpreadsheetActive = elements.find(el => el.id === activeElement)?.name === 'spreadsheet';
|
||||||
|
|
||||||
const renderField = useCallback((field, index) => {
|
const renderField = useCallback((field, index) => {
|
||||||
return (
|
return (
|
||||||
@@ -56,7 +57,7 @@ const FormBuilder = ({ callStatus, context }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Sidebar visible={!isEmpty(activeElement)} onHide={closeSettings} dismissable={false} className="formBuilder__elementSettings">
|
<Sidebar visible={!isEmpty(activeElement)} onHide={closeSettings} dismissable={false} className={`formBuilder__elementSettings${isSpreadsheetActive ? ' formBuilder__elementSettings--wide' : ''}`}>
|
||||||
<h2>{__('Impostazioni del campo modulo', 'gepafin')}</h2>
|
<h2>{__('Impostazioni del campo modulo', 'gepafin')}</h2>
|
||||||
{!isEmpty(activeElement)
|
{!isEmpty(activeElement)
|
||||||
? <BuilderElementSettings closeSettingsFn={closeSettings} callStatus={callStatus} context={context}/>
|
? <BuilderElementSettings closeSettingsFn={closeSettings} callStatus={callStatus} context={context}/>
|
||||||
|
|||||||
@@ -1586,6 +1586,7 @@ const DomandaEditInstructorManager = () => {
|
|||||||
if (!tableColumns) {
|
if (!tableColumns) {
|
||||||
tableColumns = head(o.settings.filter(o => o.name === 'criteria_table_columns'));
|
tableColumns = head(o.settings.filter(o => o.name === 'criteria_table_columns'));
|
||||||
}
|
}
|
||||||
|
const template = head(o.settings.filter(s => s.name === 'template'));
|
||||||
const step = head(o.settings.filter(o => o.name === 'step'));
|
const step = head(o.settings.filter(o => o.name === 'step'));
|
||||||
const mime = head(o.settings.filter(o => o.name === 'mime'));
|
const mime = head(o.settings.filter(o => o.name === 'mime'));
|
||||||
const formula = head(o.settings.filter(o => o.name === 'formula'));
|
const formula = head(o.settings.filter(o => o.name === 'formula'));
|
||||||
@@ -1645,6 +1646,7 @@ const DomandaEditInstructorManager = () => {
|
|||||||
sourceId={id}
|
sourceId={id}
|
||||||
useGrouping={false}
|
useGrouping={false}
|
||||||
tableColumns={tableColumns ? tableColumns.value : {}}
|
tableColumns={tableColumns ? tableColumns.value : {}}
|
||||||
|
template={template ? template.value : null}
|
||||||
/>
|
/>
|
||||||
})}
|
})}
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -822,7 +822,7 @@ const DomandaEditPreInstructor = () => {
|
|||||||
storeSet('unsetAsyncRequest');
|
storeSet('unsetAsyncRequest');
|
||||||
}
|
}
|
||||||
|
|
||||||
const doCreateAppointment = () => {
|
/*const doCreateAppointment = () => {
|
||||||
setAppointmentData({
|
setAppointmentData({
|
||||||
title: '',
|
title: '',
|
||||||
text: '',
|
text: '',
|
||||||
@@ -830,7 +830,7 @@ const DomandaEditPreInstructor = () => {
|
|||||||
amount: 0
|
amount: 0
|
||||||
});
|
});
|
||||||
setIsVisibleAppointmentDialog(true);
|
setIsVisibleAppointmentDialog(true);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
const setAppointmentFieldValue = (name, value) => {
|
const setAppointmentFieldValue = (name, value) => {
|
||||||
const newData = wrap(appointmentData).set(name, value).value();
|
const newData = wrap(appointmentData).set(name, value).value();
|
||||||
@@ -1493,6 +1493,7 @@ const DomandaEditPreInstructor = () => {
|
|||||||
if (!tableColumns) {
|
if (!tableColumns) {
|
||||||
tableColumns = head(o.settings.filter(o => o.name === 'criteria_table_columns'));
|
tableColumns = head(o.settings.filter(o => o.name === 'criteria_table_columns'));
|
||||||
}
|
}
|
||||||
|
const template = head(o.settings.filter(s => s.name === 'template'));
|
||||||
const step = head(o.settings.filter(o => o.name === 'step'));
|
const step = head(o.settings.filter(o => o.name === 'step'));
|
||||||
const mime = head(o.settings.filter(o => o.name === 'mime'));
|
const mime = head(o.settings.filter(o => o.name === 'mime'));
|
||||||
const formula = head(o.settings.filter(o => o.name === 'formula'));
|
const formula = head(o.settings.filter(o => o.name === 'formula'));
|
||||||
@@ -1552,6 +1553,7 @@ const DomandaEditPreInstructor = () => {
|
|||||||
sourceId={id}
|
sourceId={id}
|
||||||
useGrouping={false}
|
useGrouping={false}
|
||||||
tableColumns={tableColumns ? tableColumns.value : {}}
|
tableColumns={tableColumns ? tableColumns.value : {}}
|
||||||
|
template={template ? template.value : null}
|
||||||
/>
|
/>
|
||||||
})}
|
})}
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ const LoginConfidi = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isEmpty(token)) {
|
if (!isEmpty(token) && !AuthenticationService.isExpired()) {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
window.location.replace('/')
|
window.location.replace('/')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { storeGet, storeSet } from '../store';
|
import { storeGet } from '../store';
|
||||||
import logMsgWithSentry from '../helpers/logMsgWithSentry';
|
import logMsgWithSentry from '../helpers/logMsgWithSentry';
|
||||||
import { isEmpty } from 'ramda';
|
import { isEmpty } from 'ramda';
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const initialStore = {
|
|||||||
formLabel: '',
|
formLabel: '',
|
||||||
formElements: [],
|
formElements: [],
|
||||||
elementItems: [],
|
elementItems: [],
|
||||||
|
callFormFields: [],
|
||||||
activeElement: '',
|
activeElement: '',
|
||||||
selectedElement: '',
|
selectedElement: '',
|
||||||
draggingElementId: 0,
|
draggingElementId: 0,
|
||||||
|
|||||||
@@ -675,5 +675,23 @@ export const elementItems = [
|
|||||||
validators: {
|
validators: {
|
||||||
isRequired: false
|
isRequired: false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 24,
|
||||||
|
sortOrder: 24,
|
||||||
|
name: 'spreadsheet',
|
||||||
|
label: 'Foglio di Calcolo',
|
||||||
|
description: 'Modello di foglio di calcolo con variabili dinamiche',
|
||||||
|
settings: [
|
||||||
|
{
|
||||||
|
name: "label",
|
||||||
|
value: "Foglio di Calcolo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "template",
|
||||||
|
value: {}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
validators: {}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user