dmencu 2.2.16 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/client/client.d.ts +4 -1
- package/dist/client/client/client.js +165 -271
- package/dist/client/unlogged/abrir-formulario.d.ts +1 -8
- package/dist/client/unlogged/abrir-formulario.js +7 -48
- package/dist/client/unlogged/bypass-formulario.d.ts +2 -2
- package/dist/client/unlogged/bypass-formulario.js +26 -14
- package/dist/client/unlogged/redux-formulario.d.ts +141 -92
- package/dist/client/unlogged/redux-formulario.js +36 -85
- package/dist/client/unlogged/render-config.d.ts +52 -0
- package/dist/client/unlogged/render-config.js +161 -0
- package/dist/client/unlogged/render-formulario.d.ts +139 -0
- package/dist/client/unlogged/render-formulario.js +2045 -0
- package/dist/client/unlogged/render-formulario.tsx +610 -234
- package/dist/client/unlogged/render-general.d.ts +147 -0
- package/dist/client/unlogged/render-general.js +254 -0
- package/dist/client/unlogged/render-general.tsx +9 -3
- package/dist/client/unlogged/render-init.d.ts +17 -0
- package/dist/client/unlogged/render-init.js +127 -0
- package/dist/client/unlogged/tipos.d.ts +6 -4
- package/dist/client/unlogged/tipos.js +1 -1
- package/dist/server/server/app-dmencu.d.ts +8 -2
- package/dist/server/server/app-dmencu.js +20 -9
- package/dist/server/server/procedures-dmencu.d.ts +1 -1
- package/dist/server/server/procedures-dmencu.js +24 -21
- package/dist/server/server/table-sincronizaciones.js +3 -2
- package/dist/server/unlogged/tipos.d.ts +6 -4
- package/dist/server/unlogged/tipos.js +1 -1
- package/dist/unlogged/unlogged/abrir-formulario.d.ts +1 -8
- package/dist/unlogged/unlogged/abrir-formulario.js +7 -48
- package/dist/unlogged/unlogged/bypass-formulario.d.ts +2 -2
- package/dist/unlogged/unlogged/bypass-formulario.js +26 -14
- package/dist/unlogged/unlogged/redux-formulario.d.ts +141 -92
- package/dist/unlogged/unlogged/redux-formulario.js +36 -85
- package/dist/unlogged/unlogged/render-config.d.ts +52 -0
- package/dist/unlogged/unlogged/render-config.js +161 -0
- package/dist/unlogged/unlogged/render-formulario.d.ts +57 -10
- package/dist/unlogged/unlogged/render-formulario.js +365 -171
- package/dist/unlogged/unlogged/render-formulario.tsx +610 -234
- package/dist/unlogged/unlogged/render-general.d.ts +10 -0
- package/dist/unlogged/unlogged/render-general.js +8 -4
- package/dist/unlogged/unlogged/render-general.tsx +9 -3
- package/dist/unlogged/unlogged/render-init.d.ts +17 -0
- package/dist/unlogged/unlogged/render-init.js +127 -0
- package/dist/unlogged/unlogged/tipos.d.ts +6 -4
- package/dist/unlogged/unlogged/tipos.js +1 -1
- package/dist/unlogged/unlogged/unlogged.js +234 -50
- package/package.json +1 -1
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
scrollToTop,
|
|
8
8
|
materialIoIconsSvgPath,
|
|
9
9
|
useOnlineStatus,
|
|
10
|
-
RenderizadorJSON
|
|
10
|
+
RenderizadorJSON,
|
|
11
11
|
} from "./render-general";
|
|
12
12
|
import {
|
|
13
13
|
Bloque, BotonFormulario,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
Texto, Estructura, InformacionHdr, ConfiguracionSorteoFormulario, ResumenEstado, IdOperativo, IdEnc, Libre,
|
|
25
25
|
iterator, empty, ConfiguracionHabilitarBotonFormulario,
|
|
26
26
|
PMatriz,
|
|
27
|
-
ModoDM
|
|
27
|
+
ModoDM,
|
|
28
28
|
} from "./tipos";
|
|
29
29
|
import {
|
|
30
30
|
accion_abrir_formulario,
|
|
@@ -34,16 +34,18 @@ import {
|
|
|
34
34
|
calcularPermiteBorrarBF,
|
|
35
35
|
calcularResumenVivienda,
|
|
36
36
|
crearEncuesta,
|
|
37
|
+
hayDatosByPassAlmacenados,
|
|
37
38
|
getDatosByPass,
|
|
38
39
|
getFormulariosForValuePkRaiz,
|
|
39
40
|
getMainFormForVivienda,
|
|
40
41
|
intentarBackup,
|
|
41
42
|
respuestasForPk,
|
|
42
|
-
setCalcularVariables
|
|
43
|
+
setCalcularVariables,
|
|
44
|
+
setDatosByPass,
|
|
45
|
+
setEstructura
|
|
43
46
|
} from "./bypass-formulario"
|
|
44
47
|
import {
|
|
45
|
-
|
|
46
|
-
gotoSincronizar,
|
|
48
|
+
crearStoreFormulario, dispatchers,
|
|
47
49
|
gotoConsistir,
|
|
48
50
|
} from "./redux-formulario";
|
|
49
51
|
import { useState, useEffect } from "react";
|
|
@@ -56,6 +58,9 @@ import {
|
|
|
56
58
|
AppBar, ButtonGroup, Checkbox,
|
|
57
59
|
Dialog, DialogActions, DialogContent, DialogContentText,
|
|
58
60
|
DialogTitle, Divider, Fab,
|
|
61
|
+
Icon,
|
|
62
|
+
ListItemIcon,
|
|
63
|
+
ListItemText,
|
|
59
64
|
Menu, MenuItem, Paper, Popover,
|
|
60
65
|
Table, TableBody, TableCell, TableHead, TableRow, Toolbar
|
|
61
66
|
} from "@mui/material";
|
|
@@ -74,11 +79,23 @@ import {
|
|
|
74
79
|
accion_id_pregunta,
|
|
75
80
|
accion_agregar_formulario,
|
|
76
81
|
NO_CAMBIAR__VERIFICAR_SI_ES_NECESARIO,
|
|
77
|
-
NO_CAMBIAR__SOLO_TRAER_STATUS
|
|
78
|
-
MODO_DM_LOCALSTORAGE_KEY
|
|
82
|
+
NO_CAMBIAR__SOLO_TRAER_STATUS
|
|
79
83
|
} from "./bypass-formulario"
|
|
80
84
|
|
|
81
85
|
import { html, HtmlTag } from "js-to-html";
|
|
86
|
+
import { FormRenderer, getFormRenderer, registrarCargarMotor } from "./render-config";
|
|
87
|
+
|
|
88
|
+
// Registra la implementación de cargarMotor al cargar el módulo.
|
|
89
|
+
// Esto evita la dependencia circular render-config ← bypass-formulario.
|
|
90
|
+
registrarCargarMotor(async function cargarEstructuraYDatosEnMemoria() {
|
|
91
|
+
var formRenderer = getFormRenderer();
|
|
92
|
+
const estructura = await formRenderer.leerEstructura();
|
|
93
|
+
const datos = await formRenderer.leerDatos();
|
|
94
|
+
if(estructura && datos){
|
|
95
|
+
setEstructura(estructura);
|
|
96
|
+
setDatosByPass(datos);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
82
99
|
|
|
83
100
|
const DELAY_SCROLL_3 = 50;
|
|
84
101
|
|
|
@@ -218,7 +235,8 @@ const TextField = (props: {
|
|
|
218
235
|
const Typography = ({ children, ...others }: {
|
|
219
236
|
children: any,
|
|
220
237
|
component?: string
|
|
221
|
-
variant?: 'h6'
|
|
238
|
+
variant?: 'body2'|'h5'|'h6'
|
|
239
|
+
color?: ColorValues
|
|
222
240
|
} & CommonAttributes) => React.createElement(others.variant || others.component || 'div', others, children);
|
|
223
241
|
|
|
224
242
|
function Grid(props: {
|
|
@@ -247,6 +265,42 @@ function Grid(props: {
|
|
|
247
265
|
>{children}</div>
|
|
248
266
|
}
|
|
249
267
|
|
|
268
|
+
interface FastSetupProps {
|
|
269
|
+
disabled?: boolean;
|
|
270
|
+
children: React.ReactNode;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export function FastSetup(props: FastSetupProps): JSX.Element {
|
|
274
|
+
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
|
275
|
+
const [open, setOpen] = React.useState(false);
|
|
276
|
+
|
|
277
|
+
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
|
278
|
+
setAnchorEl(event.currentTarget);
|
|
279
|
+
setOpen((prev) => !prev);
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
const handleClose = () => {
|
|
283
|
+
setOpen(false);
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
return (
|
|
287
|
+
<>
|
|
288
|
+
<Button onClick={handleClick} disabled={props.disabled}>
|
|
289
|
+
<ICON.Settings />
|
|
290
|
+
</Button>
|
|
291
|
+
|
|
292
|
+
<Menu
|
|
293
|
+
open={open}
|
|
294
|
+
anchorEl={anchorEl}
|
|
295
|
+
onClose={handleClose}
|
|
296
|
+
onClick={handleClose}
|
|
297
|
+
>
|
|
298
|
+
{props.children}
|
|
299
|
+
</Menu>
|
|
300
|
+
</>
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
|
|
250
304
|
var p12 = 'p12' as IdVariable;
|
|
251
305
|
var sp2 = 'sp2' as IdVariable;
|
|
252
306
|
var sp3 = 'sp3' as IdVariable;
|
|
@@ -1558,8 +1612,7 @@ function useSelectorVivienda(forPk: ForPk) {
|
|
|
1558
1612
|
var estructura = getEstructura();
|
|
1559
1613
|
return {
|
|
1560
1614
|
formulario: estructura.formularios[forPk.formulario].casilleros,
|
|
1561
|
-
modoDespliegue:
|
|
1562
|
-
modo: state.modo,
|
|
1615
|
+
modoDespliegue: state.opciones.modoDespliegue,
|
|
1563
1616
|
opciones: state.opciones,
|
|
1564
1617
|
}
|
|
1565
1618
|
})
|
|
@@ -1690,44 +1743,6 @@ function MenuLetra(props: { tamannio: number, denominacion: string }) {
|
|
|
1690
1743
|
>letra {props.denominacion}</MenuItem>
|
|
1691
1744
|
}
|
|
1692
1745
|
|
|
1693
|
-
function FastSettup() {
|
|
1694
|
-
const [anchorEl, setAnchorEl] = React.useState(null);
|
|
1695
|
-
const [open, setOpen] = React.useState(false);
|
|
1696
|
-
const handleClick = (event: any) => {
|
|
1697
|
-
setAnchorEl(event.currentTarget);
|
|
1698
|
-
setOpen((prev) => !prev);
|
|
1699
|
-
};
|
|
1700
|
-
const dispatch = useDispatch();
|
|
1701
|
-
const cambiar = (modoDespliegue: ModoDespliegue) => {
|
|
1702
|
-
dispatch(dispatchers.MODO_DESPLIEGUE({ modoDespliegue }));
|
|
1703
|
-
setOpen(false)
|
|
1704
|
-
}
|
|
1705
|
-
const opciones = useSelector((state: CasoState) => state.opciones)
|
|
1706
|
-
return <>
|
|
1707
|
-
<Button onClick={handleClick}>
|
|
1708
|
-
<ICON.Settings />
|
|
1709
|
-
</Button>
|
|
1710
|
-
<Menu open={open} anchorEl={anchorEl} onClose={() => setOpen(false)}>
|
|
1711
|
-
<MenuItem onClick={() => cambiar("relevamiento")}>normal</MenuItem>
|
|
1712
|
-
<MenuItem onClick={() => cambiar("PDF")}>PDF para relevamiento</MenuItem>
|
|
1713
|
-
<MenuItem onClick={() => cambiar("metadatos")}>revisar metadatos</MenuItem>
|
|
1714
|
-
<Divider />
|
|
1715
|
-
<MenuLetra tamannio={12} denominacion="muy chica" />
|
|
1716
|
-
<MenuLetra tamannio={14} denominacion="chica" />
|
|
1717
|
-
<MenuLetra tamannio={16} denominacion="normal" />
|
|
1718
|
-
<MenuLetra tamannio={19} denominacion="grande" />
|
|
1719
|
-
<MenuLetra tamannio={22} denominacion="enorme" />
|
|
1720
|
-
<Divider />
|
|
1721
|
-
<MenuItem><label><Checkbox checked={opciones.conCampoOpciones} onChange={
|
|
1722
|
-
() => dispatch(dispatchers.SET_OPCION({ opcion: 'conCampoOpciones', valor: !opciones.conCampoOpciones }))
|
|
1723
|
-
} inputProps={{ 'aria-label': 'primary checkbox' }} />campo opciones</label></MenuItem>
|
|
1724
|
-
<MenuItem><label><Checkbox checked={opciones.saltoAutomatico} onChange={
|
|
1725
|
-
() => dispatch(dispatchers.SET_OPCION({ opcion: 'saltoAutomatico', valor: !opciones.saltoAutomatico }))
|
|
1726
|
-
} inputProps={{ 'aria-label': 'primary checkbox' }} />salto automático</label></MenuItem>
|
|
1727
|
-
</Menu>
|
|
1728
|
-
</>;
|
|
1729
|
-
}
|
|
1730
|
-
|
|
1731
1746
|
function BarraDeNavegacion(props: { forPk: ForPk, soloLectura: boolean, modoDirecto: boolean }) {
|
|
1732
1747
|
const dispatch = useDispatch();
|
|
1733
1748
|
const forPk = props.forPk;
|
|
@@ -1749,7 +1764,7 @@ function BarraDeNavegacion(props: { forPk: ForPk, soloLectura: boolean, modoDire
|
|
|
1749
1764
|
}
|
|
1750
1765
|
var botonesFormulario = [];
|
|
1751
1766
|
if (!opciones.modoDirecto) {
|
|
1752
|
-
botonesFormulario.push({ que: 'hdr', abr: 'HdR', id: ID_BOTON_VOLVER_HDR, label: '
|
|
1767
|
+
botonesFormulario.push({ que: 'hdr', abr: 'HdR', id: ID_BOTON_VOLVER_HDR, label: 'Hoja de Ruta', retroceso: 0 })
|
|
1753
1768
|
}
|
|
1754
1769
|
opciones.pilaForPk.forEach((forPk, i) =>
|
|
1755
1770
|
botonesFormulario.push({ que: 'volver', abr: forPk.formulario.replace(/^F:/, ''), label: forPk.formulario, retroceso: opciones.pilaForPk.length - i })
|
|
@@ -1767,6 +1782,9 @@ function BarraDeNavegacion(props: { forPk: ForPk, soloLectura: boolean, modoDire
|
|
|
1767
1782
|
elemento.setAttribute('resumen-estado', calcularResumenVivienda(forPk, feedbackAll, r).resumenEstado);
|
|
1768
1783
|
}
|
|
1769
1784
|
})
|
|
1785
|
+
const cambiar = (modoDespliegue: ModoDespliegue) => {
|
|
1786
|
+
dispatch(dispatchers.MODO_DESPLIEGUE({ modoDespliegue }));
|
|
1787
|
+
}
|
|
1770
1788
|
return <>
|
|
1771
1789
|
<ButtonGroup key="formularios" className="barra-navegacion" solo-lectura={props.soloLectura ? 'si' : 'no'} >
|
|
1772
1790
|
{botonesFormulario.map((b, i) =>
|
|
@@ -1784,6 +1802,7 @@ function BarraDeNavegacion(props: { forPk: ForPk, soloLectura: boolean, modoDire
|
|
|
1784
1802
|
}}
|
|
1785
1803
|
>
|
|
1786
1804
|
<span className="abr">{b.abr}</span>
|
|
1805
|
+
{b.que == 'hdr' ? <ICON.Assignment /> : null}
|
|
1787
1806
|
<span className="label">{b.label}</span>
|
|
1788
1807
|
</Button>
|
|
1789
1808
|
)}
|
|
@@ -1861,7 +1880,24 @@ function BarraDeNavegacion(props: { forPk: ForPk, soloLectura: boolean, modoDire
|
|
|
1861
1880
|
<div key={k}><span>{k}</span><span>{v}</span></div>
|
|
1862
1881
|
).array()}
|
|
1863
1882
|
</Typography>
|
|
1864
|
-
<
|
|
1883
|
+
<FastSetup>
|
|
1884
|
+
<MenuItem onClick={() => cambiar("relevamiento")}>normal</MenuItem>
|
|
1885
|
+
<MenuItem onClick={() => cambiar("PDF")}>PDF para relevamiento</MenuItem>
|
|
1886
|
+
<MenuItem onClick={() => cambiar("metadatos")}>revisar metadatos</MenuItem>
|
|
1887
|
+
<Divider />
|
|
1888
|
+
<MenuLetra tamannio={12} denominacion="muy chica" />
|
|
1889
|
+
<MenuLetra tamannio={14} denominacion="chica" />
|
|
1890
|
+
<MenuLetra tamannio={16} denominacion="normal" />
|
|
1891
|
+
<MenuLetra tamannio={19} denominacion="grande" />
|
|
1892
|
+
<MenuLetra tamannio={22} denominacion="enorme" />
|
|
1893
|
+
<Divider />
|
|
1894
|
+
<MenuItem><label><Checkbox checked={opciones.conCampoOpciones} onChange={
|
|
1895
|
+
() => dispatch(dispatchers.SET_OPCION({ opcion: 'conCampoOpciones', valor: !opciones.conCampoOpciones }))
|
|
1896
|
+
} inputProps={{ 'aria-label': 'primary checkbox' }} />campo opciones</label></MenuItem>
|
|
1897
|
+
<MenuItem><label><Checkbox checked={opciones.saltoAutomatico} onChange={
|
|
1898
|
+
() => dispatch(dispatchers.SET_OPCION({ opcion: 'saltoAutomatico', valor: !opciones.saltoAutomatico }))
|
|
1899
|
+
} inputProps={{ 'aria-label': 'primary checkbox' }} />salto automático</label></MenuItem>
|
|
1900
|
+
</FastSetup>
|
|
1865
1901
|
</>
|
|
1866
1902
|
}
|
|
1867
1903
|
|
|
@@ -1888,7 +1924,7 @@ function BotonVolverEnDiv({ id }: { id: string }) {
|
|
|
1888
1924
|
|
|
1889
1925
|
function FormularioDespliegue(props: { forPk: ForPk }) {
|
|
1890
1926
|
var forPk = props.forPk;
|
|
1891
|
-
var { formulario, modoDespliegue,
|
|
1927
|
+
var { formulario, modoDespliegue, opciones }
|
|
1892
1928
|
= useSelectorVivienda(props.forPk);
|
|
1893
1929
|
var soloLectura = getDatosByPass().soloLectura;
|
|
1894
1930
|
const dispatch = useDispatch();
|
|
@@ -1948,28 +1984,20 @@ function FormularioDespliegue(props: { forPk: ForPk }) {
|
|
|
1948
1984
|
})
|
|
1949
1985
|
// @ts-expect-error especial hay que leerlo en el parser de casilleros si esto termina quedando así
|
|
1950
1986
|
var pantallaCompleta = formulario.especial?.pantallaCompleta;
|
|
1951
|
-
const modoDM: ModoDM =
|
|
1987
|
+
const modoDM: ModoDM = getFormRenderer().getModoDM();
|
|
1952
1988
|
return (
|
|
1953
1989
|
<>
|
|
1954
|
-
<
|
|
1955
|
-
|
|
1990
|
+
<AppBarPrincipal
|
|
1991
|
+
modoDM={modoDM}
|
|
1992
|
+
soloLectura={soloLectura}
|
|
1993
|
+
barraNavFormulario={
|
|
1956
1994
|
<BarraDeNavegacion forPk={forPk} soloLectura={soloLectura || false} modoDirecto={opciones.modoDirecto} />
|
|
1957
|
-
|
|
1958
|
-
|
|
1995
|
+
}
|
|
1996
|
+
>
|
|
1959
1997
|
<div id="mini-console"></div>
|
|
1960
|
-
</
|
|
1998
|
+
</AppBarPrincipal>
|
|
1961
1999
|
<main>
|
|
1962
2000
|
<Paper className="formulario" modo-despliegue={modoDespliegue} ver-num-opciones={opciones.conCampoOpciones ? 'SI' : 'NO'}>
|
|
1963
|
-
{modo.demo ? <div>
|
|
1964
|
-
<Typography component="span">Modo de despliegue:</Typography>
|
|
1965
|
-
<ButtonGroup>
|
|
1966
|
-
{listaModos.map(modo =>
|
|
1967
|
-
<Button key={modo} variant={modo == modoDespliegue ? "contained" : "outlined"} onClick={
|
|
1968
|
-
() => dispatch(dispatchers.MODO_DESPLIEGUE({ modoDespliegue: modo }))
|
|
1969
|
-
}>{modo}</Button>
|
|
1970
|
-
)}
|
|
1971
|
-
</ButtonGroup>
|
|
1972
|
-
</div> : null}
|
|
1973
2001
|
{pantallaCompleta ? null : <BotonVolverEnDiv id="boton-volver-1" />}
|
|
1974
2002
|
{pantallaCompleta ? null : <FormularioEncabezado casillero={formulario} />}
|
|
1975
2003
|
<DesplegarContenidoInternoBloqueOFormulario bloqueOFormulario={formulario} formulario={formulario} forPk={forPk} multiple={false} />
|
|
@@ -2110,12 +2138,11 @@ setDesplegarCarga((props: {
|
|
|
2110
2138
|
[formulario in PlainForPk]: FormStructureState<IdVariable, Valor, IdFin>
|
|
2111
2139
|
}
|
|
2112
2140
|
}) => {
|
|
2113
|
-
const [newSurvey, setNewSurvey] = useState(0);
|
|
2114
2141
|
const { carga, idCarga, informacionHdr, respuestas } = props;
|
|
2115
2142
|
var estructura = getEstructura();
|
|
2116
2143
|
let cantLineasResumen = likeAr(informacionHdr).filter((informacion) => informacion.tem.carga == idCarga).array().length;
|
|
2117
2144
|
const dispatch = useDispatch();
|
|
2118
|
-
const modoDM: ModoDM =
|
|
2145
|
+
const modoDM: ModoDM = getFormRenderer().getModoDM();
|
|
2119
2146
|
return <Paper className="carga" style={{ marginBottom: '10px', padding: '10px' }}>
|
|
2120
2147
|
<div className="informacion-carga">
|
|
2121
2148
|
<div className="carga">Área: {idCarga}</div>
|
|
@@ -2232,66 +2259,496 @@ export function DesplegarTem(props: { tem: TEM }) {
|
|
|
2232
2259
|
</div>
|
|
2233
2260
|
}
|
|
2234
2261
|
|
|
2235
|
-
export
|
|
2262
|
+
export const handleLogout = async (): Promise<void> => {
|
|
2263
|
+
await getFormRenderer().onLogout();
|
|
2264
|
+
};
|
|
2265
|
+
|
|
2266
|
+
export type AppBarPrincipalProps = {
|
|
2267
|
+
titulo?: React.ReactNode;
|
|
2268
|
+
barraNavFormulario?: React.ReactNode;
|
|
2269
|
+
modoDM: ModoDM;
|
|
2270
|
+
soloLectura?: boolean;
|
|
2271
|
+
children?: React.ReactNode;
|
|
2272
|
+
disabled?: boolean;
|
|
2273
|
+
};
|
|
2274
|
+
|
|
2275
|
+
export function AppBarPrincipal(props: AppBarPrincipalProps): JSX.Element {
|
|
2276
|
+
var color: 'secondary' | 'success' | 'primary' = props.soloLectura ? 'secondary' : props.modoDM === 'capa' ? 'success' : 'primary';
|
|
2277
|
+
var { forPk, pantallaActual } = useSelector((state: CasoState) => state.opciones);
|
|
2278
|
+
const mostrarBotoneraNavegacion = pantallaActual && pantallaActual !== 'sincronizacion_requerida' && !props.barraNavFormulario;
|
|
2279
|
+
return (
|
|
2280
|
+
<AppBar position="fixed" color={color}
|
|
2281
|
+
style={props.disabled ? { pointerEvents: 'none', opacity: 0.9 } : {}}
|
|
2282
|
+
>
|
|
2283
|
+
<Toolbar>
|
|
2284
|
+
{props.barraNavFormulario}
|
|
2285
|
+
{mostrarBotoneraNavegacion ? (
|
|
2286
|
+
<BotoneraNavegacion disabled={props.disabled}/>
|
|
2287
|
+
) : null}
|
|
2288
|
+
{props.modoDM === 'capa' && !props.barraNavFormulario ? (
|
|
2289
|
+
<Typography><span style={{ marginLeft: '5px' }}> MODO CAPACITACIÓN</span></Typography>
|
|
2290
|
+
) : null}
|
|
2291
|
+
<UsuarioLogueadoYConfig mostrarSetup={!forPk} mostrarLogout={!!pantallaActual && !props.barraNavFormulario} onLogout={handleLogout} />
|
|
2292
|
+
</Toolbar>
|
|
2293
|
+
{props.children}
|
|
2294
|
+
</AppBar>
|
|
2295
|
+
);
|
|
2296
|
+
}
|
|
2236
2297
|
|
|
2237
|
-
export
|
|
2298
|
+
export function BotoneraNavegacion(props: { disabled?: boolean }): JSX.Element {
|
|
2299
|
+
const dispatch = useDispatch();
|
|
2300
|
+
const { pantallaActual } = useSelector((state: CasoState) => state.opciones);
|
|
2301
|
+
return (
|
|
2302
|
+
<ButtonGroup variant="outlined" size="small" color="inherit">
|
|
2303
|
+
<Button
|
|
2304
|
+
onClick={() =>
|
|
2305
|
+
dispatch(dispatchers.SET_OPCION({ opcion: 'pantallaActual', valor: 'hdr' }))
|
|
2306
|
+
}
|
|
2307
|
+
disabled={pantallaActual === 'hdr' || props.disabled}
|
|
2308
|
+
style={pantallaActual === 'hdr' ? { backgroundColor: 'rgba(255,255,255,0.1)' } : undefined}
|
|
2309
|
+
>
|
|
2310
|
+
<ICON.Assignment /> Hoja de Ruta
|
|
2311
|
+
</Button>
|
|
2312
|
+
|
|
2313
|
+
<Button
|
|
2314
|
+
onClick={() =>
|
|
2315
|
+
dispatch(dispatchers.SET_OPCION({ opcion: 'pantallaActual', valor: 'sincronizacion' }))
|
|
2316
|
+
}
|
|
2317
|
+
disabled={pantallaActual === 'sincronizacion' || props.disabled}
|
|
2318
|
+
style={pantallaActual === 'sincronizacion' ? { backgroundColor: 'rgba(255,255,255,0.1)' } : undefined}
|
|
2319
|
+
>
|
|
2320
|
+
<ICON.CloudSync /> Sincronización
|
|
2321
|
+
</Button>
|
|
2322
|
+
</ButtonGroup>
|
|
2323
|
+
);
|
|
2324
|
+
}
|
|
2238
2325
|
|
|
2239
|
-
export
|
|
2326
|
+
export function UsuarioLogueadoYConfig(props: {
|
|
2327
|
+
mostrarSetup?: boolean,
|
|
2328
|
+
mostrarLogout?: boolean,
|
|
2329
|
+
onLogout?: () => void,
|
|
2330
|
+
navigationMenu?: React.ReactNode
|
|
2331
|
+
}): JSX.Element {
|
|
2332
|
+
var username: string | null = getFormRenderer().getUsernameLogueado();
|
|
2333
|
+
var idper: string | null = getFormRenderer().getIdperLogueado();
|
|
2334
|
+
var { pantallaActual } = useSelector((state: CasoState) => state.opciones);
|
|
2335
|
+
|
|
2336
|
+
var dispatch = useDispatch();
|
|
2337
|
+
var [openDialog, setOpenDialog] = useState<boolean>(false);
|
|
2338
|
+
|
|
2339
|
+
var handleLogoutClick = (): void => {
|
|
2340
|
+
setOpenDialog(true);
|
|
2341
|
+
};
|
|
2240
2342
|
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2343
|
+
var handleClose = (): void => {
|
|
2344
|
+
setOpenDialog(false);
|
|
2345
|
+
};
|
|
2346
|
+
|
|
2347
|
+
var handleConfirmLogout = async (): Promise<void> => {
|
|
2348
|
+
setOpenDialog(false);
|
|
2349
|
+
if (props.onLogout) {
|
|
2350
|
+
await props.onLogout();
|
|
2351
|
+
}
|
|
2352
|
+
};
|
|
2353
|
+
|
|
2354
|
+
var datos = getDatosByPass();
|
|
2355
|
+
var tieneEncuestas: boolean = !!(datos && datos.informacionHdr && Object.keys(datos.informacionHdr).length > 0);
|
|
2356
|
+
const modoDM = getFormRenderer().getModoDM();
|
|
2248
2357
|
return (
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2358
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
|
|
2359
|
+
{props.navigationMenu}
|
|
2360
|
+
<Typography variant="body2" style={{ color: 'inherit', fontWeight: 'bold', marginLeft:'5px' }}>
|
|
2361
|
+
{idper} - {username}
|
|
2362
|
+
</Typography>
|
|
2363
|
+
{props.mostrarSetup ? (
|
|
2364
|
+
<FastSetup>
|
|
2365
|
+
<MenuItem
|
|
2366
|
+
onClick={() =>
|
|
2367
|
+
dispatch(dispatchers.SET_OPCION({ opcion: 'pantallaActual', valor: 'modo' }))}
|
|
2368
|
+
>
|
|
2369
|
+
<ListItemIcon>{modoDM === 'capa' ? <ICON.BusinessCenter /> : <ICON.SportsEsports />} </ListItemIcon>
|
|
2370
|
+
<ListItemText>Cambio a modo {modoDM === 'capa' ? 'Producción' : 'Capacitación'}</ListItemText>
|
|
2371
|
+
</MenuItem>
|
|
2372
|
+
<Divider/>
|
|
2373
|
+
<MenuItem
|
|
2374
|
+
disabled={true}
|
|
2375
|
+
>
|
|
2376
|
+
<ListItemText>Soporte técnico</ListItemText>
|
|
2377
|
+
</MenuItem>
|
|
2378
|
+
<MenuItem
|
|
2379
|
+
onClick={() =>
|
|
2380
|
+
dispatch(dispatchers.RESET_OPCIONES({}))}
|
|
2381
|
+
>
|
|
2382
|
+
<ListItemIcon><ICON.Refresh/></ListItemIcon>
|
|
2383
|
+
<ListItemText>Reset opciones</ListItemText>
|
|
2384
|
+
</MenuItem>
|
|
2385
|
+
<MenuItem
|
|
2386
|
+
onClick={() => {
|
|
2387
|
+
history.replaceState(null, '', `${location.origin + location.pathname}/../menu#i=sincronizar`);
|
|
2388
|
+
location.reload();
|
|
2389
|
+
}}
|
|
2390
|
+
>
|
|
2391
|
+
<ListItemIcon><ICON.SyncAlt /></ListItemIcon>
|
|
2392
|
+
<ListItemText>Sincronización (link viejo)</ListItemText>
|
|
2393
|
+
</MenuItem>
|
|
2394
|
+
</FastSetup>
|
|
2395
|
+
) : null}
|
|
2396
|
+
{props.mostrarLogout ? (
|
|
2397
|
+
<Button color="inherit" onClick={handleLogoutClick} style={{ minWidth: 'auto', padding: '6px' }}>
|
|
2398
|
+
<ICON.ExitToApp />
|
|
2399
|
+
</Button>
|
|
2400
|
+
) : null}
|
|
2401
|
+
|
|
2402
|
+
<Dialog open={openDialog} onClose={handleClose}>
|
|
2403
|
+
<DialogTitle>Cerrar Sesión</DialogTitle>
|
|
2404
|
+
<DialogContent>
|
|
2405
|
+
<DialogContentText>
|
|
2406
|
+
{tieneEncuestas
|
|
2407
|
+
? "Hay encuestas cargadas en el dispositivo. Si sale de la aplicación sin sincronizar podría perder el trabajo realizado."
|
|
2408
|
+
: "¿Está seguro de que desea salir? Para volver a ingresar deberá iniciar sesión nuevamente."
|
|
2409
|
+
}
|
|
2410
|
+
</DialogContentText>
|
|
2411
|
+
</DialogContent>
|
|
2412
|
+
<DialogActions>
|
|
2413
|
+
{tieneEncuestas ? (
|
|
2264
2414
|
<>
|
|
2265
|
-
<Button
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
gotoSincronizar()
|
|
2271
|
-
}}
|
|
2272
|
-
>
|
|
2273
|
-
<ICON.SyncAlt />
|
|
2415
|
+
<Button onClick={handleConfirmLogout} color="secondary">
|
|
2416
|
+
Salir de todos modos
|
|
2417
|
+
</Button>
|
|
2418
|
+
<Button onClick={handleClose} color="primary" variant="contained">
|
|
2419
|
+
Continuar relevando
|
|
2274
2420
|
</Button>
|
|
2275
2421
|
</>
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2422
|
+
) : (
|
|
2423
|
+
<>
|
|
2424
|
+
<Button onClick={handleClose} color="inherit">
|
|
2425
|
+
Cancelar
|
|
2426
|
+
</Button>
|
|
2427
|
+
<Button onClick={handleConfirmLogout} color="primary" variant="contained">
|
|
2428
|
+
Salir
|
|
2429
|
+
</Button>
|
|
2430
|
+
</>
|
|
2431
|
+
)}
|
|
2432
|
+
</DialogActions>
|
|
2433
|
+
</Dialog>
|
|
2434
|
+
</div>
|
|
2435
|
+
);
|
|
2436
|
+
}
|
|
2437
|
+
|
|
2438
|
+
export interface LayoutAccionDispositivoProps {
|
|
2439
|
+
tituloAppBar: React.ReactNode;
|
|
2440
|
+
tituloPanel: string;
|
|
2441
|
+
headerAdicional?: React.ReactNode;
|
|
2442
|
+
|
|
2443
|
+
modoDM: ModoDM;
|
|
2444
|
+
online: boolean;
|
|
2445
|
+
|
|
2446
|
+
loading?: boolean;
|
|
2447
|
+
aviso?: { tipo: 'info' | 'success' | 'error', mensaje: string } | null;
|
|
2448
|
+
|
|
2449
|
+
textoBotonAccion: React.ReactNode;
|
|
2450
|
+
colorBotonAccion?: ColorValues;
|
|
2451
|
+
onAccion: () => void;
|
|
2452
|
+
|
|
2453
|
+
deshabilitarBotonVolver?: boolean;
|
|
2454
|
+
mensajeVacio?: string;
|
|
2455
|
+
|
|
2456
|
+
childrenModales?: React.ReactNode;
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2459
|
+
export function LayoutAccionDispositivo(props: LayoutAccionDispositivoProps): JSX.Element {
|
|
2460
|
+
const datosByPass = getDatosByPass();
|
|
2461
|
+
const estructura = getEstructura();
|
|
2462
|
+
const dispatch = useDispatch();
|
|
2463
|
+
useEffect(() => {
|
|
2464
|
+
scrollToTop();
|
|
2465
|
+
}, []);
|
|
2466
|
+
|
|
2467
|
+
const avisoRedux = useSelector((state: CasoState) => state.opciones.avisoPersistente);
|
|
2468
|
+
const avisoAMostrar = props.aviso || avisoRedux;
|
|
2469
|
+
useEffect(() => {
|
|
2470
|
+
if (avisoRedux) {
|
|
2471
|
+
const timer = setTimeout(() => {
|
|
2472
|
+
dispatch(dispatchers.SET_OPCION({ opcion: 'avisoPersistente', valor: null }));
|
|
2473
|
+
}, 5000);
|
|
2474
|
+
return () => clearTimeout(timer);
|
|
2475
|
+
}
|
|
2476
|
+
return
|
|
2477
|
+
}, [avisoRedux, dispatch]);
|
|
2478
|
+
|
|
2479
|
+
const cantCargas: number = hayDatosByPassAlmacenados() ? likeAr(datosByPass.cargas).array().length : 0;
|
|
2480
|
+
const cantRespuestas: number = hayDatosByPassAlmacenados() && estructura ? likeAr(datosByPass.respuestas[estructura.uaPpal]).array().length : 0;
|
|
2481
|
+
|
|
2482
|
+
return (
|
|
2483
|
+
<>
|
|
2484
|
+
<AppBarPrincipal
|
|
2485
|
+
modoDM={props.modoDM}
|
|
2486
|
+
titulo={props.tituloAppBar}
|
|
2487
|
+
disabled={props.loading}
|
|
2488
|
+
/>
|
|
2280
2489
|
<div className="hoja-de-ruta">
|
|
2281
|
-
<
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2490
|
+
<InfoVersionSincroDespliegue/>
|
|
2491
|
+
<Paper style={{ padding: '20px', margin: 'auto', marginBottom: '10px' }}>
|
|
2492
|
+
<Typography variant="h5">{props.tituloPanel}</Typography>
|
|
2493
|
+
|
|
2494
|
+
{props.headerAdicional}
|
|
2495
|
+
|
|
2496
|
+
{hayDatosByPassAlmacenados() ? (
|
|
2497
|
+
<div style={{ marginBottom: '20px' }}>
|
|
2498
|
+
<Typography variant="h6">Información del dispositivo:</Typography>
|
|
2499
|
+
<Typography>{cantCargas} áreas: {likeAr(datosByPass.cargas).keys().join(', ')}</Typography>
|
|
2500
|
+
<Typography>{cantRespuestas} {estructura?.uaPpal || 'viviendas'}</Typography>
|
|
2501
|
+
</div>
|
|
2502
|
+
) : (
|
|
2503
|
+
props.mensajeVacio && props.mensajeVacio.trim() !== "" ? (
|
|
2504
|
+
<Typography style={{ marginBottom: '20px' }}>{props.mensajeVacio}</Typography>
|
|
2505
|
+
) : null
|
|
2506
|
+
)}
|
|
2507
|
+
|
|
2508
|
+
{avisoAMostrar && (
|
|
2509
|
+
<Paper style={{
|
|
2510
|
+
padding: '10px',
|
|
2511
|
+
marginBottom: '20px',
|
|
2512
|
+
backgroundColor: avisoAMostrar.tipo === 'success' ? '#e6fffa' : avisoAMostrar.tipo === 'error' ? '#fff5f5' : '#edf2f7',
|
|
2513
|
+
color: avisoAMostrar.tipo === 'success' ? '#234e52' : avisoAMostrar.tipo === 'error' ? '#9b2c2c' : '#2d3748',
|
|
2514
|
+
border: `1px solid ${avisoAMostrar.tipo === 'success' ? '#319795' : avisoAMostrar.tipo === 'error' ? '#e53e3e' : '#cbd5e0'}`
|
|
2515
|
+
}}>
|
|
2516
|
+
<Typography>{avisoAMostrar.mensaje}</Typography>
|
|
2517
|
+
</Paper>
|
|
2518
|
+
)}
|
|
2519
|
+
|
|
2520
|
+
<div style={{ display: 'flex', gap: '10px', alignItems: 'center', flexWrap: 'wrap' }}>
|
|
2521
|
+
<Button
|
|
2522
|
+
variant="contained"
|
|
2523
|
+
color={props.colorBotonAccion || 'primary'}
|
|
2524
|
+
disabled={props.loading || !props.online}
|
|
2525
|
+
onClick={props.onAccion}
|
|
2286
2526
|
>
|
|
2287
|
-
|
|
2288
|
-
</Button>
|
|
2289
|
-
</div>
|
|
2290
|
-
<div
|
|
2291
|
-
|
|
2292
|
-
|
|
2527
|
+
{props.textoBotonAccion}
|
|
2528
|
+
</Button>
|
|
2529
|
+
</div>
|
|
2530
|
+
<div style={{ display: 'flex', gap: '10px', alignItems: 'center', flexWrap: 'wrap' }}>
|
|
2531
|
+
{!props.online && (
|
|
2532
|
+
<Typography color="secondary" style={{ marginLeft: props.deshabilitarBotonVolver ? '0px' : '10px' }}>
|
|
2533
|
+
Debe estar conectado a internet para realizar esta acción.
|
|
2534
|
+
</Typography>
|
|
2535
|
+
)}
|
|
2293
2536
|
</div>
|
|
2294
2537
|
</Paper>
|
|
2538
|
+
</div>
|
|
2539
|
+
|
|
2540
|
+
{props.childrenModales}
|
|
2541
|
+
</>
|
|
2542
|
+
);
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2545
|
+
interface PantallaSincronizacionProps {
|
|
2546
|
+
// Props opcionales para el "sabor" requerida
|
|
2547
|
+
requerida?: boolean;
|
|
2548
|
+
mensajeRequerido?: React.ReactNode;
|
|
2549
|
+
}
|
|
2550
|
+
|
|
2551
|
+
export function PantallaSincronizacion(props: PantallaSincronizacionProps): JSX.Element {
|
|
2552
|
+
const [loading, setLoading] = useState<boolean>(false);
|
|
2553
|
+
const avisoPersistente = useSelector((state: CasoState) => state.opciones.avisoPersistente);
|
|
2554
|
+
const online: boolean = useOnlineStatus();
|
|
2555
|
+
const dispatch = useDispatch();
|
|
2556
|
+
const modoDM = getFormRenderer().getModoDM();
|
|
2557
|
+
|
|
2558
|
+
const handleSincronizar = async (): Promise<void> => {
|
|
2559
|
+
setLoading(true);
|
|
2560
|
+
try {
|
|
2561
|
+
dispatch(dispatchers.SET_OPCION({ opcion: 'avisoPersistente', valor: null }));
|
|
2562
|
+
const formRenderer = getFormRenderer();
|
|
2563
|
+
const datos = await formRenderer.onSincronizar(await formRenderer.leerDatos(), false);
|
|
2564
|
+
await formRenderer.cargarMotor();
|
|
2565
|
+
const mensajeExito = `Sincronización exitosa. Sincro Nº ${datos.num_sincro}`;
|
|
2566
|
+
dispatch(dispatchers.SET_PANTALLA_ACTUAL({ pantalla: 'sincronizacion', avisoPersistente: { tipo: 'success', mensaje: mensajeExito } }));
|
|
2567
|
+
} catch (err) {
|
|
2568
|
+
console.log(err)
|
|
2569
|
+
dispatch(dispatchers.SET_PANTALLA_ACTUAL({
|
|
2570
|
+
pantalla: props.requerida ? 'sincronizacion_requerida' : 'sincronizacion',
|
|
2571
|
+
avisoPersistente: { tipo: 'error', mensaje: `Error de sincronización: ${unexpected(err).message}` }
|
|
2572
|
+
}));
|
|
2573
|
+
} finally {
|
|
2574
|
+
setLoading(false);
|
|
2575
|
+
}
|
|
2576
|
+
};
|
|
2577
|
+
|
|
2578
|
+
// Estilo para el mensaje cuando es requerida
|
|
2579
|
+
const paragraphStyles = { fontSize: "1.2rem", fontWeight: 600, padding: "5px 10px", marginBottom: "15px" };
|
|
2580
|
+
|
|
2581
|
+
// Si es requerida, inyectamos el mensaje explicativo arriba
|
|
2582
|
+
const headerAdicional = props.requerida && props.mensajeRequerido ? (
|
|
2583
|
+
<Typography component="div" style={paragraphStyles}>
|
|
2584
|
+
{props.mensajeRequerido}
|
|
2585
|
+
</Typography>
|
|
2586
|
+
) : null;
|
|
2587
|
+
|
|
2588
|
+
return (
|
|
2589
|
+
<LayoutAccionDispositivo
|
|
2590
|
+
tituloAppBar={props.requerida ? `SINCRONIZACIÓN REQUERIDA${modoDM === 'capa' ? ' - CAPA' : ''}` : 'SINCRONIZACIÓN'}
|
|
2591
|
+
modoDM={modoDM}
|
|
2592
|
+
tituloPanel={props.requerida ? "Sincronización Requerida" : "Sincronizar Dispositivo"}
|
|
2593
|
+
headerAdicional={headerAdicional}
|
|
2594
|
+
aviso={avisoPersistente}
|
|
2595
|
+
loading={loading}
|
|
2596
|
+
online={online}
|
|
2597
|
+
textoBotonAccion={
|
|
2598
|
+
loading ?
|
|
2599
|
+
'Sincronizando...'
|
|
2600
|
+
:
|
|
2601
|
+
<span style={{ display: 'flex', alignItems: 'center', gap: '8px' }}><ICON.CloudSync /> Sincronizar</span>
|
|
2602
|
+
}
|
|
2603
|
+
colorBotonAccion={modoDM === 'capa' ? 'success' : 'primary'}
|
|
2604
|
+
onAccion={handleSincronizar}
|
|
2605
|
+
mensajeVacio={props.requerida ? " " : "No hay información de formularios localmente."}
|
|
2606
|
+
/>
|
|
2607
|
+
);
|
|
2608
|
+
}
|
|
2609
|
+
|
|
2610
|
+
export function PantallaCambioModo(): JSX.Element {
|
|
2611
|
+
const [loading, setLoading] = useState<boolean>(false);
|
|
2612
|
+
const [aviso, setAviso] = useState<{ tipo: 'info' | 'success' | 'error', mensaje: string } | null>(null);
|
|
2613
|
+
const [password, setPassword] = useState<string>('');
|
|
2614
|
+
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
|
2615
|
+
const [modoDM, setModoDM] = useState<ModoDM>('produc');
|
|
2616
|
+
const [errorPassword, setErrorPassword] = useState<string | null>(null);
|
|
2617
|
+
const online: boolean = useOnlineStatus();
|
|
2618
|
+
const dispatch = useDispatch();
|
|
2619
|
+
|
|
2620
|
+
useEffect(() => {
|
|
2621
|
+
const fetchModo = async (): Promise<void> => {
|
|
2622
|
+
const m: ModoDM = getFormRenderer().getModoDM();
|
|
2623
|
+
getFormRenderer().setModoDM(m);
|
|
2624
|
+
setModoDM(m);
|
|
2625
|
+
};
|
|
2626
|
+
fetchModo();
|
|
2627
|
+
}, []);
|
|
2628
|
+
|
|
2629
|
+
const handleConfirmarCambio = async (): Promise<void> => {
|
|
2630
|
+
if (password !== '1234') {
|
|
2631
|
+
setErrorPassword('Contraseña incorrecta.');
|
|
2632
|
+
return;
|
|
2633
|
+
}
|
|
2634
|
+
setErrorPassword(null);
|
|
2635
|
+
setDialogOpen(false);
|
|
2636
|
+
setLoading(true);
|
|
2637
|
+
setAviso(null);
|
|
2638
|
+
try {
|
|
2639
|
+
const nuevoModo: ModoDM = modoDM === 'produc' ? 'capa' : 'produc';
|
|
2640
|
+
const formRenderer = getFormRenderer();
|
|
2641
|
+
await formRenderer.onSincronizar(await formRenderer.leerDatos(), true);
|
|
2642
|
+
formRenderer.setModoDM(nuevoModo);
|
|
2643
|
+
setModoDM(nuevoModo);
|
|
2644
|
+
await formRenderer.cargarMotor();
|
|
2645
|
+
setAviso({ tipo: 'success', mensaje: `MODO ${nuevoModo.toUpperCase()} ACTIVADO Y DISPOSITIVO SINCRONIZADO` });
|
|
2646
|
+
dispatch(dispatchers.SET_OPCION({ opcion: 'pantallaActual', valor: 'modo' }));
|
|
2647
|
+
} catch (err) {
|
|
2648
|
+
setAviso({ tipo: 'error', mensaje: `Error al cambiar de modo: ${unexpected(err).message}` });
|
|
2649
|
+
} finally {
|
|
2650
|
+
setLoading(false);
|
|
2651
|
+
setPassword('');
|
|
2652
|
+
}
|
|
2653
|
+
};
|
|
2654
|
+
|
|
2655
|
+
const headerAdicionalText = (
|
|
2656
|
+
<Typography style={{ marginBottom: '20px', fontWeight: 'bold' }}>
|
|
2657
|
+
Modo actual: <span style={{ color: modoDM === 'capa' ? 'green' : 'blue', textTransform: 'uppercase' }}>{modoDM}</span>
|
|
2658
|
+
</Typography>
|
|
2659
|
+
);
|
|
2660
|
+
|
|
2661
|
+
return (
|
|
2662
|
+
<LayoutAccionDispositivo
|
|
2663
|
+
tituloAppBar="CAMBIO DE MODO"
|
|
2664
|
+
modoDM={modoDM}
|
|
2665
|
+
tituloPanel="Cambiar Modo del Dispositivo"
|
|
2666
|
+
headerAdicional={headerAdicionalText}
|
|
2667
|
+
aviso={aviso}
|
|
2668
|
+
loading={loading}
|
|
2669
|
+
online={online}
|
|
2670
|
+
textoBotonAccion={`Cambiar a modo ${modoDM === 'produc' ? 'capa' : 'produc'}`}
|
|
2671
|
+
colorBotonAccion={modoDM === 'produc' ? 'primary' : 'success'}
|
|
2672
|
+
onAccion={() => { setErrorPassword(null); setDialogOpen(true); }}
|
|
2673
|
+
childrenModales={
|
|
2674
|
+
<Dialog open={dialogOpen} onClose={() => { setDialogOpen(false); setPassword(''); setErrorPassword(null); }}>
|
|
2675
|
+
<DialogTitle>Confirmar cambio de modo</DialogTitle>
|
|
2676
|
+
<DialogContent>
|
|
2677
|
+
<DialogContentText style={{ marginBottom: '15px' }}>
|
|
2678
|
+
Confirma cambio de modo "{modoDM}" a "{modoDM === 'produc' ? 'capa' : 'produc'}". Se sincronizará el dispositivo.
|
|
2679
|
+
</DialogContentText>
|
|
2680
|
+
{errorPassword && (
|
|
2681
|
+
<Typography style={{ color: '#d32f2f', marginBottom: '15px', fontWeight: 'bold' }}>
|
|
2682
|
+
{errorPassword}
|
|
2683
|
+
</Typography>
|
|
2684
|
+
)}
|
|
2685
|
+
<Typography variant="body2" style={{ marginBottom: '10px' }}>Por favor ingrese la contraseña:</Typography>
|
|
2686
|
+
<input
|
|
2687
|
+
type="password"
|
|
2688
|
+
value={password}
|
|
2689
|
+
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
|
2690
|
+
setPassword(e.target.value);
|
|
2691
|
+
if (errorPassword) {
|
|
2692
|
+
setErrorPassword(null);
|
|
2693
|
+
}
|
|
2694
|
+
}}
|
|
2695
|
+
style={{ width: '100%', padding: '10px', fontSize: '16px' }}
|
|
2696
|
+
/>
|
|
2697
|
+
</DialogContent>
|
|
2698
|
+
<DialogActions>
|
|
2699
|
+
<Button onClick={() => { setDialogOpen(false); setPassword(''); setErrorPassword(null); }} color="inherit">
|
|
2700
|
+
Cancelar
|
|
2701
|
+
</Button>
|
|
2702
|
+
<Button onClick={handleConfirmarCambio} color="primary" variant="contained">
|
|
2703
|
+
Confirmar
|
|
2704
|
+
</Button>
|
|
2705
|
+
</DialogActions>
|
|
2706
|
+
</Dialog>
|
|
2707
|
+
}
|
|
2708
|
+
/>
|
|
2709
|
+
);
|
|
2710
|
+
}
|
|
2711
|
+
|
|
2712
|
+
interface InfoVersionSincroDespliegueProps {
|
|
2713
|
+
}
|
|
2714
|
+
|
|
2715
|
+
export function InfoVersionSincroDespliegue(_props: InfoVersionSincroDespliegueProps): JSX.Element {
|
|
2716
|
+
const version = getFormRenderer().getAppCacheVersion();
|
|
2717
|
+
const { num_sincro } = getDatosByPass();
|
|
2718
|
+
return (
|
|
2719
|
+
<Paper style={{ marginBottom: '10px', padding: '10px' }}>
|
|
2720
|
+
<div className="nombre-version">
|
|
2721
|
+
<div>Instituto de Estadística y Censos de la Ciudad Autónoma de Buenos Aires - IDECBA</div>
|
|
2722
|
+
<div>versión {version} - {num_sincro ? `sincro: ${num_sincro.toString()}` : 'sin sincronizar'}</div>
|
|
2723
|
+
</div>
|
|
2724
|
+
</Paper>
|
|
2725
|
+
);
|
|
2726
|
+
}
|
|
2727
|
+
|
|
2728
|
+
export type HojaDeRutaDespliegueProps = {
|
|
2729
|
+
};
|
|
2730
|
+
|
|
2731
|
+
export type HojaDeRutaDespliegueType = (props: HojaDeRutaDespliegueProps) => JSX.Element;
|
|
2732
|
+
|
|
2733
|
+
export var HojaDeRutaDespliegue: HojaDeRutaDespliegueType
|
|
2734
|
+
|
|
2735
|
+
export const setHojaDeRutaDespliegue = (hojaDeRuta: HojaDeRutaDespliegueType) => HojaDeRutaDespliegue = hojaDeRuta
|
|
2736
|
+
|
|
2737
|
+
setHojaDeRutaDespliegue((_props: HojaDeRutaDespliegueProps) => {
|
|
2738
|
+
useEffect(() => {
|
|
2739
|
+
scrollToTop();
|
|
2740
|
+
}, []);
|
|
2741
|
+
var { cargas, num_sincro, informacionHdr, respuestas } = getDatosByPass();
|
|
2742
|
+
var feedbackRowValidator = getFeedbackRowValidator();
|
|
2743
|
+
const modoDM: ModoDM = getFormRenderer().getModoDM();
|
|
2744
|
+
return (
|
|
2745
|
+
<>
|
|
2746
|
+
<AppBarPrincipal
|
|
2747
|
+
modoDM={modoDM}
|
|
2748
|
+
titulo="HOJA DE RUTA"
|
|
2749
|
+
/>
|
|
2750
|
+
<div className="hoja-de-ruta">
|
|
2751
|
+
<InfoVersionSincroDespliegue/>
|
|
2295
2752
|
{likeAr(cargas).map((carga, idCarga, _, posicion) =>
|
|
2296
2753
|
<DesplegarCarga key={idCarga} carga={carga} idCarga={idCarga} posicion={posicion} informacionHdr={informacionHdr} feedbackRowValidator={feedbackRowValidator} respuestas={respuestas} />
|
|
2297
2754
|
).array()}
|
|
@@ -2306,41 +2763,6 @@ export function ListaTextos(props: { textos: string[] }) {
|
|
|
2306
2763
|
</ul>;
|
|
2307
2764
|
}
|
|
2308
2765
|
|
|
2309
|
-
export function BienvenidaDespliegue(props: { modo: CasoState["modo"] }) {
|
|
2310
|
-
const dispatch = useDispatch();
|
|
2311
|
-
return <Paper className="bienvenida">
|
|
2312
|
-
{props.modo.demo ?
|
|
2313
|
-
<>
|
|
2314
|
-
<Typography>DEMO del sistema de relevamiento de DMENCU</Typography>
|
|
2315
|
-
<Typography>En esta demo:</Typography>
|
|
2316
|
-
<ListaTextos textos={[
|
|
2317
|
-
"Algunas viviendas aparecen relevadas (el botón está de color) sirven de ejemplo",
|
|
2318
|
-
"Lo que se carguen se guardan localmente pero no se trasmiten a la base de datos",
|
|
2319
|
-
"Se puede volver a la versión inicial (o sea borrar lo que se guardó localmente) desde la hoja de ruta boton [reiniciar demo]",
|
|
2320
|
-
"Todavía hay cosas que faltan o pueden cambiar",
|
|
2321
|
-
]} />
|
|
2322
|
-
</>
|
|
2323
|
-
: <>
|
|
2324
|
-
<Typography>Encuesta de Seroprevalencia de COVID-19</Typography>
|
|
2325
|
-
</>
|
|
2326
|
-
}
|
|
2327
|
-
<Button
|
|
2328
|
-
variant="contained"
|
|
2329
|
-
color="secondary"
|
|
2330
|
-
onClick={() => { gotoSincronizar(); }}
|
|
2331
|
-
>
|
|
2332
|
-
<span>Sincronizar </span> <ICON.SyncAlt />
|
|
2333
|
-
</Button>
|
|
2334
|
-
<Button
|
|
2335
|
-
variant="contained"
|
|
2336
|
-
color="primary"
|
|
2337
|
-
onClick={() => dispatch(dispatchers.SET_OPCION({ opcion: 'bienvenido', valor: true }))}
|
|
2338
|
-
>
|
|
2339
|
-
<span>Continuar </span> <ICON.Send />
|
|
2340
|
-
</Button>
|
|
2341
|
-
</Paper>
|
|
2342
|
-
}
|
|
2343
|
-
|
|
2344
2766
|
//CONTROL DE PESTAÑAS
|
|
2345
2767
|
var allOpenedTabs: { [x: string]: number } = {};
|
|
2346
2768
|
var infoOpenedTabs = {
|
|
@@ -2366,88 +2788,50 @@ export function OpenedTabs() {
|
|
|
2366
2788
|
}
|
|
2367
2789
|
|
|
2368
2790
|
export function AppDmEncu() {
|
|
2369
|
-
var { forPk,
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
} else if (forPk == null) {
|
|
2373
|
-
return <HojaDeRutaDespliegue />
|
|
2374
|
-
} else {
|
|
2375
|
-
return <FormularioDespliegue forPk={forPk} />
|
|
2376
|
-
}
|
|
2377
|
-
}
|
|
2791
|
+
var { forPk, pantallaActual } = useSelector((state: CasoState) => state.opciones);
|
|
2792
|
+
var datosByPass = getDatosByPass();
|
|
2793
|
+
const dispatch = useDispatch();
|
|
2378
2794
|
|
|
2379
|
-
|
|
2380
|
-
const
|
|
2795
|
+
// Determinar si la sincronización es requerida
|
|
2796
|
+
const sincroRequerida = !hayDatosByPassAlmacenados()
|
|
2797
|
+
|| (hayDatosByPassAlmacenados() && datosByPass.idper !== getFormRenderer().getIdperLogueado());
|
|
2381
2798
|
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
<Button
|
|
2400
|
-
color={modoDM == 'capa' ? 'success' : "primary"}
|
|
2401
|
-
variant="contained"
|
|
2402
|
-
onClick={() => {
|
|
2403
|
-
gotoSincronizar()
|
|
2404
|
-
}}
|
|
2405
|
-
>
|
|
2406
|
-
<ICON.SyncAlt />
|
|
2407
|
-
</Button>
|
|
2408
|
-
</span>
|
|
2409
|
-
</Typography>
|
|
2410
|
-
</>
|
|
2411
|
-
:
|
|
2412
|
-
<Typography component="p" style={paragraphStyles}>
|
|
2413
|
-
No hay conexión a internet, por favor conécte el dispositivo a una red para sincronizar una hoja de ruta.
|
|
2414
|
-
</Typography>
|
|
2415
|
-
}
|
|
2416
|
-
</div>
|
|
2417
|
-
</Paper>
|
|
2418
|
-
</main>
|
|
2419
|
-
</>
|
|
2420
|
-
);
|
|
2421
|
-
}
|
|
2799
|
+
// Si la sincro es requerida, forzar pantallaActual vía Redux
|
|
2800
|
+
useEffect(() => {
|
|
2801
|
+
if (sincroRequerida && pantallaActual !== 'sincronizacion_requerida') {
|
|
2802
|
+
dispatch(dispatchers.SET_OPCION({ opcion: 'pantallaActual', valor: 'sincronizacion_requerida' }));
|
|
2803
|
+
}
|
|
2804
|
+
}, [sincroRequerida, pantallaActual, dispatch]);
|
|
2805
|
+
|
|
2806
|
+
if (sincroRequerida) {
|
|
2807
|
+
const mensaje = !hayDatosByPassAlmacenados()
|
|
2808
|
+
? <> Debe sincronizar el dispositivo para obtener una hoja de ruta.</>
|
|
2809
|
+
: <> El usuario autenticado no coincide con el usuario asociado al
|
|
2810
|
+
trabajo almacenado en la tablet.
|
|
2811
|
+
<br />
|
|
2812
|
+
Debe sincronizar antes de continuar.
|
|
2813
|
+
</>;
|
|
2814
|
+
return <PantallaSincronizacion requerida={true} mensajeRequerido={mensaje} />;
|
|
2815
|
+
}
|
|
2422
2816
|
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2817
|
+
if (forPk == null) {
|
|
2818
|
+
if (pantallaActual === 'sincronizacion') {
|
|
2819
|
+
return <PantallaSincronizacion />
|
|
2820
|
+
} else if (pantallaActual === 'modo') {
|
|
2821
|
+
return <PantallaCambioModo />
|
|
2822
|
+
}
|
|
2428
2823
|
return <HojaDeRutaDespliegue />
|
|
2429
2824
|
} else {
|
|
2430
2825
|
return <FormularioDespliegue forPk={forPk} />
|
|
2431
2826
|
}
|
|
2432
2827
|
}
|
|
2433
2828
|
|
|
2434
|
-
export async function
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
ReactDOM.render(
|
|
2441
|
-
<PantallaInicialSinCarga />,
|
|
2442
|
-
document.getElementById('main_layout')
|
|
2443
|
-
)
|
|
2444
|
-
}
|
|
2445
|
-
|
|
2446
|
-
export async function desplegarFormularioActual(opts: { modoDemo: boolean, forPkRaiz?: ForPkRaiz, operativo: IdOperativo }) {
|
|
2447
|
-
// traer los metadatos en una "estructura"
|
|
2448
|
-
// traer los datos de localStorage
|
|
2449
|
-
// verificar el main Layout
|
|
2450
|
-
const store = await dmTraerDatosFormulario(opts)
|
|
2829
|
+
export async function desplegarFormularioActual(
|
|
2830
|
+
formRenderer: FormRenderer,
|
|
2831
|
+
opts: { forPkRaiz?: ForPkRaiz } = {}
|
|
2832
|
+
) {
|
|
2833
|
+
await formRenderer.cargarMotor();
|
|
2834
|
+
const store = await crearStoreFormulario(opts)
|
|
2451
2835
|
try {
|
|
2452
2836
|
await loadCSS(BOOTSTRAP_5_1_3_SRC);
|
|
2453
2837
|
} catch (err) {
|
|
@@ -2462,14 +2846,6 @@ export async function desplegarFormularioActual(opts: { modoDemo: boolean, forPk
|
|
|
2462
2846
|
)
|
|
2463
2847
|
}
|
|
2464
2848
|
|
|
2465
|
-
if (typeof window !== 'undefined') {
|
|
2466
|
-
// @ts-ignore para hacerlo
|
|
2467
|
-
window.desplegarFormularioActual = desplegarFormularioActual;
|
|
2468
|
-
// @ts-ignore para hacerlo
|
|
2469
|
-
window.dmPantallaInicialSinCarga = dmPantallaInicialSinCarga;
|
|
2470
|
-
}
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
2849
|
function loadInstance() {
|
|
2474
2850
|
if (typeof BroadcastChannel === 'undefined') {
|
|
2475
2851
|
return;
|