convertToLocalFormat(d, dateFormat))\n .join(', ')} // convert to local format before join\n onChange={handleMultidateChange}\n closable={false}\n />\n );\n break;\n case FIELD_TYPE.date:\n default:\n renderPicker = (\n \n );\n break;\n }\n\n return (\n {\n if (e.key !== 'Tab') {\n e.preventDefault(); // block others keys if this is not Tab key\n }\n }}\n className=\"field column\"\n >\n {renderPicker} \n
\n );\n};\n\nexport default CalendarPicker;\n","import React from 'react';\nimport { withTranslation } from 'react-i18next';\nimport { Grid, Icon } from 'semantic-ui-react';\nimport { Views } from 'react-big-calendar';\nimport styled from 'styled-components';\nimport _ from 'lodash';\n\nimport Utils from 'core/utils/utils';\nimport { getDateFormatted } from 'core/utils/date';\nimport { ThemedButton } from 'components';\nimport FasterDropdown from '../../input/dropdown/fasterDropdownContainer';\nimport CalendarPicker from '../../input/calendar/CalendarPicker';\nimport { getMoment } from '../../../core/utils/date';\n\nconst { DAY, WEEK, MONTH } = Views;\n\nconst StyledGrid = styled(Grid)`\n &&& {\n margin-bottom: -0.5rem;\n }\n`;\n\nconst StyledDiv = styled.div`\n display: flex;\n`;\n\nconst StyledButton = styled(ThemedButton)`\n &&& {\n margin: 0;\n }\n`;\n\nconst StyledDropdown = styled(FasterDropdown)`\n &&& {\n margin-left: 5px;\n margin-right: 5px;\n }\n`;\n\nconst prevnext = (view, oldDateString, next = false) => {\n const newMoment = getMoment(oldDateString);\n const increment = next ? 1 : -1;\n\n if (view === MONTH) {\n newMoment.month(newMoment.month() + increment);\n } else if (view === WEEK) {\n newMoment.week(newMoment.week() + increment);\n } else if (view === DAY) {\n newMoment.dayOfYear(newMoment.dayOfYear() + increment);\n }\n\n return getDateFormatted(newMoment.toDate());\n};\n\nconst Toolbar = ({\n // state\n t,\n // props\n dataLoading,\n selectedDate,\n view,\n views,\n // func\n handleChangeDate,\n handleChangeView,\n}) => {\n const onChangeDate = (e, { value }) => {\n handleChangeDate(value);\n };\n\n const onPrevious = () => {\n handleChangeDate(prevnext(view, selectedDate, false));\n };\n\n const onNext = () => {\n handleChangeDate(prevnext(view, selectedDate, true));\n };\n\n const label = getMoment(selectedDate).format(\n `${view === DAY ? 'DD ' : ''}MMM YYYY`\n );\n\n return (\n \n \n \n \n ({\n key: v,\n text: t(`calendar|${Utils.toSentenceCase(v)}`),\n value: v,\n }))}\n onChange={(e, { value }) => handleChangeView(value)}\n />\n \n \n \n \n {dataLoading && }\n {label}\n \n \n \n \n \n );\n};\n\nexport default withTranslation()(Toolbar);\n","export default {\n allDay: 'Journée',\n previous: 'Précédent',\n next: 'Suivant',\n today: \"Aujourd'hui\",\n month: 'Mois',\n week: 'Semaine',\n day: 'Jour',\n agenda: 'Calendrier',\n date: 'Date',\n time: 'Heure',\n event: 'Événement',\n showMore: total => `+ ${total} événement(s) supplémentaire(s)`,\n};\n","import 'react-big-calendar/lib/css/react-big-calendar.css';\nimport 'moment/locale/fr';\n\nimport React from 'react';\nimport moment from 'moment';\nimport { arrayOf, object } from 'prop-types';\nimport { Calendar, momentLocalizer, Views } from 'react-big-calendar';\n\nimport i18n from 'config/i18n';\n\nimport {\n CalendarWrapper,\n CalendarPopupWrapper,\n} from './components/CalendarWrapper';\nimport Toolbar from './components/Toolbar';\nimport messagesFrench from './helpers/messagesFrench';\nimport { langIsFrench } from './helpers/initializeAgendaCriteria';\n\nconst localizer = momentLocalizer(moment);\nconst { WEEK, MONTH } = Views;\n\nconst FasterAgenda = ({\n calendarProps: { currentDate, views, currentView, color, events },\n dataLoading,\n selectedDate,\n handleChangeDate,\n handleNavigate,\n handleChangeView,\n handleDoubleClick,\n ...props\n}) => {\n const messages = langIsFrench ? messagesFrench : undefined;\n\n const { className } = props;\n\n return (\n \n \n \n handleNavigate(slotInfo.start, currentView)}\n dayPropGetter={date => {\n if (\n [WEEK, MONTH].includes(currentView) &&\n moment(date)\n .startOf('day')\n .isSame(moment(currentDate).startOf('day'))\n ) {\n return { className: 'selected' };\n }\n return {};\n }}\n eventPropGetter={(event, start, end, isSelected) => {\n if (event.color) {\n return { style: { backgroundColor: event.color } };\n }\n return {};\n }}\n />\n \n \n
\n );\n};\n\nFasterAgenda.propTypes = {\n events: arrayOf(object),\n};\n\nexport default FasterAgenda;\n","import React, { useEffect, useState } from 'react';\nimport moment from 'moment';\nimport _ from 'lodash';\n\nimport Utils from 'core/utils/utils';\nimport { getDateFormatted } from 'core/utils/date';\nimport { useForm } from 'core/hooks/useForm';\nimport { history } from 'config/store';\n\nimport maskRowToEvent from './helpers/maskRowToEvent';\nimport FasterAgenda from './FasterAgenda';\nimport {\n formatView,\n supportedViews,\n computeDateRange,\n} from './helpers/initializeAgendaCriteria';\n\nconst FasterAgendaContainer = ({\n maskStructure,\n maskRows,\n dataLoading,\n area,\n module,\n updateCriteriaFunc,\n ...props\n}) => {\n const { calendarStart, calendarEnd, view } = maskStructure;\n const currentView = formatView(view);\n\n const [selectedDate, setSelectedDate] = useState(\n getDateFormatted(new Date())\n );\n const [calendarProps, , setCalendarProp] = useForm({\n agendaFieldKeyFrom: calendarStart,\n agendaFieldKeyTo: calendarEnd,\n events: [],\n color: null,\n views: _.values(supportedViews),\n currentView,\n currentDate: new Date(),\n dateRange: computeDateRange(new Date(), currentView),\n });\n\n useEffect(() => {\n if (maskStructure && maskRows) {\n setCalendarProp(\n 'events',\n _.map(maskRows, mr => maskRowToEvent(maskStructure, mr))\n );\n }\n }, [maskStructure, maskRows, setCalendarProp]);\n\n const handleSetDateRange = (date, view) => {\n const {\n currentDate,\n currentView,\n agendaFieldKeyFrom,\n agendaFieldKeyTo,\n } = calendarProps;\n\n // update date input value\n setSelectedDate(getDateFormatted(date));\n\n // determine whether view bounds have changed\n const { dateRange: oldDateRange } = computeDateRange(\n currentDate,\n currentView\n );\n const { startDate, endDate, dateRange } = computeDateRange(date, view);\n\n if (oldDateRange !== dateRange && agendaFieldKeyFrom && agendaFieldKeyTo) {\n // update state\n setCalendarProp('dateRange', { startDate, endDate });\n\n // trigger callback to update table query\n updateCriteriaFunc([\n { key: agendaFieldKeyFrom, value: dateRange },\n { key: agendaFieldKeyTo, value: dateRange },\n ]);\n }\n };\n\n const handleNavigate = (date, view) => {\n handleSetDateRange(date, view);\n setCalendarProp('currentDate', date);\n };\n\n const handleChangeView = view => {\n handleSetDateRange(calendarProps.currentDate, view);\n setCalendarProp('currentView', view);\n };\n\n const handleDoubleClick = event => {\n if (area || module) {\n const urlNav = Utils.buildUrlNav(area, module, event.key);\n history.push(urlNav);\n }\n };\n\n const handleChangeDate = newValue => {\n const { currentView } = calendarProps;\n const newDate = moment(newValue).toDate();\n\n setCalendarProp('currentDate', newDate);\n handleSetDateRange(newDate, currentView);\n };\n\n return (\n \n );\n};\n\nFasterAgendaContainer.propTypes = {};\n\nexport default FasterAgendaContainer;\n\nexport { maskRowToEvent };\n","export class GHRequestInfo {\n constructor({\n vehicle = 'car',\n weighting = 'fastest',\n algorithm,\n locale = 'en_US',\n pathDetails,\n pointHints,\n } = {}) {\n this.vehicle = vehicle;\n this.weighting = weighting;\n this.algorithm = algorithm;\n this.locale = locale;\n this.pathDetails = pathDetails;\n this.pointHints = pointHints;\n }\n}\n\nexport class GHResponseInfo {\n constructor({\n calcPoints = true,\n pointsEncoded = true,\n includeElevation = false,\n enableInstructions = true,\n } = {}) {\n this.calcPoints = calcPoints;\n this.pointsEncoded = pointsEncoded;\n this.includeElevation = includeElevation;\n this.enableInstructions = enableInstructions;\n }\n}\n","export class Matrix {\n constructor({\n fromPoints,\n toPoints,\n fromPointHints,\n toPointHints,\n outArrays = ['weights', 'times', 'distances'],\n vehicle = 'car',\n ghRequestInfo,\n ghResponseInfo,\n }) {\n this.fromPoints = fromPoints;\n this.toPoints = toPoints;\n this.fromPointHints = fromPointHints;\n this.toPointHints = toPointHints;\n this.outArrays = outArrays;\n this.vehicle = vehicle;\n this.ghRequestInfo = ghRequestInfo;\n this.ghResponseInfo = ghResponseInfo;\n }\n}\n\nexport class MatrixSymmetric {\n constructor({\n points,\n pointHints,\n outArrays = ['weights', 'times', 'distances'],\n vehicle = 'car',\n ghRequestInfo,\n ghResponseInfo,\n }) {\n this.points = points;\n this.pointHints = pointHints;\n this.outArrays = outArrays;\n this.vehicle = vehicle;\n this.ghRequestInfo = ghRequestInfo;\n this.ghResponseInfo = ghResponseInfo;\n }\n}\n","export class OptimizeModel {\n constructor({ points, noVehicle, ghRequestInfo, ghResponseInfo }) {\n this.points = points;\n this.noVehicle = noVehicle;\n this.ghRequestInfo = ghRequestInfo;\n this.ghResponseInfo = ghResponseInfo;\n }\n}\n","import axios from 'axios';\n\nimport { DISPATCH_BASE_URL } from 'core/utils/constant';\n\nimport {\n GHRequestInfo,\n GHResponseInfo,\n MatrixSymmetric,\n OptimizeModel,\n} from './models';\n\nexport const MAP_QUERY = {\n MATRIX_SYMMETRIC: 'matrix-sym',\n TSP: 'tsp',\n};\n\nconst getPayload = (data, query) => {\n const { points, noVehicle } = data;\n\n const ghRequestInfo = new GHRequestInfo();\n const ghResponseInfo = new GHResponseInfo();\n\n if (query === MAP_QUERY.MATRIX_SYMMETRIC)\n return new MatrixSymmetric({\n points,\n ghRequestInfo,\n ghResponseInfo,\n });\n else\n return new OptimizeModel({\n points,\n noVehicle,\n ghRequestInfo,\n ghResponseInfo,\n });\n};\n\nconst pageApi = {\n post: (data, query) => {\n try {\n return axios.post(\n `${DISPATCH_BASE_URL}/${query}`,\n getPayload(data, query)\n );\n } catch (e) {\n console.error(e);\n }\n },\n};\n\nexport default pageApi;\n","const validateViewport = viewport => {\n let isValid = false;\n\n if (viewport) {\n const { center, zoom } = viewport;\n\n if (\n center &&\n Array.isArray(center) &&\n center.length === 2 &&\n Number.isFinite(center[0]) &&\n Number.isFinite(center[1]) &&\n zoom &&\n Number.isFinite(zoom)\n ) {\n isValid = true;\n }\n }\n\n return isValid;\n};\n\nexport default validateViewport;\n","import L from 'leaflet';\n\nconst markerHtmlStyles = color => `\n background-color: ${color};\n width: 1.4rem;\n height: 1.4rem;\n display: block;\n left: -0.7rem;\n top: -1.72rem;\n position: relative;\n border-radius: 3rem 3rem 0;\n transform: rotate(45deg);\n border: 3px solid #FFFFFF;\n box-shadow: 1px 1px 4px 1px rgba(0, 0, 0, 0.5);\n`;\n\nconst getMarkerIcon = color =>\n L.divIcon({\n className: 'my-custom-pin',\n iconAnchor: [0, 0],\n labelAnchor: [0, 0],\n tooltipAnchor: [0, -9.8],\n popupAnchor: [0, -19.6],\n html: ` `,\n });\n\nexport default getMarkerIcon;\n","import React, { useRef, useEffect } from 'react';\nimport { Polyline } from 'react-leaflet';\nimport L from 'leaflet';\nimport 'leaflet-polylinedecorator';\n\n// TODO: Check using of useMap after remove mapRef\nconst PolylineDecorator = props => {\n const { patterns, mapRef } = props;\n\n const polyRef = useRef();\n\n const patternArrowDefault = [\n {\n offset: 10,\n endOffset: 10,\n repeat: 100,\n symbol: L.Symbol.arrowHead({\n polygon: true,\n headAngle: 45,\n pixelSize: 6,\n pathOptions: {},\n }),\n },\n ];\n\n useEffect(() => {\n const polyline = polyRef.current.leafletElement; //get native Leaflet polyline\n\n L.polylineDecorator(polyline, {\n patterns: patterns || patternArrowDefault,\n }).addTo(mapRef.current.leafletElement);\n }, [patternArrowDefault, mapRef, patterns]);\n\n return ;\n};\n\nexport default PolylineDecorator;\n","import { useMapEvent } from 'react-leaflet';\n\nconst DblClickComponent = () => {\n const map = useMapEvent('dblclick', e => {\n const zoom = map.getZoom();\n map.setView(e.latlng, zoom + 2);\n });\n\n return null;\n};\n\nconst RightClickComponent = () => {\n const map = useMapEvent('contextmenu', () => {\n const zoom = map.getZoom();\n map.setZoom(zoom - 2);\n });\n\n return null;\n};\n\nexport { DblClickComponent, RightClickComponent };\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n MapContainer,\n LayerGroup,\n Marker,\n TileLayer,\n Popup,\n Tooltip,\n} from 'react-leaflet';\nimport { Divider } from 'semantic-ui-react';\nimport 'leaflet/dist/leaflet.css';\nimport 'leaflet-polylinedecorator';\nimport 'leaflet-routing-machine';\nimport 'leaflet-control-geocoder';\nimport 'lrm-graphhopper';\nimport styled from 'styled-components';\nimport _ from 'lodash';\n\nimport { ButtonLink } from 'components';\n\nimport validateViewport from './helpers/validateViewport';\nimport getMarkerIcon from './helpers/getMarkerIcon';\nimport PolylineDecorator from './components/PolylineDecorator';\nimport {\n DblClickComponent,\n RightClickComponent,\n} from './components/ClickComponents';\n\nconst DEFAULT_VIEWPORT = {\n center: [28, 4],\n zoom: 2,\n};\n\nconst COLORS = ['black', 'red', 'blue', 'yellow', 'green'];\n\nconst StyledMapContainer = styled(MapContainer)`\n width: 100%;\n height: 550px;\n`;\n\nconst FasterMap = ({\n mapViewport,\n markers,\n locationsOptimized,\n addMarker,\n handleOpenDocument,\n}) => {\n const [viewport, setViewport] = useState(\n validateViewport(mapViewport) ? mapViewport : DEFAULT_VIEWPORT\n );\n\n const onViewportChanged = newViewport => {\n setViewport(newViewport);\n };\n\n const { t } = useTranslation();\n const openText = t('common|Open');\n const openIANTText = t('common|Open in new tab');\n\n return (\n \n \n \n \n \n {markers.map((m, i) => {\n const [key, lat, lng, tooltip, color] = m;\n const position = [lng, lat];\n const icon = getMarkerIcon(color);\n\n return (\n \n \n handleOpenDocument(key)}\n />\n \n handleOpenDocument(key, true)}\n />\n \n \n {_.map(tooltip.split('\\n'), (t, k) => (\n {t}
\n ))}\n \n \n );\n })}\n {locationsOptimized &&\n _.map(locationsOptimized, (p, i) => (\n \n ))}\n \n \n );\n};\n\nexport default FasterMap;\n","export const MAP_DATA = {\n MARKERS_DATA: 'markersData',\n MARKER_INDEX: 'markerIndex',\n LOCATIONS_OPTIMIZED: 'locationsOptimized',\n IS_ERROR: 'isError',\n IS_MAP_NEW_WINDOW: 'isMapNewWindow',\n};\n\nconst { MARKERS_DATA, MARKER_INDEX, LOCATIONS_OPTIMIZED, IS_ERROR } = MAP_DATA;\n\nexport const keepStorageMapState = form => {\n const { markersData, markerIndex, locationsOptimized, isError } = form;\n\n // Pass current state into localStorage\n localStorage.setItem(MARKERS_DATA, JSON.stringify(markersData));\n localStorage.setItem(MARKER_INDEX, markerIndex);\n localStorage.setItem(LOCATIONS_OPTIMIZED, JSON.stringify(locationsOptimized));\n localStorage.setItem(IS_ERROR, isError);\n};\n\nexport const clearStorageMapState = () => {\n localStorage.removeItem(MARKERS_DATA);\n localStorage.removeItem(MARKER_INDEX);\n localStorage.removeItem(LOCATIONS_OPTIMIZED);\n localStorage.removeItem(IS_ERROR);\n};\n\nexport const parseStorageMapState = handleSetKey => {\n const storageMarkersData = JSON.parse(localStorage.getItem(MARKERS_DATA));\n const storageMarkerIndex = JSON.parse(localStorage.getItem(MARKER_INDEX));\n const storageLocationsOptimized = JSON.parse(\n localStorage.getItem(LOCATIONS_OPTIMIZED)\n );\n const storageIsError = localStorage.getItem(IS_ERROR);\n\n handleSetKey(MARKER_INDEX, storageMarkerIndex);\n handleSetKey(MARKERS_DATA, storageMarkersData);\n handleSetKey(LOCATIONS_OPTIMIZED, storageLocationsOptimized);\n handleSetKey(IS_ERROR, storageIsError === 'true');\n};\n\nexport const parseAndClearMapStorage = handleSetKey => {\n if (localStorage.getItem(MARKERS_DATA) !== null) {\n parseStorageMapState(handleSetKey);\n clearStorageMapState();\n }\n};\n","import getMaskRowText from '../../mask/helpers/getMaskRowText';\n\n//// compute both start and end of event\n//const getCoordinatesXY = (data, { defaultX, defaultY }) => {\n// const coordinatesXY = {\n// coordinateX: data.CoordinateX,\n// coordinateY: data.CoordinateY,\n// };\n\n// if (!coordinatesXY.coordinateX && coordinatesXY.coordinateY) {\n// coordinatesXY.coordinateX = defaultX;\n// } else if (coordinatesXY.coordinateX && !coordinatesXY.coordinateY) {\n// coordinatesXY.coordinateY = defaultY;\n// }\n\n// // data is missing -> fallback to default cooordinate of map\n// if (!coordinatesXY.coordinateX || !coordinatesXY.coordinateY) {\n// coordinatesXY.coordinateX = defaultX;\n// coordinatesXY.coordinateX = defaultY;\n// }\n\n// return coordinatesXY;\n//};\n\n// convert mask row to map marker\nconst maskRowToMarker = (maskStructure, maskRow) => {\n const { coordinateX: filedKeyLong, coordinateY: fieldKeyLat } = maskStructure;\n const { key, data: rowData, color } = maskRow;\n\n // get coordinates X and Y\n const coordinateX = rowData[filedKeyLong];\n const coordinateY = rowData[fieldKeyLat];\n\n // define tooltip\n const tooltip = getMaskRowText(maskStructure, rowData);\n\n return [key, coordinateX, coordinateY, tooltip, color];\n};\n\nexport default maskRowToMarker;\n","import React, { useEffect, useCallback } from 'react';\nimport { connect } from 'react-redux';\nimport { withRouter } from 'react-router-dom';\nimport styled from 'styled-components';\nimport _ from 'lodash';\n\nimport {\n getIsMapNewWindow,\n DispatchCreators,\n} from 'core/dispatch/dispatchReducer';\nimport Utils from 'core/utils/utils';\nimport { useForm } from 'core/hooks/useForm';\nimport { ThemedButton, ThemedSegment } from 'components';\nimport { DISPATCH_PATHNAME } from 'core/utils/constant';\nimport mapApi, { MAP_QUERY } from 'api/map/mapApi';\n\nimport FasterMap from './FasterMap';\nimport {\n MAP_DATA,\n clearStorageMapState,\n keepStorageMapState,\n parseAndClearMapStorage,\n} from './helpers/storage';\nimport maskRowToMarker from './helpers/maskRowToMarker';\n\nconst { IS_MAP_NEW_WINDOW } = MAP_DATA;\n\nconst StyledDiv = styled.div`\n ${({ hidden }) => `\n margin: -1em -1em 0;\n ${hidden ? `display: none;` : ''}\n `}\n`;\n\nconst FasterMapContainer = ({\n // 3rd-party props\n className,\n // mapProps data\n maskStructure,\n maskRows,\n area,\n module,\n updateCriteriaFunc,\n // map props\n hidden,\n withToolbar = false,\n history,\n location: { pathname },\n isMapNewWindow,\n closeMapNewWindow,\n openMapNewWindow,\n}) => {\n const { viewport } = maskStructure || {};\n\n const [mapProps, , setMapProp] = useForm({\n mapViewport: viewport,\n markers: [],\n markerIndex: 0,\n locationsOptimized: [],\n isError: false,\n isMapped: false,\n toggleMapContent: '',\n handleToggleMap: null,\n });\n\n useEffect(() => {\n if (maskStructure && maskRows) {\n setMapProp(\n 'markers',\n _.map(maskRows, mr => maskRowToMarker(maskStructure, mr))\n );\n }\n }, [maskStructure, maskRows, setMapProp]);\n\n const lsIsMapNewWindow = localStorage.getItem(IS_MAP_NEW_WINDOW);\n const isDispatchPathname = pathname === DISPATCH_PATHNAME;\n\n useEffect(() => {\n // Detect changes of isNewMapWindow\n window.addEventListener(\n 'storage',\n () => {\n if (lsIsMapNewWindow === null) {\n closeMapNewWindow();\n\n if (isDispatchPathname) {\n window.close();\n } else {\n parseAndClearMapStorage(setMapProp);\n }\n }\n },\n false\n );\n\n // Close Map when close tab\n window.addEventListener('beforeunload', () => {\n if (lsIsMapNewWindow) {\n keepStorageMapState();\n }\n closeMapNewWindow();\n });\n }, [closeMapNewWindow, setMapProp, lsIsMapNewWindow, isDispatchPathname]);\n\n const handleOpenNewMap = useCallback(() => {\n keepStorageMapState(mapProps);\n localStorage.setItem(IS_MAP_NEW_WINDOW, true);\n openMapNewWindow();\n window.open(DISPATCH_PATHNAME, '_blank');\n }, [mapProps, openMapNewWindow]);\n\n const handleCloseMap = useCallback(() => {\n keepStorageMapState(mapProps);\n localStorage.removeItem(IS_MAP_NEW_WINDOW);\n closeMapNewWindow();\n\n if (isDispatchPathname) {\n window.close();\n }\n }, [closeMapNewWindow, mapProps, isDispatchPathname]);\n\n useEffect(() => {\n if (!lsIsMapNewWindow) {\n // Must enter from dispatch page\n if (isDispatchPathname) {\n history.push('/dispatch');\n }\n\n setMapProp('toggleMapContent', 'Open');\n setMapProp('handleToggleMap', handleOpenNewMap);\n } else {\n // Keep current state\n parseAndClearMapStorage();\n\n setMapProp('toggleMapContent', 'Close');\n setMapProp('handleToggleMap', handleCloseMap);\n }\n }, [\n setMapProp,\n history,\n lsIsMapNewWindow,\n isDispatchPathname,\n // TODO: Need to check re-render problem when pass object state as useEffect dependencies\n // handleOpenNewMap,\n // handleCloseMap,\n ]);\n\n const addMarker = e => {\n setMapProp('markerIndex', mapProps.markerIndex + 1);\n setMapProp('markers', [\n ...mapProps.markers,\n [e.latlng.lat, e.latlng.lng, mapProps.markerIndex],\n ]);\n };\n\n const onOptimize = async e => {\n const { markers } = mapProps;\n\n let points = [];\n markers.forEach(m => {\n points.push(`${m[0]},${m[1]}`);\n });\n\n const data = await mapApi({ points }, MAP_QUERY.MATRIX_SYMMETRIC);\n\n if (data !== undefined) {\n // route optimized\n if (_.isEmpty(data)) {\n setMapProp('isError', true);\n } else {\n const tmp = [];\n for (let i = 0; i < data.length; i++) {\n const points = data[i].pointsOrdered;\n const path = Utils.decodePath(data[i].paths[0].points, false);\n const vehicle = data[i].vehicle;\n tmp.push({ points, path, vehicle });\n }\n\n setMapProp('isError', false);\n setMapProp('locationsOptimized', tmp);\n }\n }\n };\n\n // TODO: Check using of useMap after remove mapRef\n const clearMap = map => {\n for (const i in map._layers) {\n if (map._layers[i]._path !== undefined) {\n try {\n map.removeLayer(map._layers[i]);\n } catch (e) {\n console.log('problem with ' + e + map._layers[i]);\n }\n }\n }\n };\n\n const onReset = () => {\n setMapProp('markers', []);\n setMapProp('markerIndex', 0);\n setMapProp('locationsOptimized', null);\n clearMap();\n clearStorageMapState();\n };\n\n const handleOpenDocument = (key, newTab) => {\n if (area || module) {\n const urlNav = Utils.buildUrlNav(area, module, key);\n\n if (newTab) {\n window.open(urlNav, '_blank');\n } else {\n history.push(urlNav);\n }\n }\n };\n\n const {\n mapViewport,\n markers,\n locationsOptimized,\n isError,\n toggleMapContent,\n handleToggleMap,\n } = mapProps;\n\n return (\n \n {withToolbar && (\n \n \n \n handleToggleMap()}\n />\n \n )}\n \n {isError && Error }\n \n );\n};\n\nconst mapStateToProps = state => ({\n isMapNewWindow: getIsMapNewWindow(state),\n});\n\nconst mapDispatchToProps = dispatch => ({\n closeMapNewWindow: () => dispatch(DispatchCreators.closeMapNewWindow()),\n openMapNewWindow: () => dispatch(DispatchCreators.openMapNewWindow()),\n});\n\nexport default connect(\n mapStateToProps,\n mapDispatchToProps\n)(withRouter(FasterMapContainer));\n","import React from 'react';\nimport { Segment } from 'semantic-ui-react';\nimport styled from 'styled-components';\nimport _ from 'lodash';\n\nconst LeftSegment = styled(({ color, ...props }) => )`\n ${({\n color,\n theme: {\n color: { tableBg, tableFg, tableBorderColor },\n },\n }) => `\n .ui.horizontal.segments > &.segment:first-child,\n &.ui.yellow.segment:not(.inverted) {\n border-top: none !important;\n border-left: ${`3px solid ${color}`};\n border-radius: 3px;\n\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n }\n\n .ui.horizontal.segments > &.segment {\n cursor: pointer;\n background-color: ${tableBg};\n color: ${tableFg};\n border-color: ${tableBorderColor};\n }\n\n .ui.accordion .title:not(.ui) {\n color: ${tableFg};\n }\n\n & p {\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n margin: 0;\n }\n\n & p:first-child {\n font-weight: bolder;\n }\n `}\n`;\n\nconst CardLeftSegment = ({ title, color, handleEdit }) => {\n //const [active, setActive] = useState(false);\n\n //const handleSetActive = e => {\n // setActive(active => !active);\n //};\n\n return (\n \n {title &&\n _.map(title.split('\\n'), (st, index) => {st}
)}\n {/*\n \n \n View description\n \n {description} \n */}\n \n );\n};\n\nexport default CardLeftSegment;\n","import React from 'react';\nimport { Segment } from 'semantic-ui-react';\nimport styled from 'styled-components';\nimport CardLeftSegment from './CardLeftSegment';\n//import CardRightSegment from './CardRightSegment';\n\nconst SegmentGroup = styled(Segment.Group)`\n &&& {\n background-color: ${({ theme: { color } }) => color.tableBg};\n color: ${({ theme: { color } }) => color.tableFg};\n border-color: ${({ theme: { color } }) => color.tableBorderColor};\n }\n`;\n\nconst Card = ({ card, handleEdit }) => {\n const { key, title, color } = card;\n\n const handleClickEdit = () => {\n if (handleEdit) {\n handleEdit(key);\n }\n };\n\n return (\n \n \n {/* */}\n \n );\n};\n\nexport default Card;\n","export default [\n {\n title: 'Card Title 1',\n description: 'Card Description 1',\n },\n {\n title: 'Card Title 2',\n description: 'Card Description 2',\n },\n {\n title: 'Card Title 3',\n description: 'Card Description 3',\n },\n];\n","import React from 'react';\nimport { Grid } from 'semantic-ui-react';\nimport _ from 'lodash';\n\nimport { SpinnerSegment } from 'components';\n\nimport Card from './components/Card';\nimport demoCardsList from './helpers/demoCardsList';\n\nimport styled from 'styled-components';\n\nconst GridRow = styled(Grid.Row)`\n &&.row {\n padding-top: 0;\n }\n`;\n\nconst FasterCards = ({\n cardsProps,\n dataLoading,\n handleEdit,\n admin,\n area,\n module,\n //currentPage,\n //totalPage,\n //totalRow,\n ...props\n}) => {\n let cards = demoCardsList;\n\n if (cardsProps) {\n cards = cardsProps.cards;\n }\n\n const { className } = props;\n\n return (\n \n {/*cardsProps && (\n
\n )*/}\n
\n \n \n {!dataLoading && cards ? (\n _.map(cards, ({ key, ...card }, index) => (\n \n ))\n ) : (\n \n )}\n \n \n \n {/*cardsProps && (\n
\n )*/}\n
\n );\n};\n\nexport default FasterCards;\n","import getMaskRowText from '../../mask/helpers/getMaskRowText';\n\nconst formToCard = (maskStructure, maskRow) => {\n const { key, data: rowData, color } = maskRow;\n\n // define title\n const title = getMaskRowText(maskStructure, rowData);\n\n return {\n title,\n key,\n color,\n row: maskRow,\n };\n};\n\nexport default formToCard;\n","import React, { useEffect } from 'react';\nimport _ from 'lodash';\n\nimport { useForm } from 'core/hooks/useForm';\nimport Utils from 'core/utils/utils';\nimport { history } from 'config/store';\n\nimport FasterCards from './FasterCards';\nimport formToCard from './helpers/formToCard';\n// import getTableMaskData from '../tables/helpers/getTableMaskData';\n\nconst FasterCardsContainer = ({\n maskStructure,\n maskRows,\n area,\n module,\n updateCriteriaFunc,\n dataType,\n dataKey,\n ...props\n}) => {\n // const cardsListData = getTableMaskData(table);\n const admin = dataType && dataKey ? true : false;\n\n const [cardsProps, , setCardsProp] = useForm({\n cards: null,\n });\n\n useEffect(() => {\n if (maskStructure && maskRows) {\n setCardsProp(\n 'cards',\n _.map(maskRows, mr => formToCard(maskStructure, mr))\n );\n }\n }, [maskStructure, maskRows, setCardsProp]);\n\n const handleEdit = key => {\n if (area || module) {\n const urlNav = Utils.buildUrlNav(area, module, key);\n history.push(urlNav);\n }\n };\n\n return (\n \n );\n};\n\nexport default FasterCardsContainer;\n\nexport { formToCard, FasterCards };\n","import _ from 'lodash';\nimport { getEventStartAndEnd } from '../../agenda/helpers/maskRowToEvent';\n\nimport getMaskRowText from '../../mask/helpers/getMaskRowText';\n\nconst maskRowsToTimelineData = (maskStructure, maskRows) => {\n const { resource, view, event } = maskStructure;\n const { start: eventStart, length: eventLength, end: eventEnd } = event;\n\n const resources = _.uniq(_.map(maskRows, mr => mr.data[resource]));\n\n const data = _.map(resources, r => ({\n name: r,\n view,\n labels: _.map(\n _.filter(maskRows, mr => mr.data[resource] === r),\n maskRow => {\n const { key, data: rowData, color, lastEdit } = maskRow;\n const { start, end, length } = getEventStartAndEnd(rowData, lastEdit, {\n eventStart,\n eventLength,\n eventEnd,\n });\n\n // define text\n const text = getMaskRowText(maskStructure, rowData);\n\n return {\n key,\n text,\n color,\n start,\n length,\n end,\n };\n }\n ),\n }));\n\n return data;\n};\n\nexport default maskRowsToTimelineData;\n","import React from 'react';\nimport { Grid } from 'semantic-ui-react';\n\nimport CalendarPicker from '../../input/calendar/CalendarPicker';\n\nconst Toolbar = ({\n // props\n selectedDate,\n // func\n handleChangeDate,\n}) => {\n const onChangeDate = (e, { value }) => {\n handleChangeDate(value);\n };\n\n return (\n \n \n \n \n \n \n \n );\n};\n\nexport default Toolbar;\n","import React from 'react';\nimport styled from 'styled-components';\nimport { Grid, GridColumn } from 'semantic-ui-react';\n\n//import { ThemedButton, ThemedLabel } from 'components';\n\nconst HeaderCellMiddle = styled.div`\n display: flex;\n align-items: center;\n`;\n\nconst RoundName = styled.span`\n text-transform: uppercase;\n margin-right: 5px;\n`;\n\n//const DriverName = styled.span`\n// font-weight: bold;\n\n// &:after {\n// content: '|';\n// font-weight: normal;\n// margin: 0 5px;\n// }\n//`;\n\n//const Volume = styled.span`\n// color: #999;\n//`;\n\nconst RoundInfo = ({ data: { name } }) => {\n return (\n \n \n \n {name} \n \n \n \n );\n};\n\nexport default RoundInfo;\n","import React from 'react';\nimport styled from 'styled-components';\n\nimport { ThemedLabel } from 'components';\n\nconst StyledLabel = styled(({ empty, left, width, ...props }) => (\n \n))`\n &&&&& {\n ${({ empty, left, width }) => `\n cursor: pointer;\n position: absolute;\n top: calc(50% - ${empty ? '9px' : '14.83px'});\n min-width: 5px;\n margin: 0;\n border: 2px solid white;\n color: white;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n\n left: ${left}%;\n width: ${width}%;\n `}\n }\n`;\n\nconst CompactLabel = styled(StyledLabel)`\n &&&&& {\n padding-left: 0;\n padding-right: 0;\n text-indent: 200%;\n }\n`;\n\nconst EventLabel = ({ compact, ...props }) => {\n return compact ? : ;\n};\n\nexport default EventLabel;\n","import React, { useRef, Fragment } from 'react';\nimport { object } from 'prop-types';\nimport { Table, Popup } from 'semantic-ui-react';\nimport styled from 'styled-components';\nimport _ from 'lodash';\n\nimport Utils from 'core/utils/utils';\nimport { ContextMenuTrigger, ThemedPopup } from 'components';\n\nimport EventLabel from './components/EventLabel';\nimport { getDateTimeFormatted } from '../../../../../../core/utils/date';\n\nconst ProgressCell = styled(Table.Cell)`\n &&& {\n position: relative;\n padding-left: 0;\n padding-right: 0;\n }\n`;\n\nconst StyledProgress = styled.div`\n &&& {\n margin: 0;\n height: 5px;\n width: 100%;\n background-color: ${({ theme: { color } }) => color.timeline};\n }\n`;\n\nconst StyledLabelDiv = styled.div`\n position: absolute;\n top: 0;\n margin: 0;\n height: 100%;\n width: 100%;\n`;\n\nconst StyledPopupContent = styled(ThemedPopup.Content)`\n &&&&&&&& {\n font-size: 12px;\n line-height: 1.4285em;\n }\n`;\n\nconst stringToSecond = time =>\n time\n ? time.split(':').reduce((acc, time) => (60 * acc + +time) * 1000)\n : undefined;\n\nconst dateToTime = jsDate => {\n const dateString = jsDate ? getDateTimeFormatted(jsDate) : undefined;\n return jsDate ? dateString.split(' ')[1] : undefined;\n};\n\nconst dateToSecond = jsDate => {\n const time = dateToTime(jsDate);\n return stringToSecond(time);\n};\n\nconst TimelineProgress = ({ view, data, handleDoubleClick }) => {\n const progressRef = useRef(null);\n\n const { start, end } = view;\n const minHour = start - 1;\n const maxHour = end;\n const timelineStart = stringToSecond(`${Utils.toHourString(minHour)}:30`);\n const timelineEnd = stringToSecond(`${Utils.toHourString(maxHour)}:30`);\n\n const getLabelProps = event => {\n let offset = 0,\n left = 0,\n width = 0,\n compact = true;\n const { start, length, end } = event;\n\n if (progressRef.current) {\n const totalWidth = progressRef.current.offsetWidth;\n\n const timeStartVal = dateToSecond(start);\n const timeEndVal = dateToSecond(end);\n const timeLengthVal = dateToSecond(length);\n\n const widthTime = timelineEnd - timelineStart;\n\n if (totalWidth) {\n offset = timeStartVal - timelineStart;\n left = (offset / widthTime) * 100;\n width =\n ((timeLengthVal || timeEndVal - timeStartVal) / widthTime) * 100;\n compact = (width / 100) * totalWidth < 35 ? true : false;\n }\n }\n\n return {\n left,\n width,\n compact,\n };\n };\n\n const { labels } = data;\n\n return (\n \n \n \n {_.map(labels, lbl => {\n return (\n {\n e.stopPropagation();\n handleDoubleClick(lbl);\n }}\n />\n ),\n }}\n >\n \n {`${dateToTime(lbl.start)} - ${dateToTime(lbl.end)}`}\n {_.map(lbl.text.split('\\n'), (line, index) => (\n \n \n {line}\n \n ))}\n \n \n );\n })}\n \n \n );\n};\n\nTimelineProgress.propTypes = {\n data: object.isRequired,\n};\n\nexport default TimelineProgress;\n","import React from 'react';\n\nimport Utils from 'core/utils/utils';\nimport { history } from 'config/store';\n\nimport TimelineProgress from './TimelineProgress';\n\nconst TimelineProgressContainer = ({ t, area, module, data, ...props }) => {\n const handleDoubleClick = event => {\n if (area || module) {\n const urlNav = Utils.buildUrlNav(area, module, event.key);\n history.push(urlNav);\n }\n };\n\n return (\n \n );\n};\n\nexport default TimelineProgressContainer;\n","import React from 'react';\nimport { Loader } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nimport { ThemedSegment } from '..';\n\nconst StyledSegment = styled(ThemedSegment)`\n &&& {\n align-self: center;\n }\n\n .ui.segment &&& {\n // when wrapped in page body segment, align-self is not applied\n max-width: 76px;\n margin: auto;\n }\n`;\n\nconst SpinnerSegment = ({ padded, frosted, ...props }) => (\n \n \n \n);\n\nexport default SpinnerSegment;\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Table } from 'semantic-ui-react';\nimport _ from 'lodash';\n\nimport Utils from 'core/utils/utils';\nimport withSelections from 'core/utils/withSelections';\nimport {\n //Center,\n ThemedTable,\n //ThemedLabel,\n ContextMenuTrigger,\n //ThemedPagination,\n} from 'components';\n\nimport RoundInfo from './components/round-info/RoundInfo';\nimport TimelineProgress from './components/progress/timelineProgressContainer';\nimport { ThemedHeaderCellHeader } from '../../../theme/ThemedTable';\nimport { showSingleRow } from '../../../tables/components/TableRow';\nimport SpinnerSegment from '../../../segments/SpinnerSegment';\n\n//const HeaderCellMiddle = styled.div`\n// display: flex;\n// align-items: center;\n// justify-content: space-between;\n//`;\n\n//const Footer = styled.div`\n// display: grid;\n// grid-template-columns: 1fr 1fr 1fr;\n// align-items: center;\n//`;\n\nconst { Header, Row, Cell, Body } = Table;\n\nconst TimelineTable = withSelections(\n ({ dataLoading, view, data, activeItem, handleRowClick, ...props }) => {\n const { t } = useTranslation();\n const { start, end } = view || {};\n const timeStart =\n start && Number.isInteger(start) && start > 0 && start < 23 ? start : 9;\n const timeEnd =\n end && Number.isInteger(end) && end > 1 && end < 24 ? end : 19;\n\n const timeCells = [];\n\n for (let i = timeStart; i < timeEnd + 1; i++) {\n timeCells.push(\n {`${Utils.toHourString(i)}:00`} \n );\n }\n\n return (\n \n \n \n {/*\n \n handleSelectAll(data)}\n />\n \n */}\n \n {timeCells}\n
\n \n \n {dataLoading && (\n \n \n \n | \n \n )}\n {!dataLoading &&\n !(data && data.length > 0) &&\n showSingleRow(25, t('No records found'))}\n {!dataLoading &&\n data &&\n data.length > 0 &&\n _.map(data, d => (\n {\n handleRowClick(d.name);\n },\n }}\n callbackOnShow={() => handleRowClick(d.id)}\n >\n {/*\n handleSelect(d.id)}\n />\n | */}\n \n \n | \n \n {/* | */}\n \n ))}\n \n \n );\n }\n);\n\nexport default TimelineTable;\n","import React, { useState, useRef } from 'react';\nimport { connect } from 'react-redux';\n\nimport { ModalCreators, getModal } from 'core/modal/modalReducer';\nimport { DispatchCreators } from 'core/dispatch/dispatchReducer';\nimport TimelineTable from './TimelineTable';\nimport { Ref } from 'semantic-ui-react';\nimport useClickAwayListener from 'core/utils/useClickAwayListener';\n\nconst TimelineTableContainer = ({\n data,\n setRound,\n setTransport,\n openSidebar,\n ...props\n}) => {\n const timelineTableRef = useRef();\n\n const [activeItem, setActiveItem] = useState(undefined);\n\n const handleRowClick = key => {\n setActiveItem(key);\n };\n\n useClickAwayListener(timelineTableRef, activeItem, () => {\n handleRowClick(undefined);\n });\n\n return (\n [\n ] \n \n );\n};\n\nconst mapStateToProps = state => ({\n modal: getModal(state),\n});\n\nconst mapDispatchToProps = dispatch => ({\n openModal: (modalType, options) =>\n dispatch(ModalCreators.openModal(modalType, options)),\n closeModal: () => dispatch(ModalCreators.closeModal()),\n setRound: round => dispatch(DispatchCreators.setRound(round)),\n setTransport: transport => dispatch(DispatchCreators.setTransport(transport)),\n openSidebar: () => dispatch(DispatchCreators.openSidebar()),\n});\n\nexport default connect(\n mapStateToProps,\n mapDispatchToProps\n)(TimelineTableContainer);\n","import React from 'react';\n\nimport Toolbar from './components/Toolbar';\nimport TimelineTable from './components/table/timelineTableContainer';\n\nconst Timeline = ({\n className,\n tlProps: { selectedDate, timeline },\n handleChangeDate,\n ...props\n}) => {\n return (\n \n \n \n
\n );\n};\n\nexport default Timeline;\n","import React, { useEffect, useRef } from 'react';\n\n//import Utils from 'core/utils/utils';\nimport { getDateFormatted } from 'core/utils/date';\nimport { useForm } from 'core/hooks/useForm';\n\nimport maskRowsToTimelineData from './helpers/maskRowsToTimelineData';\nimport Timeline from './Timeline';\nimport { computeDayDateRange } from '../agenda/helpers/initializeAgendaCriteria';\n\nconst TimelineContainer = ({\n maskStructure,\n maskRows,\n updateCriteriaFunc,\n ...props\n}) => {\n const defaultDate = useRef(getDateFormatted(new Date()));\n const {\n view,\n //event: { start: eventStart, end: eventEnd }, // todo unused var\n } = maskStructure;\n const [tlProps, , setTlProp] = useForm({\n selectedDate: defaultDate.current,\n timeline: [],\n });\n\n useEffect(() => {\n if (maskStructure && maskRows) {\n setTlProp('timeline', maskRowsToTimelineData(maskStructure, maskRows));\n }\n }, [maskStructure, maskRows, setTlProp]);\n\n const handleDateChange = newDate => {\n const { selectedDate: oldDate } = tlProps;\n const { date /*, start, end*/ } = view;\n\n // set state\n setTlProp('selectedDate', newDate);\n\n // if date has changed, update query\n if (oldDate !== newDate) {\n //const range = `${Utils.toHourString(start)}:00|${Utils.toHourString(\n // // todo unused var\n // end\n //)}:00`;\n const { dateRange } = computeDayDateRange(newDate);\n\n updateCriteriaFunc([\n { key: date, value: dateRange },\n //{ key: eventStart, value: range },\n //{ key: eventEnd, value: range },\n ]);\n }\n };\n\n return (\n \n );\n};\n\nTimelineContainer.propTypes = {};\n\nexport default TimelineContainer;\n","import React from 'react';\n\nimport { CONTENT_TYPE } from 'core/utils/constant';\n\nimport MaskedComponent from './MaskedComponent';\nimport getMaskRows from './helpers/getMaskRows';\nimport getTableMaskData from '../tables/helpers/getTableMaskData';\nimport FasterAgenda from '../agenda/fasterAgendaContainer';\nimport FasterMap from '../map/fasterMapContainer';\nimport FasterCards from '../cards/fasterCardsContainer';\nimport Timeline from '../timeline/timelineContainer';\n\nconst { agenda, cards, map, timeline } = CONTENT_TYPE;\n\nconst maskByType = {\n [agenda]: FasterAgenda,\n [cards]: FasterCards,\n [map]: FasterMap,\n [timeline]: Timeline,\n};\n\nconst MaskContainer = ({ type, table, data, ...props }) => {\n const maskStructure = getTableMaskData(table);\n const maskRows = getMaskRows(data, table.columns);\n //const { currentPage, totalPage, totalRow } = data;\n\n const maskProps = {\n ...props,\n maskStructure,\n maskRows,\n component: maskByType[type],\n //currentPage,\n //totalPage,\n //totalRow,\n };\n\n return ;\n};\n\nexport default MaskContainer;\n","import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { withRouter } from 'react-router-dom';\nimport { connect } from 'react-redux';\nimport { useTranslation } from 'react-i18next';\nimport { Divider, Dropdown, Icon } from 'semantic-ui-react';\nimport styled from 'styled-components';\nimport _ from 'lodash';\n\nimport Utils from 'core/utils/utils';\nimport { CONTENT_TYPE, DOWNLOAD_TYPE } from 'core/utils/constant';\nimport { getCurrentUser } from 'core/auth/authReducer';\nimport { useApi } from 'api/useApi';\nimport { useHub } from 'api/useHub';\nimport tableDataApi from 'api/tableData/tableDataApi';\nimport exportApi from 'api/export/exportApi';\nimport tableHub from 'api/table/tableHub';\nimport { SegmentMenu } from 'components';\n\nimport Table from './Table';\nimport { filterTableColumns } from '../helpers/filterTableColumns';\nimport {\n initializeTableCriteria,\n setCriterion,\n} from '../helpers/tableCriteriaHelpers';\nimport Mask from '../../mask/maskContainer';\nimport MaskedComponent from '../../mask/MaskedComponent';\n\nconst { agenda, cards, map, timeline } = CONTENT_TYPE;\nconst { csv, xlsx } = DOWNLOAD_TYPE;\n\nconst StyledDivider = styled(Divider)`\n &&& {\n margin-top: 0;\n margin-bottom: 0.5rem;\n border: none !important;\n }\n`;\n\nconst TableContainer = props => {\n const { t } = useTranslation();\n const {\n tableKey,\n table,\n token,\n ids,\n filters,\n dataType,\n dataKey,\n documentID,\n activeItem,\n setActiveItem,\n mask,\n } = props;\n\n // state\n const canRefetch = useRef(false);\n const [criteria] = useState(() => ({\n // do not replace by useRef https://github.com/facebook/react/issues/14490\n current: initializeTableCriteria(table, filters, mask),\n }));\n const [maskToggle, setMaskToggle] = useState(mask ? true : false);\n const [loading, setLoading] = useState(true);\n const [disableExportBtn, setDisableExportBtn] = useState(false);\n const [activeColumn, setActiveColumn] = useState(table.sortByColumnKey);\n const [direction, setDirection] = useState(\n table.ascendingSort ? 'ascending' : 'descending'\n );\n const [query, setQuery] = useState(\n tableDataApi.buildQuery(tableKey, table.type, criteria.current)\n );\n const [args, setArgs] = useState([\n query,\n ids,\n table,\n dataType,\n dataKey,\n documentID,\n ]);\n\n // hooks\n const reFetch = useCallback(() => {\n setQuery(query);\n setArgs([query, ids, table, dataType, dataKey, documentID]);\n }, [query, ids, table, dataType, dataKey, documentID]);\n\n useHub(tableHub, token, reFetch);\n\n const [fetchedData, pendingData] = useApi(tableDataApi.getMany, args, {\n tableData: undefined,\n });\n\n useEffect(() => {\n if (canRefetch.current) {\n reFetch();\n } else {\n canRefetch.current = true;\n }\n }, [reFetch]);\n\n useEffect(() => {\n if (pendingData) {\n setLoading(true);\n } else {\n setLoading(false);\n }\n }, [fetchedData, pendingData]);\n\n const handleRowClick = (item, actionable) => {\n setActiveItem([item, actionable]);\n };\n\n // trigger query\n const queryWithCriteria = useCallback(() => {\n setActiveItem([]);\n setQuery(tableDataApi.buildQuery(tableKey, table.type, criteria.current));\n setLoading(true);\n }, [tableKey, table, criteria, setActiveItem]);\n\n const handleExportData = async fileType => {\n setDisableExportBtn(true);\n\n const res = await exportApi.exportTo(\n fileType,\n tableKey,\n criteria.current,\n ids,\n documentID\n );\n\n if (res && res.fileUrl) {\n // open to save file\n Utils.openInNewTab(res.fileUrl);\n setDisableExportBtn(false);\n }\n };\n\n // update sorting\n const handleSort = clickedColumn => () => {\n // set sort direction\n const switchToDescending =\n activeColumn === clickedColumn && direction === 'ascending';\n const newDirection = switchToDescending ? 'descending' : 'ascending';\n setDirection(newDirection);\n\n // set sorted column\n criteria.current.orderByField = switchToDescending\n ? undefined\n : clickedColumn;\n criteria.current.orderByFieldDesc = switchToDescending\n ? clickedColumn\n : undefined;\n\n // set active column\n if (activeColumn !== clickedColumn) {\n setActiveColumn(clickedColumn);\n }\n\n // query\n queryWithCriteria();\n };\n\n // page change\n const handlePageChange = (e, { activePage }) => {\n // set page\n criteria.current.indexPage = activePage;\n // query\n queryWithCriteria();\n };\n\n // global search change\n const handleSearchAllChange = (e, column) => {\n // reset page\n criteria.current.indexPage = 1;\n // query\n criteria.current.searchAllByValue =\n column.value === '' ? undefined : column.value;\n queryWithCriteria();\n };\n\n // column filter change\n const handleSearchFieldChange = (e, column, preventSearch) => {\n // reset page\n criteria.current.indexPage = 1;\n\n // query\n if (!preventSearch) {\n setCriterion(criteria.current, column);\n queryWithCriteria();\n }\n };\n\n // mask filter change\n const handleUpdateCriteriaAndQuery = useCallback(\n criteriaObjects => {\n // update criteria\n _.forEach(criteriaObjects, criterion => {\n setCriterion(criteria.current, criterion);\n });\n\n // query\n queryWithCriteria();\n },\n [criteria, queryWithCriteria]\n );\n\n // hide or show mask or table\n const toggleMask = () => {\n setMaskToggle(!maskToggle);\n };\n\n const tableProp = filterTableColumns(table, mask);\n const dataProp = fetchedData.tableData;\n\n const iconByType = {\n [agenda]: 'calendar',\n [cards]: 'align justify',\n [map]: 'map',\n [timeline]: 'clock',\n };\n\n const textByType = {\n [agenda]: 'agenda',\n [cards]: 'cards',\n [map]: 'map',\n [timeline]: 'timeline',\n };\n\n const DropdownItems = () => (\n <>\n \n \n {t('common|Download')}\n \n handleExportData(csv)}>csv \n handleExportData(xlsx)}>xlsx \n >\n );\n\n const icon = maskToggle ? 'th' : iconByType[mask];\n const text = t(`See ${maskToggle ? 'table' : textByType[mask]}`);\n const onClick = toggleMask;\n const menuButtonProps = { icon, text, onClick };\n\n return (\n <>\n {mask && (\n \n )}\n \n \n {!dataType && (\n \n )}\n >\n );\n};\n\nconst mapStateToProps = state => {\n const { token /*, selectedFilters*/ } = getCurrentUser(state);\n\n return {\n token,\n //selectedFilters,\n };\n};\n\nexport default withRouter(\n connect(\n mapStateToProps,\n null\n )(TableContainer)\n);\n","import { useEffect, useRef } from 'react';\n\nexport function useHub(hub, token, handler) {\n const pending = useRef(true);\n const connection = useRef(undefined);\n\n useEffect(() => {\n let cancelled = false;\n\n const connectToHub = async (hubClass, auth, callback) => {\n // get hub\n const h = new hubClass(auth);\n\n // define handler callbacks\n h.addHandlers(callback);\n\n // start hub connection\n const c = await h.getConnection();\n\n if (!cancelled) {\n connection.current = c;\n }\n };\n\n connectToHub(hub, token, handler).then(() => (pending.current = false));\n\n return () => {\n cancelled = true;\n\n if (!pending.current && connection.current) {\n connection.current.stop();\n }\n };\n }, [hub, token, handler]);\n\n return [];\n}\n","import React from 'react';\n\nimport Table from './components/tableContainer';\n\nconst DocumentTable = props => ;\n\nexport default DocumentTable;\n","import React from 'react';\nimport { Placeholder } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nimport { TableRowFooter, TableHeader } from './components';\nimport ThemedPlaceholder from '../theme/ThemedPlaceholder';\n\nconst TablePlaceholder = styled(ThemedPlaceholder).attrs({\n fluid: true,\n})`\n height: 350px;\n`;\n\nconst RightPlaceholder = styled(ThemedPlaceholder)`\n margin-left: 95%;\n`;\n\nconst DocumentTablePlaceholder = () => (\n <>\n \n \n \n \n \n \n \n \n >\n);\n\nexport default DocumentTablePlaceholder;\n","import React, { useEffect, useState } from 'react';\nimport { withRouter } from 'react-router-dom';\nimport { connect } from 'react-redux';\nimport { withTranslation } from 'react-i18next';\n\nimport tableApi from 'api/table/tableApi';\nimport { useApi } from 'api/useApi';\nimport Utils from 'core/utils/utils';\nimport { getCurrentUser } from 'core/auth/authReducer';\nimport { ContextMenuCreators } from 'core/context-menu/contextMenuReducer';\nimport { getTemplates } from 'core/template/templateReducer';\nimport { MENU_IDS } from 'core/utils/constant';\n\nimport DocumentTable from './DocumentTable';\nimport DocumentTablePlaceholder from './DocumentTablePlaceholder';\n\nconst DocumentTableContainer = props => {\n const { t, history, addMenu, area, module, tableKey } = props;\n\n const [args] = useState([tableKey]);\n const [activeItem, setActiveItem] = useState([]);\n\n const [fetchedTable, pendingTable] = useApi(tableApi.getTable, args);\n\n useEffect(() => {\n const menuItemOnClick = (action, info) => {\n const urlNav = Utils.buildUrlNav(area, module, info);\n\n if (action === 'Open') {\n // Open in same tab\n history.push(urlNav);\n } else if (action === 'OpenInNewTab') {\n // Open in new tab\n Utils.openInNewTab(urlNav);\n }\n };\n\n const menuTableGridRow = {\n id: MENU_IDS.MENU_TABLE_GRID_ROW,\n items: [\n {\n disabled: !activeItem[1],\n data: { action: 'Open' },\n title: t('common|Open'),\n onClick: (action, info) => menuItemOnClick(action, info),\n },\n {\n disabled: !activeItem[1],\n data: { action: 'OpenInNewTab' },\n title: t('common|Open in new tab'),\n onClick: (action, info) => menuItemOnClick(action, info),\n },\n ],\n };\n\n // setItems(menuItems);\n addMenu(menuTableGridRow);\n }, [addMenu, t, area, history, module, activeItem]);\n\n return pendingTable ? (\n \n ) : (\n \n );\n};\n\nconst mapStateToProps = state => {\n const { token /*, selectedFilters*/ } = getCurrentUser(state);\n\n return {\n token,\n //selectedFilters,\n templates: getTemplates(state),\n };\n};\n\nconst mapDispatchToProps = dispatch => ({\n // setItems: items => dispatch(ContextMenuCreators.setItems(items)),\n addMenu: menu => dispatch(ContextMenuCreators.addMenu(menu)),\n});\n\nexport default withRouter(\n connect(\n mapStateToProps,\n mapDispatchToProps\n )(withTranslation()(DocumentTableContainer))\n);\n","import React from 'react';\nimport { Icon, Segment, Button } from 'semantic-ui-react';\nimport { withTranslation } from 'react-i18next';\nimport styled from 'styled-components';\n\nimport { ThemedSegment, ThemedLabel } from 'components';\nimport TilesPanel from '../tiles/TilesPanel';\n\nconst BodySegment = styled(Segment)`\n &&& {\n padding: 0;\n margin: 0.5rem 0 0 0;\n\n > .ui.segment:not(:first-child) {\n margin-top: 0.5rem;\n margin-bottom: 1rem;\n }\n }\n`;\n\nconst BackButton = styled(Button)`\n &&& {\n font-weight: 700;\n margin-top: 1px;\n }\n`;\n\nconst StyledSegment = styled(({ embedding, ...props }) => (\n \n))`\n ${({ embedding }) =>\n embedding\n ? `\n &&& {\n overflow: hidden;\n }\n `\n : ''}\n`;\n\nconst PageSegment = ({\n t,\n icon,\n label,\n embedding,\n quickaccess,\n tiles,\n routes,\n scroll,\n children,\n basic,\n onBack,\n backgroundColor,\n color,\n}) => (\n \n {onBack && (\n \n )}\n {!quickaccess && (icon && label) && (\n \n \n {quickaccess ? t('common|Quick access') : t(`common|${label}`)}\n \n )}\n {!tiles && children && (\n \n {children}\n \n )}\n {tiles && routes && (\n \n )}\n \n);\n\nexport default withTranslation()(PageSegment);\n","import React from 'react';\nimport DocumentTable from '../tables/documentTableContainer';\nimport PageSegment from './PageSegment';\n\nconst TableSegment = ({ area, module, tableKey, ids, filters, ...props }) => (\n \n \n \n);\n\nexport default TableSegment;\n","import React, { useState } from 'react';\n\nimport Table from '../tables/components/tableContainer';\nimport PageSegment from '../segments/PageSegment';\n\nconst AdminTable = ({ table, dataType, dataKey, ...props }) => {\n const [activeItem, setActiveItem] = useState([]);\n\n return (\n \n \n \n );\n};\n\nexport default AdminTable;\n","import styled from 'styled-components';\n\nconst ScrollableTable = styled.div`\n &&& {\n max-width: 100%;\n min-height: 350px;\n overflow-x: scroll;\n margin-bottom: 1rem;\n scrollbar-width: thin; /*in Firefox*/\n }\n\n // in Chrome\n &&&::-webkit-scrollbar {\n width: 7px;\n height: 7px;\n }\n`;\n\nexport default ScrollableTable;\n","import { toast, ToastContainer } from 'react-toastify';\nimport styled from 'styled-components';\n\nconst StyledToast = styled(ToastContainer).attrs({\n suppressClassNameWarning: true,\n closeButton: false,\n position: toast.POSITION.TOP_CENTER,\n autoClose: 10000,\n})`\n ${({\n theme: {\n color: { border, toastBg, toastFg, boxShadowToast },\n },\n }) => `\n .Toastify__toast {\n padding: 1em 1.5em;\n\n &--info,\n &--success,\n &--warning,\n &--error {\n background-color: ${toastBg};\n color: ${toastFg};\n border: ${border};\n -webkit-box-shadow: ${boxShadowToast};\n box-shadow: ${boxShadowToast};\n border-radius: 0.28571429rem;\n }\n\n .Toastify__toast-body {\n display: flex;\n flex-direction: row;\n flex-wrap: nowrap;\n align-items: stretch;\n max-width: 100%;\n\n > i {\n margin-right: 0.5rem;\n }\n\n > p {\n flex-grow: 1;\n overflow-wrap: anywhere;\n }\n }\n\n &--info .Toastify__progress-bar {\n background: #00b5ad;\n opacity: 0.7 !important;\n }\n &--success .Toastify__progress-bar {\n background: #21ba45;\n opacity: 0.7 !important;\n }\n &--warning .Toastify__progress-bar {\n background: #fbbd08;\n opacity: 0.7 !important;\n }\n &--error .Toastify__progress-bar {\n background: #db2828;\n opacity: 0.7 !important;\n }\n }\n`}\n`;\n\nexport default StyledToast;\n","import React from 'react';\nimport { withTranslation } from 'react-i18next';\nimport { Icon } from 'semantic-ui-react';\n\nconst ToastMessage = ({ t, success, warning, error, message }) => (\n <>\n \n {t(`common|${message}`)}
\n >\n);\n\nexport default withTranslation()(ToastMessage);\n","import React, { useState, Fragment } from 'react';\nimport { element, string } from 'prop-types';\nimport { Image } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nconst HiddenImage = styled(Image)`\n &&&& {\n display: none;\n }\n`;\n\nconst ImageSrcValidator = ({\n src,\n errorComponent: ErrorComponent,\n children: Children,\n}) => {\n const [loaded, setLoaded] = useState(undefined);\n const [error, setError] = useState(false);\n\n // if image loads correctly, set loaded state\n const handleLoad = () => {\n setLoaded(true);\n };\n\n // if image pops error, set loaded and error states\n const handleError = () => {\n setLoaded(true);\n setError(true);\n };\n\n const TestImage = (\n \n );\n\n // try loading image first, then either display children or error component\n return loaded && error\n ? ErrorComponent || Fragment\n : !loaded\n ? TestImage\n : Children || TestImage;\n};\n\nImageSrcValidator.propTypes = {\n src: string,\n errorComponent: element,\n children: element,\n};\n\nexport default ImageSrcValidator;\n","import React from 'react';\nimport { withTranslation } from 'react-i18next';\nimport { Icon, Image } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nimport { ThemedLabel } from 'components';\n\nimport ImageSrcValidator from './ImageSrcValidator';\n\nconst StyledImage = styled(Image)`\n ${({ onClick }) => (onClick ? `cursor: pointer;` : '')}\n margin: 0 auto;\n`;\n\nconst ImagePreview = ({ t, url, data, size, onClick }) => {\n const src = data ? data : url ? url : undefined;\n\n const ErrorComponent = (\n \n \n {`${t('Image not found')}${url ? ` (${url})` : ''}`}\n \n );\n\n return !src ? (\n <>>\n ) : (\n }\n />\n );\n};\n\nexport default withTranslation()(ImagePreview);\n","import _ from 'lodash';\n\nconst renderOptions = options => {\n return _.chain(options)\n .map(o => {\n return o.items\n ? { name: o.text, results: renderOptions(o.items) }\n : { title: o.key !== undefined && o.key !== null ? o.key : o.value };\n })\n .value();\n};\n\nconst getOptions = (options, isCategory, allowAddition, value) => {\n // Add value of dropdown input even when not in list\n if (!isCategory) {\n if (!_.some(options, o => o.value === value) && value !== undefined) {\n options.push({ key: value, text: value, value: value, disabled: true });\n }\n\n if (allowAddition) {\n options.push({ key: '', value: '', text: '' });\n }\n } else {\n const itemsWithoutCategory = _.filter(options, o => {\n return o.items === null || o.items === undefined;\n });\n const categories = _.filter(options, o => {\n return o.items !== null && o.items !== undefined;\n });\n const itemsHasCategory = _.flatMap(categories, opt => opt.items);\n\n if (\n value !== undefined &&\n !_.some(itemsWithoutCategory, o => o.value === value) &&\n !_.some(itemsHasCategory, o => o.value === value)\n ) {\n options.push({ key: value, text: value, value: value, disabled: true });\n }\n }\n\n return renderOptions(options);\n};\n\nexport default getOptions;\n","import React, { useState, useEffect } from 'react';\nimport {\n bool,\n func,\n string,\n arrayOf,\n object,\n oneOfType,\n number,\n} from 'prop-types';\nimport { Form, Icon } from 'semantic-ui-react';\nimport _ from 'lodash';\n\nimport { ThemedSearch } from 'components';\nimport getOptions from './helpers/getOptions';\n\nconst resultRenderer = ({ title }, isAddition) =>\n isAddition ? `Add ${title}` : title;\n\nconst FasterSearch = ({\n editable,\n clearable,\n label,\n required,\n name,\n value,\n options,\n onChange,\n onFocus,\n onBlur,\n onClickLabel,\n ...props\n}) => {\n const isCategory = _.some(\n options,\n o => o.items !== undefined && o.items !== null\n );\n\n const [innerValue, setInnerValue] = useState(value);\n const [initOptions, setInitOptions] = useState(\n getOptions(options, isCategory, editable, value)\n );\n const [loading, setLoading] = useState(false);\n const [keySuggestions, setKeySuggestions] = useState(initOptions);\n const [isAddition, setIsAddition] = useState(false);\n\n useEffect(() => {\n if (value) {\n setInnerValue(value);\n const re = new RegExp(_.escapeRegExp(value), 'i');\n const isMatch = result => re.test(result.title);\n const newKeySuggestions = _.filter(initOptions, isMatch);\n setKeySuggestions(newKeySuggestions);\n }\n }, [value, initOptions]);\n\n const handleSearchChange = (e, field) => {\n setLoading(true);\n setInnerValue(field.value);\n\n setTimeout(() => {\n if (field.value && field.value.length < 1) {\n setLoading(false);\n setKeySuggestions(initOptions);\n return;\n }\n const re = new RegExp(_.escapeRegExp(field.value), 'i');\n const isMatch = result => re.test(result.title);\n const newKeySuggestions = _.filter(initOptions, isMatch);\n\n if (_.isEmpty(newKeySuggestions)) {\n newKeySuggestions.push({ title: field.value });\n if (isAddition === false) {\n setIsAddition(true);\n }\n } else {\n if (isAddition === true) {\n setIsAddition(false);\n }\n }\n\n setLoading(false);\n setKeySuggestions(newKeySuggestions);\n }, 300);\n };\n\n const handleResultSelect = (e, field) => {\n onChange(e, field);\n\n if (isAddition) {\n setInitOptions(oldOptions => [...oldOptions, { title: field.value }]);\n }\n };\n\n let icon = 'search';\n\n if (clearable) {\n const clearInput = e => {\n e.preventDefault();\n e.stopPropagation();\n if (innerValue) {\n setInnerValue('');\n setKeySuggestions(initOptions);\n }\n };\n\n if (innerValue !== undefined && innerValue !== '') {\n icon = ;\n }\n }\n\n return (\n \n {label && (\n \n {label}\n \n )}\n resultRenderer(data, isAddition)}\n showNoResults={false}\n onFocus={onFocus}\n onBlur={onBlur}\n icon={icon}\n {...props}\n />\n \n );\n};\n\nFasterSearch.propTypes = {\n label: string,\n name: string,\n value: oneOfType([string, number]),\n options: arrayOf(object),\n onChange: func.isRequired,\n onFocus: func,\n onBlur: func,\n required: bool,\n onClickLabel: func,\n editable: bool,\n clearable: bool,\n};\n\nFasterSearch.defaultProps = {\n label: undefined,\n name: undefined,\n value: undefined,\n options: [],\n required: false,\n onClickLabel: undefined,\n onFocus: undefined,\n onBlur: undefined,\n editable: false,\n clearable: false,\n};\n\nexport default FasterSearch;\n","import React, { useState } from 'react';\nimport { TimeInput } from 'semantic-ui-calendar-react';\nimport { ThemedInput } from 'components';\n\nconst initialState = { start: undefined, end: undefined };\n\nconst TimeRange = ({ onChange, defaultValue, ...props }) => {\n const defaultState = defaultValue\n ? { start: defaultValue.split('|')[0], end: defaultValue.split('|')[1] }\n : initialState;\n\n const [timeRange, setTimeRange] = useState(defaultState);\n const [oldTimeRange, setOldTimeRange] = useState(defaultState);\n\n const handleSet = (e, { value }) => {\n const { start, end } = timeRange;\n\n const tr =\n start && end\n ? { start: value, end: '' } // already select two value then when we select it again, we start to select a new one\n : {\n start: start ? start : value,\n end: start && start !== value ? value : '',\n };\n\n if (tr.start && tr.end) {\n // switch start-end time if start time is greater than end time\n const startTime = parseInt(tr.start.substr(0, 2));\n const endTime = parseInt(tr.end.substr(0, 2));\n\n if (startTime > endTime) {\n tr.start = `${endTime}:00`;\n tr.end = `${startTime}:00`;\n }\n\n // is finish select time range and the value is different than before then trigger search\n if (tr.start !== oldTimeRange.start || tr.end !== oldTimeRange.end) {\n onChange(e, { value: `${tr.start}|${tr.end}` });\n setOldTimeRange(tr); // save the filter of search to compare with previous later\n }\n }\n\n setTimeRange(tr);\n };\n\n const reset = e => {\n const { start, end } = timeRange;\n if (start && end) {\n // remove filter in search if only the value is searched before\n onChange(e, { value: '' }); // reset filter then trigger search\n setOldTimeRange(initialState);\n setTimeRange(initialState);\n } else if (start && !end) {\n setTimeRange(oldTimeRange); // is clear when selecting new time range then set value to before\n }\n };\n\n return (\n {\n e.stopPropagation();\n }}\n onKeyDown={e => {\n if (e.key !== 'Tab') {\n e.preventDefault(); // block others keys if this is not Tab key\n }\n }}\n className=\"field column\"\n >\n \n
\n );\n};\n\nexport default TimeRange;\n","import React, { useRef, useState } from 'react';\nimport _ from 'lodash';\n\nimport { FIELD_TYPE } from 'core/utils/constant';\nimport { typeMapper } from 'core/utils/mapper';\nimport { FasterDropdown } from 'components';\n\nconst DropdownSearch = ({\n name,\n type,\n loading,\n handleChange,\n options,\n disabled,\n defaultValue,\n singleChoice,\n}) => {\n const search = useRef([]);\n const newSearch = useRef([]);\n const [val, setVal] = useState(defaultValue);\n\n const onBlur = (e, data) => {\n // case add an option then blur\n // check if search are updated then launch the search\n if (searchValueIsDifferent(newSearch.current)) {\n search.current = newSearch.current;\n handleChange(e, {\n name: data.name,\n value:\n newSearch.current && Array.isArray(newSearch.current)\n ? newSearch.current.length > 0\n ? newSearch.current\n : null\n : newSearch.current,\n });\n }\n };\n\n const onChange = (e, data) => {\n setVal(data.value);\n newSearch.current = data.value;\n\n if (Array.isArray(data.value)) {\n //if (data.value) {\n // update selected value but not launching the search\n const preventSearch = true;\n handleChange(e, { name: data.name, value: data.value }, preventSearch);\n //}\n } else {\n newSearch.current = data.value;\n handleChange(e, { name: data.name, value: data.value });\n }\n };\n\n const dropdownProps = {\n name: name,\n loading: loading,\n multiple:\n !singleChoice || _.includes([FIELD_TYPE.multiselect], typeMapper(type)),\n editable: _.includes(\n [FIELD_TYPE.editabledropdown, FIELD_TYPE.searcheditselect],\n typeMapper(type)\n ),\n disabled: disabled,\n options:\n options && options.length > 0\n ? options.filter(o => o.value.length > 0)\n : [],\n categorize: options.length > 0 && options.some(opt => opt.items !== null),\n onBlur: !singleChoice ? onBlur : undefined,\n onChange: onChange,\n };\n\n const searchValueIsDifferent = newValue =>\n search.current.length !== newValue.length ||\n newValue.filter(s => search.current.indexOf(s) === -1).length > 0;\n\n return ;\n};\n\nexport default DropdownSearch;\n","import React, { useState } from 'react';\nimport { Checkbox, Icon } from 'semantic-ui-react';\n\nimport Utils from 'core/utils/utils';\n\nconst CheckboxSearch = ({\n name,\n handleChange,\n disabled,\n controlled,\n defaultValue,\n}) => {\n const [indeterminate, setIndeterminate] = useState(true);\n const checked = Utils.getBoxChecked(defaultValue);\n\n return (\n \n
{\n if (indeterminate) {\n setIndeterminate(false);\n }\n\n e.stopPropagation();\n }} //Prevent event handleSort from parent component\n />\n \n {\n if (!indeterminate) {\n setIndeterminate(true);\n\n handleChange(e, { name: data.name, checked: undefined });\n }\n\n e.stopPropagation();\n }}\n />\n
\n \n );\n};\n\nexport default CheckboxSearch;\n","import React, { useState, useRef } from 'react';\nimport { Form, Icon, Input } from 'semantic-ui-react';\nimport _ from 'lodash';\n\nimport Utils from 'core/utils/utils';\nimport { FIELD_TYPE, OPERATOR } from 'core/utils/constant';\nimport { typeMapper } from 'core/utils/mapper';\nimport { CalendarPicker, ThemedInput } from 'components';\n\n//import CalendarPicker from '../calendar/CalendarPicker';\n\nimport TimeRange from '../calendar/TimeRange';\nimport DropdownSearch from './DropdownSearch';\nimport CheckboxSearch from './CheckboxSearch';\n\nconst WAIT_INTERVAL = 700;\nlet timer = null;\n\nconst InputSearch = ({\n t,\n column,\n handleValue,\n controlled = false,\n disabled = false,\n defaultValue,\n operator = OPERATOR.contains,\n levelFilter = 'quick',\n singleChoice,\n loading,\n dispatch,\n clearable,\n icon,\n ...props\n}) => {\n // const [loading, setLoading] = useState(false);\n const [dateRangeValue, setDateRangeValue] = useState('');\n const inputRef = useRef();\n\n const handleClick = e => {\n e.stopPropagation();\n };\n\n // input value change handler\n const handleChange = (e, data, preventSearch) => {\n clearTimeout(timer);\n const colWithVal = {\n ...column,\n value:\n !column || column.checked === undefined\n ? data.checked === undefined\n ? data.value\n : data.checked\n : column.checked,\n };\n\n if (levelFilter === 'quick') {\n timer = setTimeout(\n () => handleValue(e, colWithVal, preventSearch),\n WAIT_INTERVAL\n );\n } else {\n handleValue(e, colWithVal, preventSearch);\n }\n };\n\n const handleDateRangeChange = (e, data) => {\n setDateRangeValue(data.value);\n\n if (data.value.indexOf(' - ') < 0) {\n // is both dates are selected then trigger search\n handleChange(e, data);\n }\n };\n\n // prefill input with data to facilitate date period selection\n const handleClickDatetime = (e, val) => {\n const event = e;\n const d = { value: '' };\n\n d.value = Utils.getDefaultDateTimePeriod(val);\n\n handleChange(event, d, column);\n };\n\n //render\n // if table column input search (as opposed to all data search)\n if (column) {\n // Checkbox case\n if (_.includes([FIELD_TYPE.checkbox], typeMapper(column.type))) {\n return (\n \n );\n }\n\n // ComboList/editable dropdown case\n if (\n _.includes(\n [\n FIELD_TYPE.combolist,\n FIELD_TYPE.editabledropdown,\n FIELD_TYPE.searchselect,\n FIELD_TYPE.searcheditselect,\n FIELD_TYPE.multiselect,\n ],\n column.type\n )\n ) {\n return (\n \n );\n }\n\n if (\n _.includes(\n [FIELD_TYPE.decimal, FIELD_TYPE.number],\n typeMapper(column.type)\n ) &&\n operator === OPERATOR.between\n ) {\n const leftValue = defaultValue ? defaultValue.split('|')[0] : '';\n const rightValue =\n defaultValue && defaultValue.includes('|')\n ? defaultValue.split('|')[1]\n : '';\n\n return (\n <>\n {\n data.value = `${data.value}|${rightValue}`;\n handleChange(e, data);\n }}\n />\n {t('And')} \n {\n data.value = `${leftValue}|${data.value}`;\n handleChange(e, data);\n }}\n />\n >\n );\n }\n\n if (_.includes([FIELD_TYPE.decimal], typeMapper(column.type)))\n return (\n \n );\n\n if (\n levelFilter === 'quick' &&\n _.includes(\n [FIELD_TYPE.date, FIELD_TYPE.datetime],\n typeMapper(column.type)\n )\n ) {\n // for quick search, we need to use hooks to set the current value of date range picker\n return (\n \n );\n }\n\n if (\n levelFilter === 'quick' &&\n _.includes([FIELD_TYPE.time], typeMapper(column.type))\n ) {\n return ;\n }\n\n if (\n levelFilter === 'advanced' &&\n _.includes([FIELD_TYPE.date], typeMapper(column.type)) &&\n operator === OPERATOR.between\n ) {\n return (\n \n );\n }\n\n if (\n _.includes([FIELD_TYPE.datetime], typeMapper(column.type)) &&\n levelFilter === 'advanced' &&\n operator === OPERATOR.between\n ) {\n const leftValue = defaultValue ? defaultValue.split('|')[0] : '';\n const rightValue = defaultValue ? defaultValue.split('|')[1] : '';\n\n return (\n <>\n handleClickDatetime(e, defaultValue)}\n onChange={(e, data) => {\n data.value = `${data.value}|${rightValue}`;\n handleChange(e, data);\n }}\n />\n {t('And')} \n handleClickDatetime(e, defaultValue)}\n onChange={(e, data) => {\n data.value = `${leftValue}|${data.value}`;\n handleChange(e, data);\n }}\n />\n >\n );\n }\n\n if (\n _.includes([FIELD_TYPE.time], typeMapper(column.type)) &&\n levelFilter === 'advanced' &&\n operator === OPERATOR.between\n ) {\n return (\n \n );\n }\n\n // for input type date, datetime, time which doesn't have operator between (in batch edit)\n if (\n levelFilter === 'advanced' &&\n _.includes(\n [FIELD_TYPE.date, FIELD_TYPE.time, FIELD_TYPE.datetime],\n column.type\n )\n ) {\n return (\n \n );\n }\n }\n\n if (clearable) {\n const inputValue =\n inputRef.current && inputRef.current.inputRef.current.value;\n\n const clearInput = e => {\n e.preventDefault();\n e.stopPropagation();\n if (inputRef.current) {\n inputRef.current.inputRef.current.value = '';\n handleChange(e, '');\n }\n };\n\n if (inputValue !== undefined && inputValue !== '') {\n icon = ;\n }\n }\n\n // fallbacks to Input for all cases\n return (\n \n );\n};\n\nexport default InputSearch;\n","import React, { Component } from 'react';\nimport { DateRangePicker } from 'react-dates';\nimport moment from 'moment';\n// import frLocale from 'moment/locale/fr';\nimport styled, { createGlobalStyle } from 'styled-components';\n\nconst Wrapper = styled.div`\n ${({\n theme: {\n color: { inputBg, inputFg, borderColor },\n },\n }) => `\n .DateRangePickerInput__withBorder {\n border: 1px solid rgba(34, 36, 38, 0.15);\n border-radius: 0.28571429rem;\n }\n\n .DateRangePickerInput__showClearDates {\n padding-right: 22px;\n }\n\n .DateRangePicker_picker {\n z-index: 2;\n }\n\n .DateInput {\n width: 85px;\n }\n\n .DateRangePickerInput_arrow {\n width: 5px;\n color: ${inputFg};\n }\n\n .DateInput_input {\n font-weight: 400;\n font-style: normal;\n font-size: 1em;\n font-family: Lato, 'Helvetica Neue', Arial, Helvetica, sans-serif;\n padding: 0.44em 0.3em;\n line-height: 24px !important;\n width: 100% !important;\n border: 0 !important;\n border-radius: 0 !important;\n background-color: ${inputBg};\n color: ${inputFg};\n border-color: ${borderColor};\n }\n\n .DateRangePickerInput {\n background-color: ${inputBg};\n color: ${inputFg};\n }\n\n .DateRangePickerInput_clearDates {\n margin: 0 5px 0 0;\n padding: 5px;\n line-height: 10px;\n }\n\n .DateRangePickerInput_clearDates_svg {\n height: 12px;\n width: 12px;\n }\n `}\n`;\n\nconst DateRangePickerModal = createGlobalStyle`\n .DateRangePicker_picker__portal {\n z-index: 99;\n }\n`;\n\nclass DateRangePickerWrapper extends Component {\n state = {\n startDate: null,\n endDate: null,\n focusedInput: null,\n };\n\n onDatesChange = ({ startDate, endDate }) => {\n const { submit } = this.props;\n\n this.setState({ startDate, endDate });\n\n if (\n (startDate !== null && endDate !== null) ||\n (startDate === null && endDate === null)\n ) {\n submit(startDate, endDate);\n }\n };\n\n onFocusChange = focusedInput => this.setState({ focusedInput });\n\n render() {\n // set fr dates localization\n // (should load correct language from i18n for dates)\n // moment.locale('fr', frLocale);\n\n const { focusedInput, startDate, endDate } = this.state;\n const { showAsModal, direction } = this.props;\n\n return (\n {\n e.stopPropagation();\n }} // prevent event handleSort from parent component\n >\n {showAsModal && }\n false}\n displayFormat=\"YYYY-MM-DD\"\n withPortal={showAsModal}\n initialVisibleMonth={() => moment().add(-1, 'M')}\n minimumNights={0}\n startDatePlaceholderText=\"aaaa-mm-jj\"\n endDatePlaceholderText=\"aaaa-mm-jj\"\n showClearDates\n hideKeyboardShortcutsPanel\n />\n \n );\n }\n}\n\nexport default DateRangePickerWrapper;\n","import React, { useCallback, useEffect, useReducer, useRef } from 'react';\nimport PropTypes from 'prop-types';\nimport { Form } from 'semantic-ui-react';\nimport _ from 'lodash';\n\nimport addressApi from 'api/address/addressApi';\nimport { ThemedSearch, ThemedSegment } from 'components';\n\nconst initialState = { isLoading: false, results: [], value: '' };\n\nconst resultRenderer = ({ title }) => title;\n\nresultRenderer.propTypes = {\n title: PropTypes.string,\n};\n\nconst searchReducer = (state, action) => {\n switch (action.type) {\n case 'CLEAN_QUERY':\n return initialState;\n case 'START_SEARCH':\n return { ...state, loading: true, value: action.query };\n case 'FINISH_SEARCH':\n return { ...state, loading: false, results: action.results };\n case 'UPDATE_SELECTION':\n return { ...state, value: action.selection };\n default:\n throw new Error();\n }\n};\n\nconst WAIT_INTERVAL = 300;\n\nconst InputAddress = () => {\n const [state, dispatch] = useReducer(searchReducer, initialState);\n const { loading, results, value } = state;\n\n const timeoutRef = useRef();\n\n const buildQuery = (\n data = {},\n { focus = null, bRect = null, bCircle = null, bCountry = null }\n ) => {\n const params = {};\n if (focus) {\n params['focus.point.lat'] = focus.latitude;\n params['focus.point.lon'] = focus.longitude;\n }\n if (bRect) {\n params['boundary.rect.min_lon'] = bRect[0];\n params['boundary.rect.min_lat'] = bRect[1];\n params['boundary.rect.max_lon'] = bRect[2];\n params['boundary.rect.max_lat'] = bRect[3];\n }\n if (bCircle) {\n params['boundary.circle.lat'] = bCircle[0];\n params['boundary.circle.lon'] = bCircle[1];\n params['boundary.circle.radius'] = bCircle[2];\n }\n if (bCountry) {\n params['boundary.country'] = bCountry;\n }\n return _.assign({}, data, params);\n };\n\n const handleResultSelect = (e, { result }) => {\n dispatch({ type: 'UPDATE_SELECTION', selection: result.title });\n };\n\n const handleSearchChange = useCallback((e, { value }) => {\n clearTimeout(timeoutRef.current);\n dispatch({ type: 'START_SEARCH', query: value });\n\n timeoutRef.current = setTimeout(() => {\n if (value.length === 0) {\n dispatch({ type: 'CLEAN_QUERY' });\n return;\n }\n\n const data = buildQuery({ text: value }, {});\n\n addressApi.autocomplete(data).then(res => {\n if (res.data && res.data.features) {\n const { features } = res.data;\n\n const results = _.chain(features)\n .uniqBy(({ properties: { label } }) => label)\n .map(({ properties: { label } }) => ({ title: label }))\n .value();\n\n dispatch({ type: 'FINISH_SEARCH', results });\n }\n });\n }, WAIT_INTERVAL);\n }, []);\n\n useEffect(() => {\n return () => {\n clearTimeout(timeoutRef.current);\n };\n }, []);\n\n return (\n \n Champ de type addresse \n \n \n \n \n {JSON.stringify({ loading, results, value }, null, 2)}\n \n \n \n );\n};\n\nexport default InputAddress;\n","import styled from 'styled-components';\n\nimport { ThemedButton } from 'components';\n\nconst InputButton = styled(ThemedButton).attrs(() => ({\n type: 'button',\n size: 'tiny',\n}))`\n ${({ theme: { color: buttonDisabled } }) => `\n &&&& {\n max-width: calc(50% - 0.25em);\n text-overflow: ellipsis;\n white-space: nowrap;\n overflow: hidden;\n\n &:disabled {\n background-color: \n ${buttonDisabled} !important;\n opacity: 1 !important;\n }\n }\n `}\n`;\n\nexport default InputButton;\n","import React from 'react';\n\nimport { ColoredIcon, ThemedInput } from 'components';\n\nimport InputButton from '../components/InputButton';\n\nconst LinkInput = ({\n name,\n value,\n required,\n disabled,\n showIframe,\n onChange,\n handleToggleShowIframe,\n handleOpenInNewTab,\n}) => {\n return (\n <>\n \n ) : (\n undefined\n )\n }\n action={\n \n }\n onChange={onChange}\n />\n {value && showIframe && (\n \n )}\n >\n );\n};\n\nexport default LinkInput;\n","import React, { useState } from 'react';\n\nimport Utils from 'core/utils/utils';\n\nimport LinkInput from './LinkInput';\n\nconst LinkInputContainer = ({ name, value, required, disabled, onChange }) => {\n const [showIframe, setShowIframe] = useState(false);\n\n const handleToggleShowIframe = () => {\n setShowIframe(!showIframe);\n };\n\n const handleOpenInNewTab = () => {\n Utils.openInNewTab(value);\n };\n\n const linkProps = {\n name,\n value,\n required,\n disabled,\n showIframe,\n onChange,\n handleToggleShowIframe,\n handleOpenInNewTab,\n };\n\n return ;\n};\n\nexport default LinkInputContainer;\n","import styled from 'styled-components';\nimport { FIELD_TYPE } from 'core/utils/constant';\nimport { IMAGE_TYPES, typesAsString } from 'core/utils/mimeTypes';\n\nconst InputFileHidden = styled.input.attrs({\n type: FIELD_TYPE.file,\n})`\n &&&&&& {\n opacity: 0;\n height: 0;\n width: 0;\n padding: 0 !important;\n float: left;\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n }\n`;\n\nconst InputFileImageHidden = styled(InputFileHidden).attrs({\n accept: typesAsString(IMAGE_TYPES),\n})``;\n\nexport { InputFileHidden, InputFileImageHidden };\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Divider } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nimport { FIELD_TYPE } from 'core/utils/constant';\n\nimport InputButton from '../components/InputButton';\nimport {\n InputFileHidden,\n InputFileImageHidden,\n} from './components/InputFileHidden';\nimport { Center, ColoredIcon, ImagePreview, ThemedInput } from '../..';\n\nconst { file, photo } = FIELD_TYPE;\n\nconst StyledDivider = styled(Divider)`\n &&&& {\n margin: 5px 0;\n }\n`;\n\nconst InputFile = ({\n name,\n label,\n type,\n value,\n url,\n data,\n disableDelete,\n htmlInput,\n required,\n disabled,\n handleChangeFile,\n handleOpenInNewTab,\n handleSelectFile,\n handleResetFile,\n}) => {\n const { t } = useTranslation();\n const isPhoto = type === photo;\n const isFile = type === file;\n\n const InputHidden = isPhoto ? (\n InputFileImageHidden\n ) : isFile ? (\n InputFileHidden\n ) : (\n <>>\n );\n\n return (\n <>\n {label} \n \n \n ) : (\n undefined\n )\n }\n action={\n \n }\n />\n {(data || url) && (\n \n \n {isPhoto && (\n \n )}\n {isFile && (\n \n )}\n \n )}\n >\n );\n};\n\nexport default InputFile;\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { INVALID_FILE_TYPE, FILE_SIZE_LIMIT } from 'core/utils/constant';\n\nimport { ToastMessage } from 'components';\n\nconst ToastFileError = ({ invalidType }) => {\n const { t } = useTranslation();\n\n switch (invalidType) {\n case INVALID_FILE_TYPE.invalidImageExtension:\n return ;\n\n case INVALID_FILE_TYPE.invalidFileExtension:\n return ;\n\n case INVALID_FILE_TYPE.invalidSize:\n default:\n return (\n \n );\n }\n};\n\nexport default ToastFileError;\n","import React, { useRef, useState } from 'react';\nimport { toast } from 'react-toastify';\n\nimport Utils from 'core/utils/utils';\nimport { FIELD_TYPE } from 'core/utils/constant';\n\nimport InputFile from './InputFile';\nimport ToastFileError from './components/ToastFileError';\n\nconst { photo } = FIELD_TYPE;\n\nconst InputFileContainer = ({\n name,\n label,\n type,\n defaultValue,\n required: propRequired,\n disabled,\n disableDelete,\n onChange,\n}) => {\n const htmlInput = useRef(null);\n\n const filename = Utils.getFullNameFromUrl(defaultValue);\n const initialValue = filename.includes('_')\n ? `${Utils.base64DecodeUnicode(filename.split('_')[0])}.${filename\n .split('.')\n .pop()}`\n : filename;\n\n const [value, setValue] = useState(initialValue);\n const [fileUrl, setFileUrl] = useState(defaultValue);\n const [data, setData] = useState();\n\n const handleChangeFile = (e, field) => {\n e.preventDefault();\n\n const file = e.target.files[0];\n const fileIsPhoto = type === photo;\n\n if (file) {\n const res = Utils.fileValidated(file, fileIsPhoto);\n\n if (res && res.result) {\n // set data as local (no url)\n setFileUrl();\n\n if (fileIsPhoto) {\n const reader = new FileReader();\n\n reader.readAsDataURL(file);\n setValue(file.name);\n\n reader.onloadend = () => {\n setData(reader.result);\n };\n } else {\n setValue(file.name);\n }\n\n onChange(e, field);\n } else {\n toast.error( );\n }\n }\n };\n\n const handleResetFile = e => {\n // reset state\n setValue();\n setData();\n setFileUrl();\n\n // reset html input\n htmlInput.current.value = '';\n onChange(e, htmlInput.current);\n };\n\n const handleSelectFile = e => {\n e.preventDefault();\n htmlInput.current.click();\n };\n\n const handleOpenInNewTab = () => {\n Utils.openInNewTab(defaultValue);\n };\n\n // XOR operation for toggle the required validation\n const required =\n propRequired &&\n (!!htmlInput.current && !!htmlInput.current.value) === (!!value || !!data);\n\n return (\n \n );\n};\n\nexport default InputFileContainer;\n","const getShadowByState = (saved, unchanged) => {\n return saved\n ? '#21ba45 30px 0px 0px -27px inset'\n : unchanged\n ? 'none'\n : '#fbbd08 30px 0px 0px -27px inset';\n};\n\nexport default getShadowByState;\n","import React, { useState, useEffect } from 'react';\nimport { withTranslation } from 'react-i18next';\n\nimport FasterDropdown from 'components/input/dropdown/FasterDropdown';\n\nimport _ from 'lodash';\n\nconst AdditionsInput = ({\n t,\n options,\n handleAddition,\n handleChange,\n handleFocusChange,\n handleOnClose,\n value,\n name,\n multiple = false,\n clearable = false,\n}) => {\n const [, setSearchQuery] = useState('');\n\n useEffect(() => {\n if (value && value !== '') {\n setSearchQuery(value);\n }\n }, []);\n\n const onChange = (e, field) => {\n const { value } = field && field.value ? field : e.target;\n\n // if (!multiple) {\n // setSearchQuery(value); // keep entered value when focus back to this input after selection.\n // }\n\n setSearchQuery(value);\n\n handleChange(e, field);\n };\n\n //const onSearchChange = (e, field) => {\n // setSearchQuery(field.searchQuery);\n\n // handleChange(e, { name: field.name, value: field.searchQuery });\n //};\n\n // const searchQueryProps = multiple\n // ? {}\n // : {\n // onSearchChange: (e, data) => onSearchChange(e, data),\n // searchQuery: searchQuery,\n // };\n\n return (\n {\n return { key: o.value, value: o.value, text: o.text };\n })\n ),\n 'value'\n )}\n onAddItem={handleAddition}\n onChange={onChange}\n onClose={handleOnClose}\n onFocus={handleFocusChange}\n onBlur={handleFocusChange}\n clearable={clearable}\n // {...searchQueryProps}\n />\n );\n};\n\nexport default withTranslation()(AdditionsInput);\n","import React from 'react';\nimport styled from 'styled-components';\n\nimport { ThemedInput } from 'components';\n\nimport getShadowByState from './helpers/getShadowByState';\n\nconst TrackedInput = styled(({ unchanged, saved, value, ...props }) => (\n \n))`\n ${({ saved, unchanged }) => `\n &&&&& input {\n box-shadow: ${getShadowByState(saved, unchanged)};\n }\n `}\n`;\n\nexport default TrackedInput;\n","import React from 'react';\nimport styled from 'styled-components';\n\nimport { ThemedDropdown } from 'components';\n\nimport getShadowByState from './helpers/getShadowByState';\n\nconst TrackedDropdown = styled(({ unchanged, saved, ...props }) => (\n \n))`\n ${({ saved, unchanged }) => `\n &&&&& {\n box-shadow: ${getShadowByState(saved, unchanged)};\n }\n `}\n`;\n\nexport default TrackedDropdown;\n","import React from 'react';\nimport styled from 'styled-components';\nimport { Form, Checkbox } from 'semantic-ui-react';\n\nimport getShadowByState from './helpers/getShadowByState';\n\nconst TrackedCheckbox = styled(\n ({ value, unchanged, saved, type, ...props }) => (\n \n )\n)`\n ${({\n saved,\n unchanged,\n theme: {\n color: { fg, checkboxBg, checkboxBgHover },\n },\n }) => `\n &&&&& label::before {\n box-shadow: ${getShadowByState(saved, unchanged)};\n }\n\n &&& {\n label,\n input:active:checked ~ label,\n input:checked ~ label {\n color: ${fg} !important;\n }\n }\n\n &.toggle label {\n &::before {\n background-color: ${checkboxBg};\n }\n &:hover::before {\n background-color: ${checkboxBgHover};\n }\n }\n `}\n`;\n\nexport default TrackedCheckbox;\n","import React from 'react';\nimport styled from 'styled-components';\n\nimport { ThemedSearch } from 'components';\n\nimport getShadowByState from './helpers/getShadowByState';\n\nconst TrackedSearch = styled(({ unchanged, saved, ...props }) => (\n \n))`\n ${({ saved, unchanged }) => `\n &&&&& div input {\n box-shadow: ${getShadowByState(saved, unchanged)};\n }\n `}\n`;\n\nexport default TrackedSearch;\n","import React, { useEffect, useState, useCallback } from 'react';\nimport { Icon } from 'semantic-ui-react';\nimport { ALL_ICONS_IN_ALL_CONTEXTS } from 'semantic-ui-react/dist/commonjs/lib/SUI';\nimport { func, string } from 'prop-types';\nimport _ from 'lodash';\n\nimport { TrackedSearch } from 'components';\n\nconst resultRenderer = ({ title }) => (\n \n \n {title}\n
\n);\n\nresultRenderer.propTypes = {\n title: string.isRequired,\n};\n\nconst IconInput = ({ name, value, onChange, type, ...props }) => {\n const [val, setVal] = useState(value || '');\n const [loading, setLoading] = useState(false);\n const [results, setResults] = useState([]);\n\n useEffect(() => {\n setTimeout(() => {\n setLoading(false);\n\n if (!val) {\n setResults([]);\n } else {\n setResults(\n _.filter(ALL_ICONS_IN_ALL_CONTEXTS, s => s.indexOf(val) >= 0).map(\n s => ({ title: s })\n )\n );\n }\n }, 200);\n }, [val]);\n\n const handleResultSelect = useCallback(\n (e, { result }) => {\n setVal(result.title);\n onChange(e, { name, value: result.title });\n },\n [name, onChange]\n );\n\n const handleSearchChange = (e, { value }) => {\n if (!loading) {\n setLoading(true);\n }\n\n setVal(value);\n onChange(e, { name, value });\n };\n\n return (\n \n );\n};\n\nIconInput.propTypes = {\n name: string.isRequired,\n value: string,\n onChange: func.isRequired,\n};\n\nexport default IconInput;\n","import React from 'react';\nimport { Icon } from 'semantic-ui-react';\n\nconst NewGridIcons = () => (\n <>\n \n \n >\n);\n\nexport default [\n {\n type: 'link',\n content: '/admin/grids',\n iconName: undefined,\n icons: NewGridIcons,\n popupMenu: undefined,\n },\n];\n","export default [\n {\n type: 'link',\n content: '/admin/users/register',\n iconName: 'user plus',\n },\n];\n","import React from 'react';\nimport { Button } from 'semantic-ui-react';\n\nimport { FasterDropdown } from 'components';\n\nconst DownloadButton = ({\n disabled,\n loading,\n dropdownRef,\n name,\n icon,\n iconColor,\n color,\n downloadOptions,\n handleFetch,\n handleChange,\n}) => {\n return (\n \n \n \n );\n};\n\nexport default DownloadButton;\n","import React, { useState, useRef } from 'react';\nimport { bool, func, string } from 'prop-types';\nimport _ from 'lodash';\n\nimport documentApi from 'api/document/documentApi';\nimport { DOWNLOAD_TYPE } from 'core/utils/constant';\n\nimport DownloadButton from './DownloadButton';\n\nconst { pdf } = DOWNLOAD_TYPE;\nconst fileTypeDownload = [pdf];\n\n// map template names and types to dropdown options\nconst getDownloadOptions = templateNames =>\n _.map(fileTypeDownload, t => ({\n key: `${t}`,\n value: `${t}`,\n text: `${t}`,\n items: _.map(templateNames, n => ({\n key: `${t}_${n}`,\n value: `${t}_${n}`,\n text: n,\n })),\n }));\n\nconst DownloadButtonContainer = ({\n disabled,\n name,\n icon,\n iconColor,\n color,\n onDownload,\n}) => {\n const dropdownRef = useRef();\n const [loading, setLoading] = useState(false);\n const [downloadOptions, setDownloadOptions] = useState();\n\n // get all download templates on dropdown opening\n const handleFetch = async () => {\n if (!downloadOptions) {\n setLoading(true);\n const result = await documentApi.getDownloadTemplates();\n\n if (result && result.downloadTemplateNames) {\n setDownloadOptions(getDownloadOptions(result.downloadTemplateNames));\n setLoading(false);\n }\n }\n };\n\n // start download on item click in dropdown\n const handleChange = (e, { value }) => {\n const split = value.split('_', 2);\n const fileType = split[0];\n const templateName = split[1];\n\n onDownload(templateName, fileType);\n };\n\n const buttonProps = {\n name,\n icon,\n iconColor,\n color,\n disabled,\n loading,\n dropdownRef,\n downloadOptions,\n handleFetch,\n handleChange,\n };\n\n return ;\n};\n\nDownloadButtonContainer.propTypes = {\n disabled: bool,\n name: string,\n onDownload: func,\n};\n\nexport default DownloadButtonContainer;\n","import React from 'react';\nimport { Button } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nconst ButtonAsLink = styled(Button).attrs({\n basic: true,\n primary: true,\n type: 'button',\n})`\n ${({\n theme: {\n color: { primary },\n },\n }) => `\n &&&&&& {\n overflow: hidden;\n max-width: 100%;\n white-space: nowrap;\n text-overflow: ellipsis;\n }\n\n &&&&&&,\n &&&&&&:hover,\n &&&&&&:focus,\n &&&&&&:target {\n border: 0 !important;\n border-radius: 0 !important;\n box-shadow: none !important;\n padding: 0.4em 0.2em;\n color: ${primary} !important;\n }\n\n &&&&&&:hover {\n border-radius: 0 !important;\n box-shadow: 0 0.1em 0 -0.05em !important;\n }\n `}\n`;\n\nconst ButtonLink = ({ text, icon, iconName, handleClickFunc }) => (\n \n);\n\nexport default ButtonLink;\n","import BaseApi from 'api/baseApi';\n\nconst userFilterApi = {\n putMany: (filters, params) => BaseApi.put(`userfilter`, { filters }, params),\n};\n\nexport default userFilterApi;\n","import React from 'react';\nimport { ThemedButton } from 'components';\n\nconst DocumentButton = ({ name, ...props }) => (\n {name} \n);\n\nDocumentButton.propTypes = {};\n\nDocumentButton.defaultProps = {};\n\nexport default DocumentButton;\n","import React, { useEffect, useState, useRef } from 'react';\nimport { connect } from 'react-redux';\nimport { Button } from 'semantic-ui-react';\nimport _ from 'lodash';\n\nimport { FORM_LAYOUT_TYPE } from 'core/utils/constant';\nimport { usePrint } from 'core/hooks/usePrint';\nimport { getVisibleFormData } from 'core/form-data/formDataReducer';\nimport { getTemplates } from 'core/template/templateReducer';\n\nimport { FasterDropdown } from '..';\n\nimport DocumentButton from './DocumentButton';\n\nconst PrintButton = ({\n // stores\n dispatch,\n formData,\n templates,\n // props\n documentID,\n printNow,\n selectedTemplate,\n disabled,\n onClick,\n onPrint,\n ...props\n}) => {\n const printOptions = _.map(\n _.filter(templates, {\n type: FORM_LAYOUT_TYPE.print,\n }),\n t => ({\n value: t.key,\n text: t.name,\n key: t.key,\n })\n );\n\n if (printOptions.length < 1) {\n printOptions.push({\n value: selectedTemplate.key,\n text: selectedTemplate.name,\n key: selectedTemplate.key,\n });\n }\n\n const keyRef = useRef(printOptions[0].key);\n const printData = useRef();\n\n const [templateKey, setTemplateKey] = useState(keyRef.current);\n const [template, setTemplate] = useState();\n\n const [printPending] = usePrint(printData.current, template);\n\n // update form data\n useEffect(() => {\n printData.current = [{ documentID, ...formData }];\n }, [documentID, formData]);\n\n // template key was changed or print was started\n useEffect(() => {\n // template has changed -> trigger click\n if (!printNow && keyRef.current !== templateKey) {\n onClick();\n }\n // print was started -> trigger usePrint hook\n else if (printNow && keyRef.current === templateKey) {\n setTemplate(\n _.find(templates, {\n key: templateKey,\n })\n );\n }\n\n // update ref\n keyRef.current = templateKey;\n }, [printNow, templates, templateKey, onClick]);\n\n // deactivate print until next button click\n useEffect(() => {\n if (printPending) {\n setTemplate();\n onPrint();\n }\n }, [printPending, onPrint]);\n\n // change templat key from dropdown\n const changePrint = (e, { value }) => {\n setTemplateKey(value);\n };\n\n disabled = disabled || printPending;\n\n return (\n \n \n \n \n );\n};\n\nPrintButton.propTypes = {};\n\nPrintButton.defaultProps = {};\n\nconst mapStateToProps = state => ({\n formData: getVisibleFormData(state),\n templates: getTemplates(state),\n});\n\nexport default connect(\n mapStateToProps,\n null\n)(PrintButton);\n","import React, { useEffect, useState } from 'react';\nimport { withRouter } from 'react-router-dom';\nimport { connect } from 'react-redux';\nimport { withTranslation } from 'react-i18next';\nimport { toast } from 'react-toastify';\nimport { arrayOf, bool, func, object } from 'prop-types';\nimport _ from 'lodash';\n\nimport userFilterApi from 'api/user/userFilterApi';\nimport documentApi from 'api/document/documentApi';\nimport Utils from 'core/utils/utils';\nimport { AuthCreators, getCurrentUser } from 'core/auth/authReducer';\nimport { TemplateCreators, getTemplates } from 'core/template/templateReducer';\nimport { ModalCreators } from 'core/modal/modalReducer';\nimport { BUTTON_TYPE, DRAFT_STATUS } from 'core/utils/constant';\nimport { ToastMessage } from 'components';\nimport { isValidPopup, isValidDocument } from 'core/utils/utilsModal';\n\nimport DownloadButton from './downloadButtonContainer';\nimport PrintButton from './PrintButton';\nimport DocumentButton from './DocumentButton';\n\nconst DocumentButtonContainer = ({\n // stores\n t,\n history,\n templates,\n updateTemplate,\n updateIsSubmitting,\n // props\n isValidForm,\n documentID,\n clickable,\n closeModal,\n openModal,\n changeSize,\n popupAction,\n viewersWarning,\n formData,\n requiredFields,\n patternFields,\n filterSelection,\n selectedTemplate,\n currentUser,\n updateCurrentUser,\n clearFunc,\n submitFunc,\n}) => {\n const [startPrint, setStartPrint] = useState();\n const [, setInnerFormData] = useState(formData);\n const [loading, setLoading] = useState(false);\n\n useEffect(() => {\n setInnerFormData(formData);\n }, [formData]);\n\n const { cId, btnKey, btnName, btnType, toStatus } = {\n cId: clickable.clickableId,\n btnKey: clickable.key,\n btnName: clickable.name,\n btnType: clickable.type,\n toStatus: clickable.toStatus,\n };\n\n const handleCloseModal = () => {\n setLoading(false);\n closeModal();\n };\n\n // show modal on button click\n const showModal = () => {\n setLoading(true);\n\n // read fields from templates\n const fields = Utils.getFieldsFromTemplates(templates);\n\n // if valid document\n if (\n _.includes([BUTTON_TYPE.print], btnType) ||\n //(_.includes([BUTTON_TYPE.download], btnType) /*&& documentID > 0*/) ||\n toStatus === DRAFT_STATUS ||\n (!filterSelection &&\n _.includes([BUTTON_TYPE.link, BUTTON_TYPE.reset], btnType)) ||\n isValidDocument(formData, requiredFields, patternFields, fields)\n ) {\n // define modal\n const { name, message, ok, cancel } = popupAction;\n\n const modalOptions = {\n title: name ? t(`common|${name}`) : '',\n message: message ? t(message) : '',\n warning: viewersWarning\n ? t(\n `Other users are viewing this document, continuing may disrupt their operations`\n )\n : '',\n btnTitle: ok ? t(`common|${ok}`) : '',\n onBtnClick: () => yesAction(),\n secondaryBtnTitle: cancel ? t(`common|${cancel}`) : '',\n onSecondaryBtnClick: handleCloseModal,\n popupAction: popupAction,\n };\n\n // open modal\n changeSize('tiny');\n openModal('form-action', modalOptions);\n } else {\n setLoading(false);\n }\n };\n\n // when user clicks ok in modal\n const yesAction = async () => {\n updateIsSubmitting(true);\n\n if (await isValidPopup(popupAction, setInnerFormData)) {\n switch (btnType) {\n case BUTTON_TYPE.status:\n changeStatus();\n break;\n case BUTTON_TYPE.reset:\n clearDocument();\n break;\n case BUTTON_TYPE.print:\n print();\n break;\n //case BUTTON_TYPE.download:\n // download();\n // break;\n case BUTTON_TYPE.link:\n redirect();\n break;\n case BUTTON_TYPE.popup:\n default:\n closeModal();\n break;\n }\n } else {\n updateIsSubmitting(false);\n }\n };\n\n // submit document to new status\n const changeStatus = () => {\n submitFunc(true, cId);\n closeModal();\n };\n\n // reset all field values\n const clearDocument = () => {\n clearFunc();\n closeModal();\n };\n\n // start print\n const print = () => {\n setStartPrint(true);\n closeModal();\n };\n\n // stop print\n const resetPrint = () => {\n setStartPrint(false);\n setLoading(false);\n };\n\n // download as file\n const download = async (templateName, fileType) => {\n if (templateName && fileType) {\n setLoading(true);\n const fileUrl = await documentApi.downloadAs(\n documentID,\n templateName,\n fileType\n );\n\n if (fileUrl) {\n // open to save file\n Utils.openInNewTab(fileUrl);\n setLoading(false);\n }\n }\n };\n\n // redirect\n const redirect = async () => {\n await closeModal();\n\n if (\n btnKey.indexOf('https://') === 0 ||\n btnKey.indexOf('http://') === 0 ||\n btnKey.indexOf('/') === 0\n ) {\n if (filterSelection) {\n const selectedFilters = Utils.mapDataToFilters(formData);\n\n const res = await userFilterApi.putMany(selectedFilters);\n\n if (res.status === 204) {\n // separate backend filters and frontend filters\n const filters = _.filter(\n currentUser.filters,\n f => !_.some(selectedFilters, sf => sf.key === f.key)\n );\n\n updateCurrentUser({\n ...currentUser,\n filters,\n selectedFilters,\n });\n }\n }\n\n // redirect\n if (filterSelection) {\n history.push(btnKey);\n } else {\n // delay redirect to wait for end of execution\n setTimeout(() => (window.location.href = btnKey), 1000);\n }\n } else {\n toast.error( );\n }\n };\n\n const btnProps = {\n name: btnName,\n primary: true,\n color: Utils.getColor(clickable.color),\n icon: clickable.icon,\n iconColor: Utils.getColor(clickable.iconColor),\n disabled:\n formData === undefined || loading || isValidForm ? true : undefined,\n type: btnType === BUTTON_TYPE.status ? 'submit' : 'button',\n form: btnType === BUTTON_TYPE.status ? 'renderedDocument' : undefined,\n onClick: submitFunc ? showModal : null,\n };\n\n if (_.includes([BUTTON_TYPE.print], btnType)) {\n btnProps.documentID = documentID;\n btnProps.printNow = startPrint;\n btnProps.onPrint = resetPrint;\n btnProps.selectedTemplate = selectedTemplate;\n } else if (_.includes([BUTTON_TYPE.download], btnType)) {\n btnProps.onDownload = download;\n }\n\n // render\n return _.includes([BUTTON_TYPE.print], btnType) ? (\n \n ) : _.includes([BUTTON_TYPE.download], btnType) ? (\n \n ) : (\n \n );\n};\n\nDocumentButtonContainer.propTypes = {\n t: func.isRequired,\n clickable: object,\n popupAction: object,\n formData: object,\n requiredFields: arrayOf(object),\n patternFields: arrayOf(object),\n filterSelection: bool,\n isValidForm: bool,\n clearFunc: func,\n submitFunc: func,\n};\n\nDocumentButtonContainer.defaultProps = {\n filterSelection: false,\n};\n\nconst mapStateToProps = state => ({\n currentUser: getCurrentUser(state),\n templates: getTemplates(state),\n});\n\nconst mapDispatchToProps = dispatch => ({\n updateCurrentUser: user => dispatch(AuthCreators.updateCurrentUser(user)),\n\n updateTemplate: (templateId, field, value) =>\n dispatch(TemplateCreators.updateTemplate(templateId, field, value)),\n\n closeModal: () => dispatch(ModalCreators.closeModal()),\n openModal: (modalType, options) =>\n dispatch(ModalCreators.openModal(modalType, options)),\n changeSize: size => dispatch(ModalCreators.changeSize(size)),\n updateIsSubmitting: isSubmitting =>\n dispatch(ModalCreators.updateIsSubmitting(isSubmitting)),\n});\n\nexport default withRouter(\n connect(\n mapStateToProps,\n mapDispatchToProps\n )(withTranslation()(DocumentButtonContainer))\n);\n","import React from 'react';\nimport { connect } from 'react-redux';\nimport { Button, Container } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nimport Utils from 'core/utils/utils';\nimport { BUTTON_TYPE } from 'core/utils/constant';\n\nimport DocumentButton from './documentButtonContainer';\n\n// Fix error in Semantic UI, margin is defined in em unit\n// Then does not apply on display: flex element such as button group\nconst StyledContainer = styled(Container)`\n &&& {\n .ui.buttons {\n margin-right: 3.5px;\n }\n }\n`;\n\nconst DocumentButtonGroup = ({\n clickables,\n viewersWarning,\n isValidForm,\n submitFunc,\n clearFunc,\n documentID,\n status,\n formData,\n requiredFields,\n patternFields,\n filterSelection,\n externalPrint,\n printable,\n printed,\n print,\n selectedTemplate,\n}) => (\n \n {clickables &&\n Utils.getClickablesByStatus(clickables, status)\n .sort(function(a, b) {\n if (a.type > b.type) {\n return -1;\n } else if (a.type < b.type) {\n return 1;\n } else {\n return a.name > b.name ? 1 : -1;\n }\n })\n .map(c =>\n !(externalPrint && [BUTTON_TYPE.print].includes(c.type)) ||\n [BUTTON_TYPE.link].includes(c.type) ? (\n \n ) : (\n \n \n {c.name}\n \n \n )\n )}\n \n);\n\nexport default connect(\n state => state.settings,\n null\n)(DocumentButtonGroup);\n","import React, { useState, useRef } from 'react';\nimport { Button } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nimport { Tooltip } from 'components';\nimport ThemedPopup from '../theme/ThemedPopup';\n\nconst isIconCircularPrimaryInverted = ({ icon, circular, primary, inverted }) =>\n icon && circular && primary && inverted;\n\nconst InlineBlock = styled.div`\n display: inline-block;\n`;\n\nconst StyledButton = styled(Button)`\n ${({\n theme: {\n color: { primary, headerItemBgHover },\n },\n ...props\n }) => `\n &&&&& {\n ${isIconCircularPrimaryInverted(props) &&\n `\n color: ${primary};\n background: transparent;\n box-shadow: none !important;\n\n &:focus,\n &:hover {\n background: ${headerItemBgHover}\n }\n `}\n }\n `}\n`;\n\nconst Popuptrigger = ({ buttonProps, popupProps, tooltipProps }) => {\n const context = useRef();\n const triggerRef = useRef();\n const pendingLeave = useRef(false);\n const [open, setOpen] = useState(false);\n\n const toggle = () => setOpen(!open);\n\n const cancelPendingLeave = () => {\n pendingLeave.current = false;\n };\n\n const handleClose = (e, data) => {\n cancelPendingLeave();\n setOpen(false);\n triggerRef.current.ref.current.blur();\n };\n\n const handleEnter = e => {\n cancelPendingLeave();\n };\n\n const handleLeave = e => {\n pendingLeave.current = true;\n\n setTimeout(() => {\n if (pendingLeave.current) {\n handleClose(e);\n }\n }, 400);\n };\n\n const ButtonContainer = ({ children }) =>\n tooltipProps ? (\n {children} \n ) : (\n <>{children}>\n );\n\n return (\n <>\n \n \n \n \n \n \n >\n );\n};\n\nexport default Popuptrigger;\n","import React from 'react';\nimport { Responsive } from 'semantic-ui-react';\nimport { ThemedButton } from 'components';\n\nconst ResponsiveButtonCore = ({ children, ...props }) => {\n // render\n return (\n <>\n \n {children}\n \n \n {children}\n \n >\n );\n};\n\nexport default ResponsiveButtonCore;\n","import { Button } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nconst getSubtleStyle = theme => {\n const {\n color: { buttonFg, buttonFgHover, headerItemBgHover },\n } = theme;\n\n return `\n color: ${buttonFg} !important;\n background: none !important;\n\n &:hover {\n color: ${buttonFgHover} !important;\n background-color: ${headerItemBgHover} !important;\n }\n `;\n};\n\nconst SubtleIconButton = styled(Button).attrs(({ icon }) => ({\n basic: true,\n icon,\n}))`\n ${({ theme }) => `\n &.ui.basic.button {\n box-shadow: none;\n vertical-align: middle;\n ${getSubtleStyle(theme)}\n `}\n`;\n\nexport { getSubtleStyle };\nexport default SubtleIconButton;\n","import React from 'react';\nimport { Form, Input, Table } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nimport { FIELD_TYPE } from 'core/utils/constant';\nimport { InputSearch, ThemedInput } from 'components';\n\nconst FilterTableCellInput = ({\n t,\n advanced,\n columns,\n fieldID,\n operator,\n value,\n handleChangeValue,\n}) => (\n \n {columns.some(c => `${c.fieldID}` === fieldID) && (\n `${c.fieldID}` === fieldID)}\n disabled={\n (!advanced && (!fieldID ? true : undefined)) ||\n (advanced && (!operator || operator < 0 ? true : undefined))\n }\n operator={operator}\n controlled\n defaultValue={value ? value : ''}\n levelFilter=\"advanced\"\n handleValue={handleChangeValue}\n singleChoice={!advanced}\n />\n )}\n {!fieldID && (\n \n )}\n \n);\n\nconst SmallInput = styled(Input)`\n ${({\n theme: {\n color: { fg, inputFg, inputFgHover, inputBg, borderColor },\n },\n }) => `\n &.ui.input {\n max-width: 70px;\n\n background-color: ${inputBg};\n color: ${inputFg};\n border-color: ${borderColor};\n\n &:hover {\n background-color: ${inputBg};\n color: ${inputFgHover};\n }\n\n input {\n background-color: ${inputBg};\n color: ${inputFg};\n border-color: ${borderColor};\n }\n\n + i {\n color: ${fg};\n }\n }\n `}\n`;\n\nconst FilterTableCellInputNumber = ({ value, onChange }) => (\n \n \n \n \n \n);\n\nexport { FilterTableCellInput, FilterTableCellInputNumber };\n","import React from 'react';\nimport { Table } from 'semantic-ui-react';\nimport { ThemedButton } from 'components';\n\nconst FilterTableCellButton = ({ icon, onClick, disabled }) => (\n \n \n \n);\nexport default FilterTableCellButton;\n","import React from 'react';\nimport { withTranslation } from 'react-i18next';\n\nimport { OPERATOR, FIELD_TYPE } from 'core/utils/constant';\nimport { FasterDropdown } from 'components';\n\nconst {\n decimal,\n number,\n text,\n checkbox,\n combolist,\n editabledropdown,\n searchselect,\n searcheditselect,\n multiselect,\n textarea,\n time,\n date,\n datetime,\n autocomplete,\n} = FIELD_TYPE;\n\nconst Operators = [\n {\n text: 'Contains',\n value: OPERATOR.contains,\n types: [decimal, number, text, textarea, autocomplete],\n },\n {\n text: 'Does not contain',\n value: OPERATOR.notContains,\n types: [decimal, number, text, textarea, autocomplete],\n },\n {\n text: 'Equals',\n value: OPERATOR.equals,\n types: [\n checkbox,\n combolist,\n editabledropdown,\n searchselect,\n searcheditselect,\n multiselect,\n decimal,\n number,\n text,\n textarea,\n autocomplete,\n ],\n },\n {\n text: 'Does not equal',\n value: OPERATOR.notEquals,\n types: [\n checkbox,\n combolist,\n editabledropdown,\n searchselect,\n searcheditselect,\n multiselect,\n decimal,\n number,\n text,\n textarea,\n autocomplete,\n ],\n },\n {\n text: 'Between',\n value: OPERATOR.between,\n types: [date, datetime, time, decimal, number],\n },\n {\n text: 'Starts with',\n value: OPERATOR.startsWith,\n types: [decimal, number, text, textarea, autocomplete],\n },\n {\n text: 'Ends with',\n value: OPERATOR.endsWith,\n types: [decimal, number, text, textarea, autocomplete],\n },\n];\n\nconst FilterTableOperatorSelect = ({\n t,\n disabled,\n columnType,\n operator,\n handleChangeOperator,\n}) => (\n o.types.some(ot => ot === columnType))\n ? Operators.filter(o => o.types.some(ot => ot === columnType)).map(\n ({ text, value }) => ({ key: value, text: t(`${text}`), value })\n )\n : []\n }\n onChange={handleChangeOperator}\n />\n);\n\nexport default withTranslation()(FilterTableOperatorSelect);\n","import React from 'react';\nimport { Table } from 'semantic-ui-react';\n\nimport { FasterDropdown } from 'components';\n\nimport FilterTableOperatorSelect from '../operator-select/FilterTableOperatorSelect';\n\nconst FilterTableCellSelect = ({ disabled, options, value, onChange }) => (\n \n \n \n);\n\nconst FilterTableCellOperatorSelect = ({\n advanced,\n columns,\n fieldID,\n operator,\n handleChangeOperator,\n}) =>\n advanced ? (\n \n fieldID === `${c.fieldID}`)\n ? columns.find(c => fieldID === `${c.fieldID}`).type\n : undefined\n }\n handleChangeOperator={handleChangeOperator}\n />\n \n ) : null;\n\nexport { FilterTableCellSelect, FilterTableCellOperatorSelect };\n","import React from 'react';\nimport { Table } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nimport { ThemedHeaderCellHeader } from 'components';\n\nconst StyledHeaderCellFilter = styled(ThemedHeaderCellHeader).attrs({\n withFilter: true,\n})``;\n\nconst FilterTableHeader = ({ t, advanced }) => (\n \n \n {t('Template')} \n {t('Section')} \n {t('Field')} \n {advanced && }\n {t('Value')} \n \n \n \n);\n\nconst GridFilterTableHeader = ({ t, advanced }) => (\n \n \n {t('Position')} \n {t('Template')} \n {t('Section')} \n {t('Field')} \n {advanced && }\n {t('Value')} \n \n \n \n);\n\nexport { FilterTableHeader, GridFilterTableHeader };\n","import React from 'react';\nimport { Table } from 'semantic-ui-react';\n\nimport { ButtonLink, ThemedTableFooter } from 'components';\n\nconst FilterTableFooter = ({ t, options, handleClickFunc }) => (\n \n \n \n {options.length > 0 && (\n \n )}\n \n \n \n);\n\nexport default FilterTableFooter;\n","import React from 'react';\nimport { withTranslation } from 'react-i18next';\nimport { Table } from 'semantic-ui-react';\nimport _ from 'lodash';\n\nimport { FilterTableCellInput } from './components/cell/FilterTableCellInput';\nimport FilterTableCellButton from './components/cell/FilterTableCellButton';\nimport {\n FilterTableCellSelect,\n FilterTableCellOperatorSelect,\n} from './components/cell/FilterTableCellSelect';\nimport { FilterTableHeader } from './components/layout/FilterTableHeader';\nimport FilterTableFooter from './components/layout/FilterTableFooter';\nimport { ThemedTable } from 'components';\n\nconst FilterTable = ({\n advanced,\n filters,\n templateOptions,\n sectionOptions,\n columnOptions,\n columns,\n activeFilter,\n handleAddFilter,\n handleRemoveFilter,\n handleRowClick,\n handleChangeTemplate,\n handleChangeSection,\n handleChangeColumn,\n handleChangeOperator,\n handleChangeValue,\n t,\n}) => (\n \n \n \n {filters.length > 0 &&\n filters\n .sort((f1, f2) => f1.position - f2.position)\n .map(({ templateId, sectionID, columnID, operator, value }) => {\n const keyColumns = [templateId, sectionID, columnID];\n\n return (\n \n \n handleChangeTemplate(keyColumns, e, data)\n }\n />\n so.temp === templateId)}\n value={\n sectionOptions.findIndex(\n so => so.temp === templateId && so.value === sectionID\n ) >= 0\n ? sectionID\n : ''\n }\n onChange={(e, data) =>\n handleChangeSection(keyColumns, e, data)\n }\n />\n co.temp === templateId && co.sect === sectionID\n )}\n value={\n columnOptions.findIndex(\n co =>\n co.temp === templateId &&\n co.sect === sectionID &&\n co.value === columnID\n ) > 0\n ? columnID\n : ''\n }\n onChange={(e, data) =>\n handleChangeColumn(keyColumns, e, data)\n }\n />\n \n handleChangeOperator(keyColumns, e, data)\n }\n />\n \n handleChangeValue(keyColumns, e, data)\n }\n />\n handleRemoveFilter(keyColumns)}\n />\n \n );\n })}\n \n \n \n);\n\nexport default withTranslation()(FilterTable);\n","const equals = (filter, activeFilter, equalPositions) => {\n return (\n `${filter.templateId}` === activeFilter[0] &&\n `${filter.sectionID}` === activeFilter[1] &&\n `${filter.columnID}` === activeFilter[2] &&\n (equalPositions ? filter.columnPosition === activeFilter[3] : true)\n );\n};\n\nexport default equals;\n","import equals from './equals';\n\nconst getFixedFiltersBatch = (filters, activeFilter) =>\n filters.filter(f => !equals(f, activeFilter));\n\nconst getFixedFiltersGrid = (filters, activeFilter) =>\n filters.filter(f => !equals(f, activeFilter, true));\n\nexport { getFixedFiltersBatch, getFixedFiltersGrid };\n","import equals from './equals';\n\nconst getFixedFilterPropsBatch = (filters, activeFilter) =>\n filters.find(f => equals(f, activeFilter));\n\nconst getFixedFilterPropsGrid = (filters, activeFilter) =>\n filters.find(f => equals(f, activeFilter, true));\n\nexport { getFixedFilterPropsBatch, getFixedFilterPropsGrid };\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport { withRouter } from 'react-router-dom';\nimport { connect } from 'react-redux';\nimport _ from 'lodash';\n\nimport { getTemplates } from 'core/template/templateReducer';\nimport { getTemplateContents } from 'core/utils/form';\n\nimport FilterTable from './components/table/FilterTable';\nimport { getFixedFiltersBatch } from './helpers/fixed-filters';\nimport { getFixedFilterPropsBatch } from './helpers/fixed-filter-props';\n\nconst emptyFilter = {\n templateId: '',\n sectionID: '',\n position: Number.MAX_SAFE_INTEGER,\n columnID: '',\n column: undefined,\n value: '',\n};\n\nclass Filter extends Component {\n state = {\n templateOptions: [],\n sectionOptions: [],\n columnOptions: [],\n columns: [],\n };\n\n async componentDidMount() {\n const { filters, templates, handleReloadColOpts } = this.props;\n\n // load available fields from redux-stored templates\n const templateOptions = [];\n const sectionOptions = [];\n const columnOptions = [];\n const columns = [];\n\n templates.forEach(t => {\n templateOptions.push({\n reference: t.key,\n key: `${t.templateId}`,\n value: `${t.templateId}`,\n text: t.name,\n });\n _.filter(getTemplateContents(t), ct => ct.sectionID >= 0).forEach(s => {\n sectionOptions.push({\n temp: `${t.templateId}`,\n reference: s.key,\n key: `${s.sectionID}`,\n value: `${s.sectionID}`,\n text: s.name,\n });\n s.fields.forEach(f => {\n columnOptions.push({\n temp: `${t.templateId}`,\n sect: `${s.sectionID}`,\n reference: f.key,\n key: `${f.fieldID}`,\n value: `${f.fieldID}`,\n text: f.name,\n disabled: filters.some(fltr => fltr.columnID === f.fieldID),\n });\n columns.push(f);\n });\n });\n });\n\n this.setState({ templateOptions, sectionOptions, columnOptions, columns });\n\n if (handleReloadColOpts) {\n handleReloadColOpts(this.reloadColOptions);\n }\n }\n\n handleAddFilter = () => {\n const { advanced, filters, callbackFunc } = this.props;\n const { templateOptions } = this.state;\n\n if (\n !filters.some(f => !f.columnID || (!f.operator && advanced)) &&\n templateOptions.length > 0\n ) {\n // compute new position\n const pos = !_.isEmpty(filters)\n ? _.maxBy(filters, 'position').position + 1\n : 1;\n\n // update state\n callbackFunc(filters.concat({ ...emptyFilter, position: pos }));\n }\n };\n\n handleRemoveFilter = filter => {\n const { filters, callbackFunc } = this.props;\n const { columnOptions } = this.state;\n\n // new options\n const colOpts = columnOptions.some(o => o.value === filter[2])\n ? [\n ...columnOptions.filter(o => o.value !== filter[2]),\n ...columnOptions\n .filter(o => o.value === filter[2])\n .map(o => ({ ...o, disabled: false })), // enable old option\n ]\n : [...columnOptions];\n\n // update state\n this.setState({\n // disable selected option\n columnOptions: colOpts,\n });\n\n // update state\n callbackFunc(getFixedFiltersBatch(filters, filter));\n };\n\n // set active row\n handleRowClick = activeFilter => () => {\n this.setState({ activeFilter });\n };\n\n handleChangeColumn = (filter, e, data) => {\n const { value } = data ? data : e.target;\n const { columnOptions, columns } = this.state;\n\n // new options\n const newColumnOptions = columnOptions.some(o => o.value === filter[2])\n ? [\n ...columnOptions.filter(\n o => o.value !== value && o.value !== filter[2]\n ),\n ...columnOptions\n .filter(o => o.value === value)\n .map(o => ({ ...o, disabled: true })), // disable selected option\n ...columnOptions\n .filter(o => o.value === filter[2])\n .map(o => ({ ...o, disabled: false })), // enable old option\n ]\n : [\n ...columnOptions.filter(o => o.value !== value),\n ...columnOptions\n .filter(o => o.value === value)\n .map(o => ({ ...o, disabled: true })), // disable selected option\n ];\n\n const newActiveFilter = [...filter];\n newActiveFilter[2] = value;\n\n // update state\n this.setState({\n columnOptions: newColumnOptions, // disable selected option\n activeFilter: newActiveFilter, // set active row\n });\n\n this.handleChangeAttr(\n 'columnID',\n ['operator', 'value'],\n [['column', columns.find(c => `${c.fieldID}` === value)]]\n )(filter, e, data);\n };\n\n handleChangeAttr = (attr, attrReset, attrCustom) => (filter, e, data) => {\n const { value } = data ? data : e.target;\n const { filters, callbackFunc } = this.props;\n\n this.setState({ activeFilter: filter });\n\n const attrResets = _.reduce(\n attrReset,\n (acc, elem) => {\n acc[elem] = undefined;\n return acc;\n },\n {}\n );\n\n const attrCustoms = _.reduce(\n attrCustom,\n (acc, elem) => {\n acc[elem[0]] = elem[1];\n return acc;\n },\n {}\n );\n\n // update state\n callbackFunc([\n // leave unaffected filters unchanged\n ...getFixedFiltersBatch(filters, filter),\n {\n // leave all properties unchanged first\n ...getFixedFilterPropsBatch(filters, filter),\n // then update desired property\n [attr]: value,\n ...attrResets,\n ...attrCustoms,\n },\n ]);\n };\n\n reloadColOptions = filters => {\n const { columnOptions } = this.state;\n\n // first enable all the options\n let colOpts = columnOptions.map(o => ({ ...o, disabled: false }));\n\n // then disable the option which is in new filters\n filters.forEach(f => {\n colOpts = [\n ...colOpts.filter(o => o.value !== `${f.columnID}`),\n ...colOpts\n .filter(o => o.value === `${f.columnID}`)\n .map(o => ({ ...o, disabled: true })), // disable selected option\n ];\n });\n\n this.setState({ columnOptions: colOpts });\n };\n\n render() {\n const { filters, advanced } = this.props;\n const {\n templateOptions,\n sectionOptions,\n columnOptions,\n columns,\n activeFilter,\n } = this.state;\n\n return (\n \n );\n }\n}\n\nFilter.propTypes = {\n filters: PropTypes.arrayOf(PropTypes.object).isRequired,\n advanced: PropTypes.bool,\n callbackFunc: PropTypes.func.isRequired,\n handleReloadColOpts: PropTypes.func.isRequired,\n templates: PropTypes.arrayOf(PropTypes.object).isRequired,\n};\n\nFilter.defaultProps = {\n advanced: false,\n};\n\nconst mapStateToProps = state => ({\n templates: getTemplates(state),\n});\n\nconst mapDispatchToProps = null;\n\nexport default withRouter(\n connect(\n mapStateToProps,\n mapDispatchToProps\n )(Filter)\n);\n","import React from 'react';\nimport { withTranslation } from 'react-i18next';\nimport { Table } from 'semantic-ui-react';\n\nimport Utils from 'core/utils/utils';\nimport { ThemedTable, ScrollableTable } from 'components';\n\nimport {\n FilterTableCellInput,\n FilterTableCellInputNumber,\n} from './components/cell/FilterTableCellInput';\nimport FilterTableCellButton from './components/cell/FilterTableCellButton';\nimport {\n FilterTableCellSelect,\n FilterTableCellOperatorSelect,\n} from './components/cell/FilterTableCellSelect';\nimport { GridFilterTableHeader } from './components/layout/FilterTableHeader';\nimport FilterTableFooter from './components/layout/FilterTableFooter';\n\nconst FilterTable = ({\n advanced,\n filters,\n templateOptions,\n sectionOptions,\n columnOptions,\n columns,\n activeFilter,\n handleAddFilter,\n handleRemoveFilter,\n handleRowClick,\n handleChangePosition,\n handleChangeTemplate,\n handleChangeSection,\n handleChangeColumn,\n handleChangeOperator,\n handleChangeValue,\n t,\n}) => (\n \n \n \n \n {filters.length > 0 &&\n Utils.sortFieldWithFalsey(filters, 'columnPosition').map(\n ({\n columnPosition,\n templateId,\n sectionID,\n columnID,\n operator,\n value,\n }) => {\n const keyColumns = [\n templateId,\n sectionID,\n columnID,\n columnPosition,\n ];\n return (\n \n \n \n so.temp === templateId\n )}\n value={sectionID}\n onChange={handleChangeSection}\n />\n = 0 ? undefined : true}\n options={columnOptions.filter(\n co => co.temp === templateId && co.sect === sectionID\n )}\n value={columnID}\n onChange={handleChangeColumn}\n />\n \n \n \n \n );\n }\n )}\n \n \n \n \n);\n\nexport default withTranslation()(FilterTable);\n","import React, { Component } from 'react';\nimport { arrayOf, object, bool, func } from 'prop-types';\nimport { withRouter } from 'react-router-dom';\nimport { connect } from 'react-redux';\nimport _ from 'lodash';\n\nimport { getTemplates } from 'core/template/templateReducer';\nimport { getTemplateContents } from 'core/utils/form';\n\nimport GridFilterTable from './components/table/GridFilterTable';\nimport { getFixedFiltersGrid } from './helpers/fixed-filters';\nimport { getFixedFilterPropsGrid } from './helpers/fixed-filter-props';\n\nconst emptyFilter = {\n position: Number.MAX_SAFE_INTEGER,\n columnID: -1,\n column: undefined,\n value: '',\n};\n\nclass GridFilter extends Component {\n state = {\n templateOptions: [],\n sectionOptions: [],\n columnOptions: [],\n columns: [],\n };\n\n async componentDidMount() {\n const { filters, templates, handleReloadColOpts } = this.props;\n\n // load available fields from redux-stored templates\n const templateOptions = [];\n const sectionOptions = [];\n const columnOptions = [];\n const columns = [];\n\n templates.forEach(t => {\n templateOptions.push({\n reference: t.key,\n value: t.templateId,\n text: t.name,\n });\n _.filter(getTemplateContents(t), ct => ct.sectionID >= 0).forEach(s => {\n sectionOptions.push({\n temp: t.templateId,\n reference: s.key,\n value: s.sectionID,\n text: s.name,\n });\n s.fields.forEach(f => {\n columnOptions.push({\n temp: t.templateId,\n sect: s.sectionID,\n reference: f.key,\n value: f.fieldID,\n text: f.name,\n disabled: filters.some(fltr => fltr.columnID === f.fieldID),\n });\n columns.push(f);\n });\n });\n });\n\n this.setState({ templateOptions, sectionOptions, columnOptions, columns });\n\n if (handleReloadColOpts) {\n handleReloadColOpts(this.reloadColOptions);\n }\n }\n\n handleAddFilter = () => {\n const { advanced, filters, callbackFunc } = this.props;\n const { templateOptions } = this.state;\n\n // check available for filter adding\n // + check if column filling\n // + check if filter filling\n const isAvailable = f =>\n f.columnID === -1 || (!f.operator && advanced && f.columnPosition === '');\n\n if (!filters.some(f => isAvailable(f)) && templateOptions.length > 0) {\n // compute new position\n const position = !_.isEmpty(filters)\n ? _.maxBy(filters, 'position').position + 1\n : 1;\n\n // update state\n callbackFunc(filters.concat({ ...emptyFilter, position }));\n }\n };\n\n handleRemoveFilter = () => {\n const { filters, callbackFunc } = this.props;\n const { activeFilter, columnOptions } = this.state;\n\n // new options\n const colOpts = columnOptions.some(o => o.value === activeFilter[2])\n ? [\n ...columnOptions.filter(o => o.value !== activeFilter[2]),\n ...columnOptions\n .filter(o => o.value === activeFilter[2])\n .map(o => ({ ...o, disabled: false })), // enable old option\n ]\n : [...columnOptions];\n\n // update state\n this.setState({\n // disable selected option\n columnOptions: colOpts,\n });\n\n // update state\n callbackFunc(getFixedFiltersGrid(filters, activeFilter));\n };\n\n // set active row\n handleRowClick = activeFilter => () => {\n this.setState({ activeFilter });\n };\n\n handleChangePosition = (e, data) => {\n // console.log(name, value);\n // this.setState({ [name]: value });\n // if (e.target.value) {\n // const { table, columnOptions, activeColumn } = this.state;\n // const { columns } = table;\n // const column = columns.find(\n // c => [c.position, c.columnID] === activeColumn\n // );\n // if (column && column.position !== undefined) {\n // column.position = +e.target.value;\n // if (column.position < 0) {\n // // remove field\n // columns.splice(columns.indexOf(column), 1);\n // // enable again in list field option\n // if (column.columnID > 0) {\n // columnOptions.find(\n // o => o.value === column.columnID\n // ).disabled = false;\n // }\n // }\n // const newTable = { ...table, columns };\n // this.setState({\n // table: newTable,\n // activeColumn: activeColumn,\n // });\n // } else {\n // console.log(e.target.value);\n // }\n // }\n };\n\n handleChangeColumn = (e, data) => {\n const { activeFilter, columnOptions, columns } = this.state;\n\n // new options\n const newColumnOptions = columnOptions.some(\n o => o.value === activeFilter[2]\n )\n ? [\n ...columnOptions.filter(\n o => o.value !== data.value && o.value !== activeFilter[2]\n ),\n ...columnOptions\n .filter(o => o.value === data.value)\n .map(o => ({ ...o, disabled: true })), // disable selected option\n ...columnOptions\n .filter(o => o.value === activeFilter[2])\n .map(o => ({ ...o, disabled: false })), // enable old option\n ]\n : [\n ...columnOptions.filter(o => o.value !== data.value),\n ...columnOptions\n .filter(o => o.value === data.value)\n .map(o => ({ ...o, disabled: true })), // disable selected option\n ];\n\n const newActiveFilter = [...activeFilter];\n newActiveFilter[2] = data.value;\n\n // update state\n this.setState({\n columnOptions: newColumnOptions, // disable selected option\n activeFilter: newActiveFilter, // set active row\n });\n\n this.handleChangeAttr(\n 'columnID',\n ['operator', 'value'],\n [['column', columns.find(c => c.fieldID === data.value)]]\n )(e, data);\n };\n\n handleChangeAttr = (attr, attrReset, attrCustom) => (e, { value }) => {\n const { filters, callbackFunc } = this.props;\n const { activeFilter } = this.state;\n\n const attrResets = _.reduce(\n attrReset,\n (acc, elem) => {\n acc[elem] = undefined;\n return acc;\n },\n {}\n );\n\n const attrCustoms = _.reduce(\n attrCustom,\n (acc, elem) => {\n acc[elem[0]] = elem[1];\n return acc;\n },\n {}\n );\n\n // update state\n callbackFunc([\n // leave unaffected filters unchanged\n ...getFixedFiltersGrid(filters, activeFilter),\n {\n // leave all properties unchanged first\n ...getFixedFilterPropsGrid(filters, activeFilter),\n // then update desired property\n [attr]: value,\n ...attrResets,\n ...attrCustoms,\n },\n ]);\n };\n\n reloadColOptions = filters => {\n const { columnOptions } = this.state;\n\n // first enable all the options\n let colOpts = columnOptions.map(o => ({ ...o, disabled: false }));\n\n // then disable the option which is in new filters\n filters.forEach(f => {\n colOpts = [\n ...colOpts.filter(o => o.value !== f.columnID),\n ...colOpts\n .filter(o => o.value === f.columnID)\n .map(o => ({ ...o, disabled: true })), // disable selected option\n ];\n });\n\n this.setState({ columnOptions: colOpts });\n };\n\n render() {\n const { filters, advanced } = this.props;\n const {\n templateOptions,\n sectionOptions,\n columnOptions,\n columns,\n activeFilter,\n } = this.state;\n\n return (\n \n );\n }\n}\n\nGridFilter.propTypes = {\n filters: arrayOf(object).isRequired,\n advanced: bool,\n callbackFunc: func.isRequired,\n handleReloadColOpts: func.isRequired,\n templates: arrayOf(object).isRequired,\n};\n\nGridFilter.defaultProps = {\n advanced: false,\n};\n\nconst mapStateToProps = state => ({\n templates: getTemplates(state),\n});\n\nconst mapDispatchToProps = null;\n\nexport default withRouter(\n connect(\n mapStateToProps,\n mapDispatchToProps\n )(GridFilter)\n);\n","import React from 'react';\nimport styled from 'styled-components';\nimport { ContextMenu as ReactContextMenu, MenuItem } from 'react-contextmenu';\nimport { Menu, Icon } from 'semantic-ui-react';\nimport _ from 'lodash';\n\nconst StyledContextMenu = styled(ReactContextMenu)`\n ${({\n theme: {\n color: { menuItemBgDisabled, menuItemFgDisabled },\n },\n }) => `\n z-index: 99;\n min-width: 250px;\n\n & .react-contextmenu-item--disabled {\n background-color: ${menuItemBgDisabled};\n\n > div.link.item {\n color: ${menuItemFgDisabled};\n }\n }\n `}\n`;\n\nconst ContextMenu = ({ id, menu, handleOnShow, handleClick }) => (\n \n
\n {!_.isEmpty(menu) &&\n menu.map(({ disabled, icon, title, data, onClick }, index) => (\n handleClick(dataMerged, onClick)}\n key={index}\n >\n \n {icon && }\n {title}\n \n \n ))}\n \n \n);\n\nexport default ContextMenu;\n","import React from 'react';\nimport { connect } from 'react-redux';\nimport _ from 'lodash';\n\nimport ContextMenu from './ContextMenu';\nimport {\n // getContextMenuItems,\n getContextMenus,\n} from 'core/context-menu/contextMenuReducer';\nimport { MENU_IDS } from 'core/utils/constant';\n\nconst ContextMenuContainer = ({ menus }) => {\n const handleClick = (dataMerged, onClick) => {\n onClick(dataMerged.action, dataMerged.info);\n };\n\n const handleOnShow = event => {\n const { callbackOnShow } = event.detail.data;\n\n if (callbackOnShow) {\n callbackOnShow();\n }\n };\n\n return _.map(MENU_IDS, id => {\n const menu = _.find(menus, { id });\n return (\n menu && (\n \n )\n );\n });\n};\n\nconst mapStateToProps = state => ({\n // menuItems: getContextMenuItems(state),\n menus: getContextMenus(state),\n});\n\nconst mapDispatchToProps = null;\n\nexport default connect(\n mapStateToProps,\n mapDispatchToProps\n)(ContextMenuContainer);\n","import React from 'react';\nimport { ContextMenuTrigger as ReactContextMenuTrigger } from 'react-contextmenu';\n\n// takes props as input and returns the data to be passed to contextmenu.\nconst collect = ({ info, callbackOnShow }) => ({ info, callbackOnShow });\n\nconst ContextMenuTrigger = ({ id, children, ...rest }) => (\n {\n e.stopPropagation();\n }}\n {...rest}\n >\n {children}\n \n);\n\nexport default ContextMenuTrigger;\n","import React from 'react';\nimport { string, func, bool, node } from 'prop-types';\nimport { Modal } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nconst StyledModal = styled(Modal)`\n && {\n background: none;\n }\n`;\n\nconst ModalContent = styled(Modal.Content)`\n ${({\n theme: {\n color: { fg, modalBg },\n },\n }) => `\n &&& {\n color: ${fg};\n background-color: ${modalBg};\n }\n `}\n`;\n\nconst ActionModal = ({ open, onClose, children, size }) => (\n \n {children} \n \n);\n\nActionModal.propTypes = {\n size: string,\n onClose: func.isRequired,\n open: bool.isRequired,\n children: node,\n};\n\nActionModal.defaultProps = {\n size: 'small',\n children: null,\n};\n\nexport default ActionModal;\n","import React, { useEffect } from 'react';\nimport { connect } from 'react-redux';\nimport { Link } from 'react-router-dom';\nimport { withTranslation } from 'react-i18next';\nimport { Header, Icon } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nimport { getIsSubmitting, ModalCreators } from 'core/modal/modalReducer';\nimport { MODAL_TYPE } from 'core/utils/constant';\nimport { ThemedButton, ThemedLabel } from 'components';\n\nconst Container = styled.div``;\n\nconst StyledHeader = styled(Header.Content)`\n ${({\n theme: {\n color: { fg },\n },\n }) => `\n && {\n &.content {\n color: ${fg};\n width: 100%;\n }\n }\n `}\n`;\n\nconst StyledSubheader = styled(Header.Subheader)`\n ${({\n theme: {\n color: { popupFg },\n },\n }) => `\n &&& {\n &&.sub.header {\n color: ${popupFg};\n }\n }\n `}\n`;\n\nconst Content = styled.div`\n display: block;\n width: 100%;\n font-size: 1em;\n line-height: 1.4;\n`;\n\nconst ButtonToolbar = styled.div`\n margin-top: 1em;\n text-align: right;\n`;\n\nconst PrimaryButton = ({\n btnTo,\n onBtnClick,\n btnTitle,\n popupInputs,\n disabled,\n}) =>\n btnTo ? (\n \n {btnTitle}\n \n ) : popupInputs ? (\n \n {btnTitle}\n \n ) : (\n \n {btnTitle}\n \n );\n\nconst SecondaryButton = ({\n secondaryBtnTo,\n onSecondaryBtnClick,\n secondaryBtnTitle,\n disabled,\n}) =>\n secondaryBtnTo ? (\n \n {secondaryBtnTitle}\n \n ) : (\n \n {secondaryBtnTitle}\n \n );\n\nconst PopupTemplateHeader = ({ t, type, modalType, title, children }) => (\n \n {!['popup-inputs-clean', 'form-action'].includes(modalType) && (\n \n )}\n \n {!['popup-inputs-clean', 'form-action'].includes(modalType)\n ? `${t(`common|${type}`)} - ${title}`\n : title}\n {children} \n \n \n);\n\nconst PopupTemplate = ({\n t,\n title,\n btnTo,\n onBtnClick,\n btnTitle,\n secondaryBtnTitle,\n secondaryBtnTo,\n onSecondaryBtnClick,\n children,\n warning,\n popupInputs,\n type = MODAL_TYPE.confirm,\n modalType,\n isSubmitting,\n updateIsSubmitting,\n}) => {\n useEffect(() => {\n updateIsSubmitting(false);\n }, [updateIsSubmitting]);\n\n return (\n \n \n \n {warning && (\n \n {warning}\n \n )}\n \n \n {btnTitle && (\n \n )}\n {secondaryBtnTitle && (\n \n )}\n \n \n );\n};\n\nconst mapStateToProps = state => ({\n isSubmitting: getIsSubmitting(state),\n});\n\nconst mapDispatchToProps = dispatch => ({\n updateIsSubmitting: isSubmitting =>\n dispatch(ModalCreators.updateIsSubmitting(isSubmitting)),\n});\n\nexport default connect(\n mapStateToProps,\n mapDispatchToProps\n)(withTranslation()(PopupTemplate));\n","import React from 'react';\n\nimport PopupTemplate from '../template/PopupTemplate';\n\nconst PopupAlert = ({ message, ...other }) => (\n {message} \n);\n\nexport default PopupAlert;\n","import React from 'react';\nimport { connect } from 'react-redux';\nimport { bindActionCreators } from 'redux';\nimport _ from 'lodash';\nimport { Form } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nimport { FormDataCreators } from 'core/form-data/formDataReducer';\n\nimport { FormInput } from 'components';\nimport PopupTemplate from '../template/PopupTemplate';\n\nconst Subtitle = styled.div`\n margin-bottom: 1em;\n`;\n\nconst ReverseMargin = styled.div`\n margin-bottom: -1em;\n`;\n\nconst PopupInputs = ({\n inputs,\n message,\n formData,\n updateFormData,\n ...other\n}) => {\n const onChange = (e, field) => {\n if (!field) {\n field = e.target;\n }\n\n updateFormData(e, field);\n };\n\n return (\n \n {message} \n \n {_.isEmpty(inputs) && }\n \n );\n};\n\nexport default connect(\n state => state.formData,\n dispatch => bindActionCreators(FormDataCreators, dispatch)\n)(PopupInputs);\n","import React, { useState } from 'react';\nimport { Modal } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nimport ActionModal from '../../action-modal/ActionModal';\nimport PopupAlert from '../alert/PopupAlert';\nimport PopupInputs from '../inputs/PopupInputs';\n\nconst Container = styled.div`\n padding: 10px;\n`;\n\nconst PopupActionModal = props => {\n const { popupAction, onBtnClick, onSecondaryBtnClick } = props;\n const [isOpen, setIsOpen] = useState(false);\n const [popupActionYesNo, setPopupActionYesNo] = useState(null);\n\n const closeModal = () => {\n setIsOpen(false);\n };\n\n const configConfirmModal = (action, onClick) => {\n const { name, message, yes_OkButton, no_CancelButton } = action;\n\n const confirmModalOptions = {\n title: name ? name : '',\n message: message ? message : '',\n btnTitle: yes_OkButton ? yes_OkButton.name : '',\n onBtnClick: onClick,\n secondaryBtnTitle: no_CancelButton ? no_CancelButton.name : '',\n onSecondaryBtnClick: closeModal,\n };\n\n setIsOpen(true);\n setPopupActionYesNo(confirmModalOptions);\n };\n\n const showConfirmModal = (yesNoAction, onClick) =>\n yesNoAction ? configConfirmModal(yesNoAction, onClick) : onClick();\n\n const PopupType =\n popupAction.inputs && popupAction.inputs.length > 0\n ? PopupInputs\n : PopupAlert;\n\n return (\n \n \n showConfirmModal(popupAction.yes_OkPopupAction, onBtnClick)\n }\n onSecondaryBtnClick={() =>\n showConfirmModal(\n popupAction.no_CancelPopupAction,\n onSecondaryBtnClick\n )\n }\n />\n \n \n \n \n \n \n );\n};\n\nexport default PopupActionModal;\n","import React from 'react';\nimport { Tab, Form, Menu } from 'semantic-ui-react';\nimport _ from 'lodash';\n\nimport { withRouter } from 'react-router-dom';\nimport { withTranslation } from 'react-i18next';\nimport { connect } from 'react-redux';\n\nimport { getModal } from 'core/modal/modalReducer';\n\nimport PopupTemplate from '../template/PopupTemplate';\n\nimport styled from 'styled-components';\n\nconst StyledTab = styled(Tab)`\n ${({\n theme: {\n color: { fg, accentBg },\n },\n }) => `\n &&&&& {\n & .ui.attached.tabular.menu {\n border: none !important;\n }\n\n & .ui.tabular.menu .item {\n color: ${fg} !important;\n border: none !important;\n }\n\n & .ui.tabular.menu .active.item {\n background-color: ${accentBg} !important;\n color: ${fg} !important;\n border: none !important;\n }\n }\n `}\n`;\n\nconst PopupTabs = ({ panes, handleTabChange, modal, ...other }) => (\n \n \n \n);\n\nconst mapStateToProps = state => ({\n modal: getModal(state),\n});\n\nconst mapDispatchToProps = null;\n\nexport default withRouter(\n connect(\n mapStateToProps,\n mapDispatchToProps\n )(withTranslation()(PopupTabs))\n);\n","import React from 'react';\nimport { connect } from 'react-redux';\nimport { bindActionCreators } from 'redux';\nimport { Form, Segment, Dropdown } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nimport { ThemedSegment, ThemedLabel } from 'components';\nimport { FormDataCreators } from 'core/form-data/formDataReducer';\n\nimport PopupTemplate from '../template/PopupTemplate';\n\nconst Bold = styled.span`\n font-weight: 700;\n margin: 0 6px;\n`;\n\nconst roundOptions = [\n {\n key: 1,\n text: 'Round 1',\n value: 1,\n },\n {\n key: 2,\n text: 'Round 2',\n value: 2,\n },\n];\n\nconst TransportDetails = ({ inputs, message, round, transport, ...other }) => (\n \n {round && (\n <>\n \n \n \n Round \n \n \n \n \n >\n )}\n \n \n \n Name: {transport.name}\n
\n \n Client: {transport.client}\n
\n \n Address: {transport.address}\n
\n \n Phone: {transport.phone}\n
\n \n Volume: {transport.volume}\n
\n \n Notes: {transport.notes}\n
\n \n \n);\n\nexport default connect(\n state => state.formData,\n dispatch => bindActionCreators(FormDataCreators, dispatch)\n)(TransportDetails);\n","import { IMAGE_URL } from 'core/utils/constant';\n\nexport default {\n drivers: [\n {\n id: 1,\n name: 'John P.',\n avatar: IMAGE_URL.logoMedium,\n capacity: 40,\n status: 'On transit',\n },\n {\n id: 2,\n name: 'Joe W.',\n avatar: IMAGE_URL.logoMedium,\n capacity: 0,\n status: 'Not working',\n },\n {\n id: 3,\n name: 'Alex D.',\n avatar: IMAGE_URL.logoMedium,\n capacity: 90,\n status: 'Not working',\n },\n {\n id: 4,\n name: 'Alex D.',\n avatar: IMAGE_URL.logoMedium,\n capacity: 90,\n status: 'Not working',\n },\n {\n id: 5,\n name: 'Alex D.',\n avatar: IMAGE_URL.logoMedium,\n capacity: 90,\n status: 'Not working',\n },\n {\n id: 6,\n name: 'Alex D.',\n avatar: IMAGE_URL.logoMedium,\n capacity: 90,\n status: 'Not working',\n },\n ],\n};\n","// import axios from 'axios';\n// import BaseApi from 'api/baseApi';\nimport _ from 'lodash';\nimport driversMock from './driversMock';\n\n// const CancelToken = axios.CancelToken;\nconst sources = [];\n\nconst driverApi = {\n getAll: () => {\n setTimeout(function() {\n console.log('Mocking drivers data');\n }, 1500);\n\n return driversMock;\n },\n cancelRequests: () => {\n _.forEach(sources, source => {\n source.cancel('Cancellation');\n });\n },\n};\n\nexport default driverApi;\n","import React from 'react';\nimport styled from 'styled-components';\nimport { Header } from 'semantic-ui-react';\n\nconst Title = styled(Header)`\n margin-bottom: 1.5em;\n text-align: center;\n text-transform: uppercase;\n opacity: 0.5;\n`;\n\nconst PopupTitle = ({ title, size }) => (\n {`${title} (${size})`} \n);\n\nexport default PopupTitle;\n","import React from 'react';\nimport { string } from 'prop-types';\nimport styled from 'styled-components';\n\nconst Container = styled.div`\n float: left;\n text-transform: uppercase;\n > * {\n display: block;\n }\n`;\n\nconst ModifcationsLink = styled.span`\n text-decoration: underline;\n font-size: 0.8em;\n font-style: italic;\n text-transform: uppercase;\n`;\n\nconst PopupStatusMessage = ({ title }) => (\n \n All {title} uploaded!\n See modifications \n \n);\n\nPopupStatusMessage.propTypes = {\n title: string.isRequired,\n};\n\nexport default PopupStatusMessage;\n","import React from 'react';\nimport { Item, Button } from 'semantic-ui-react';\nimport { InputSearch } from 'components';\nimport styled from 'styled-components';\nimport PopupStatusMessage from './PopupStatusMessage';\n\nconst ScrollableItemGroup = styled(Item.Group)`\n max-height: 500px;\n overflow-y: scroll;\n padding-right: 10px;\n`;\n\nconst PopupList = ({ loading, title, handleSearch, children }) => (\n <>\n \n {children} \n \n \n >\n);\n\nexport default PopupList;\n","import React from 'react';\nimport styled from 'styled-components';\nimport { Item, Button, Icon, Progress, Grid } from 'semantic-ui-react';\n\nimport { ThemedButton } from 'components';\n\nconst StyledMetaItem = styled(Item.Meta)`\n & {\n color: ${({ theme: { color } }) => color.popupFg} !important;\n }\n`;\n\nconst Container = styled(Item)`\n &&& {\n padding: 1em 1em;\n border-radius: 0.28571429rem;\n border: ${({ theme: { color } }) => color.border} !important;\n cursor: pointer;\n background-color: ${({ theme: { color } }) => color.bgGeneral} !important;\n\n :hover,\n :focus,\n :active {\n background-color: ${({ theme: { color } }) =>\n color.tableItemBgHover} !important;\n }\n }\n`;\n\nconst DriverName = styled.h4`\n margin-bottom: 0;\n`;\n\nconst CapacityContainer = styled.div`\n position: relative;\n`;\nconst CapacityProgress = styled(Progress)`\n &&& {\n margin: 0;\n }\n`;\nconst CapacityEmptyProgress = styled(Progress)`\n &&& {\n margin: 0;\n\n .bar {\n background-color: transparent;\n }\n }\n`;\nconst PercentValue = styled.span`\n position: absolute;\n top: 3px;\n text-align: center;\n width: 100%;\n z-index: 99;\n`;\n\nconst EditToolsContainer = styled.div`\n float: right;\n`;\n\nconst StyledButton = ({ name, handleClick }) => (\n \n \n \n);\n\nconst EditTools = ({ handleEditMode }) => (\n \n \n \n \n \n \n \n \n);\n\nconst DriverListItem = ({ info, handleClick, handleEditMode }) => {\n return (\n \n \n \n \n \n {info.name} \n {info.status} \n \n \n Capacity \n \n {info.capacity > 0 ? (\n \n ) : (\n \n )}\n {`${info.capacity}%`} \n \n \n \n \n \n \n \n \n );\n};\n\nexport default DriverListItem;\n","import React from 'react';\nimport { node } from 'prop-types';\nimport styled from 'styled-components';\nimport { Segment } from 'semantic-ui-react';\n\nconst Container = styled(Segment)`\n &&& {\n height: 100%;\n background-color: ${({ theme: { color } }) => color.bgGeneral} !important;\n\n label {\n color: ${({ theme: { color } }) => color.fg} !important;\n }\n }\n`;\n\nconst PopupInfoPanel = ({ children }) => {children} ;\n\nPopupInfoPanel.propTypes = {\n children: node.isRequired,\n};\n\nexport default PopupInfoPanel;\n","import React from 'react';\nimport styled from 'styled-components';\nimport { Image, Form, Button } from 'semantic-ui-react';\nimport PopupInfoPanel from '../../components/info-panel/PopupInfoPanel';\nimport { ThemedInput } from 'components';\n\nconst EditPhotoContainer = styled.div`\n font-weight: bold;\n text-align: center;\n margin-top: 10px;\n cursor: pointer;\n`;\n\nconst FormContainer = styled(Form)`\n height: 280px;\n max-height: 300px;\n overflow-y: scroll;\n padding-right: 10px;\n margin-bottom: 10px;\n`;\n\nconst EditPhoto = () => (\n \n Edit photo \n \n);\n\nconst DriverInfoPanel = ({ driver, edited }) => {\n return (\n \n \n \n \n \n \n {edited && }\n \n );\n};\n\nexport default DriverInfoPanel;\n","import React, { useState, useEffect } from 'react';\nimport { Grid } from 'semantic-ui-react';\nimport driverApi from '../../../api/driver/driverApi';\n\nimport PopupTitle from '../components/container/PopupTitle';\nimport PopupList from '../components/list/PopupList';\n\nimport DriverListItem from './components/DriverListItem';\nimport DriverInfoPanel from './components/DriverInfoPanel';\n\nconst PopupDrivers = () => {\n const [loading, setLoading] = useState(false);\n const [drivers, setDrivers] = useState([]);\n const [selectedDriver, setSelectedDriver] = useState(null);\n const [editMode, setEditMode] = useState(false);\n\n useEffect(() => {\n fetchDrivers();\n }, []);\n\n const fetchDrivers = async () => {\n setLoading(true);\n const response = await driverApi.getAll();\n\n if (response && response.drivers) {\n const { drivers } = response;\n setDrivers(drivers);\n setSelectedDriver(drivers[0]);\n }\n setLoading(false);\n };\n\n const handleSelectDriver = driver => {\n setEditMode(false);\n setSelectedDriver(driver);\n };\n\n const enableEditMode = async (e, driver) => {\n e.stopPropagation();\n if (selectedDriver.id !== driver.id) {\n // const res = await setSelectedDriver(driver);\n }\n setEditMode(true);\n };\n\n const handleSearch = (e, { name, value }) => {\n fetchDrivers();\n };\n\n return (\n \n
\n
\n \n \n {drivers.map((driver, index) => (\n handleSelectDriver(driver)}\n handleEditMode={e => enableEditMode(e, driver)}\n />\n ))}\n \n \n \n \n \n \n
\n );\n};\n\nexport default PopupDrivers;\n","export const STOP_STATUS = {\n SCHEDULED: 'Scheduled',\n UNSCHEDULED: 'Unscheduled',\n};\n\nexport default {\n stops: [\n {\n id: 1,\n name: 'Location X',\n address: '123 Loc.1 Paris',\n client: {\n name: 'John P.',\n phone: '1234567890',\n },\n time: '09:00 - 12:00',\n status: STOP_STATUS.UNSCHEDULED,\n },\n {\n id: 2,\n name: 'Location SY',\n address: '123 Loc.1 Paris',\n client: {\n name: 'John P.',\n phone: '1234567890',\n },\n time: '09:00 - 12:00',\n status: STOP_STATUS.SCHEDULED,\n },\n {\n id: 3,\n name: 'Location X',\n address: '123 Loc.1 Paris',\n client: {\n name: 'John P.',\n phone: '1234567890',\n },\n time: '09:00 - 12:00',\n status: STOP_STATUS.UNSCHEDULED,\n },\n {\n id: 4,\n name: 'Location YZ',\n address: '123 Loc.1 Paris',\n client: {\n name: 'John P.',\n phone: '1234567890',\n },\n time: '09:00 - 12:00',\n status: STOP_STATUS.SCHEDULED,\n },\n {\n id: 5,\n name: 'Location X',\n address: '123 Loc.1 Paris',\n client: {\n name: 'John P.',\n phone: '1234567890',\n },\n time: '09:00 - 12:00',\n status: STOP_STATUS.SCHEDULED,\n },\n {\n id: 6,\n name: 'Location X',\n address: '123 Loc.1 Paris',\n client: {\n name: 'John P.',\n phone: '1234567890',\n },\n time: '09:00 - 12:00',\n status: STOP_STATUS.UNSCHEDULED,\n },\n ],\n};\n","// import axios from 'axios';\n// import BaseApi from 'api/baseApi';\nimport _ from 'lodash';\nimport stopsMock from './stopsMock';\n\n// const CancelToken = axios.CancelToken;\nconst sources = [];\n\nconst stopApi = {\n getAll: () => {\n setTimeout(function() {\n console.log('Mocking stops data');\n }, 1500);\n\n return stopsMock;\n },\n cancelRequests: () => {\n _.forEach(sources, source => {\n source.cancel('Cancellation');\n });\n },\n};\n\nexport default stopApi;\n","import React from 'react';\nimport styled from 'styled-components';\nimport { Item, Button, Icon, Grid } from 'semantic-ui-react';\n\nimport { ThemedLabel, ThemedButton } from 'components';\n\nimport { STOP_STATUS } from '../../../../api/stop/stopsMock';\n\nconst Container = styled(Item)`\n &&& {\n padding: 1em 1em;\n border-radius: 0.28571429rem;\n border: ${({ theme: { color } }) => color.border} !important;\n cursor: pointer;\n background-color: ${({ theme: { color } }) => color.bgGeneral} !important;\n }\n`;\n\nconst LocationName = styled.h4`\n margin-bottom: 0;\n`;\n\nconst StyledMetaItem = styled(Item.Meta)`\n & {\n color: ${({ theme: { color } }) => color.popupFg} !important;\n }\n`;\n\nconst StyledMetadata = styled.div`\n font-weight: bold;\n color: ${({ theme: { color } }) => color.fg} !important;\n font-style: italic;\n`;\n\nconst EditToolsContainer = styled.div`\n float: right;\n`;\n\nconst StyledButton = ({ name, handleClick }) => (\n \n \n \n);\n\nconst EditTools = ({ handleEditMode }) => (\n \n \n \n \n \n \n \n \n);\n\nconst StopListItem = ({ info, handleClick, handleEditMode }) => {\n const { name, address, client, time, status } = info;\n const { name: clientName, phone } = client;\n\n return (\n \n \n \n \n \n \n \n {name} \n {address} \n {`${clientName} - ${phone}`} \n \n \n {time} \n \n \n {status}\n \n \n \n \n \n \n \n \n \n );\n};\n\nexport default StopListItem;\n","const sortedFieldSection = fields => [\n ...new Set(\n //section.field_Section\n fields\n .sort(function(a, b) {\n if (a.row < b.row) {\n return -1;\n } else if (a.row > b.row) {\n return 1;\n } else {\n if (a.column < b.column) {\n return -1;\n } else if (a.column > b.column) {\n return 1;\n } else {\n return -1;\n }\n }\n })\n .map(fs => fs.row)\n ),\n];\n\nexport default sortedFieldSection;\n","import { FIELD_TYPE } from 'core/utils/constant';\n\nexport default [\n {\n row: 1,\n column: 1,\n key: 'id',\n name: 'ID',\n pattern: null,\n comboList: null,\n type: FIELD_TYPE.text,\n required: true,\n isDisabled: true,\n isVisible: true,\n },\n {\n row: 2,\n column: 1,\n key: 'name',\n name: 'Name',\n pattern: null,\n comboList: null,\n type: FIELD_TYPE.text,\n required: true,\n isVisible: true,\n },\n {\n row: 3,\n column: 1,\n key: 'address',\n name: 'Address',\n pattern: null,\n comboList: null,\n type: FIELD_TYPE.text,\n required: true,\n isVisible: true,\n },\n {\n row: 4,\n column: 1,\n key: 'clientName',\n name: 'Client Name',\n pattern: null,\n comboList: null,\n type: FIELD_TYPE.text,\n required: true,\n isVisible: true,\n },\n {\n row: 4,\n column: 2,\n key: 'clientPhone',\n name: 'Client Phone',\n pattern: null,\n comboList: null,\n type: FIELD_TYPE.text,\n required: true,\n isVisible: true,\n },\n {\n row: 6,\n column: 1,\n key: 'status',\n name: 'Status',\n pattern: null,\n comboList: null,\n type: FIELD_TYPE.text,\n required: true,\n isDisabled: true,\n isVisible: true,\n },\n];\n","import React from 'react';\nimport { node } from 'prop-types';\nimport { Form, Grid } from 'semantic-ui-react';\n\nconst InfoPanelFormContainer = ({ children }) => (\n \n);\n\nInfoPanelFormContainer.propTypes = {\n children: node.isRequired,\n};\n\nexport default InfoPanelFormContainer;\n","import React, { useState, useEffect } from 'react';\nimport styled from 'styled-components';\nimport { Form, Button, Grid } from 'semantic-ui-react';\n\nimport sortedFieldSection from '../helpers/sortedFieldSection';\n\nimport stopsForm from '../form/stopsForm';\nimport { FormInput } from 'components';\nimport PopupInfoPanel from '../../components/info-panel/PopupInfoPanel';\nimport InfoPanelFormContainer from '../../components/info-panel/InfoPanelFormContainer';\nimport { STOP_STATUS } from '../../../../api/stop/stopsMock';\n\nconst GridRow = styled(Grid.Row)`\n .ui.grid > &.row {\n margin: 0;\n padding: 1rem 0 0 0;\n }\n\n @media only screen and (min-width: 768px) {\n .ui.grid > &.row {\n flex-wrap: nowrap;\n }\n }\n\n .ui.grid > &.row:first-child {\n margin-top: 1rem;\n }\n\n .ui.grid > &.row:last-child {\n margin-bottom: 1rem;\n }\n`;\n\nconst StopInfoPanel = ({ stop, edited }) => {\n const [formLayout, setFormLayout] = useState([]);\n const [formData, setFormData] = useState({});\n\n useEffect(() => {\n console.log(stop);\n setFormLayout(stopsForm);\n setFormData({\n ...stop,\n clientName: stop && stop.client ? stop.client.name : '',\n clientPhone: stop && stop.client ? stop.client.phone : '',\n });\n }, [stop]);\n\n return (\n \n \n {sortedFieldSection(formLayout).map(row => (\n \n {formLayout\n .filter(fis => fis.row === row)\n .map(field => (\n {}}\n />\n ))}\n \n ))}\n \n {edited && (\n <>\n \n {stop.status === STOP_STATUS.SCHEDULED ? (\n \n ) : (\n \n )}\n >\n )}\n \n );\n};\n\nexport default StopInfoPanel;\n","import React from 'react';\nimport {\n ActionModal,\n PopupAlert,\n PopupActionModal,\n PopupInputs,\n PopupTabs,\n TransportDetails,\n} from './components';\nimport PopupDrivers from 'scenes/dashboard/scenes/dispatch/components/popups/drivers/PopupDrivers';\nimport PopupStops from 'scenes/dashboard/scenes/dispatch/components/popups/stops/PopupStops';\n\nconst componentsByType = {\n 'popup-alert': PopupAlert,\n 'form-action': PopupActionModal,\n 'popup-inputs': PopupInputs,\n 'popup-inputs-clean': PopupInputs,\n 'popup-tabs': PopupTabs,\n 'transport-details': TransportDetails,\n 'popup-drivers': PopupDrivers,\n 'popup-stops': PopupStops,\n};\n\nconst Modal = ({ modalType, isOpen, options, closeModal, size }) => {\n const BodyModal = componentsByType[modalType];\n\n return (\n \n {modalType && }\n \n );\n};\n\nexport default Modal;\n","import React, { useState, useEffect } from 'react';\nimport { Grid } from 'semantic-ui-react';\nimport stopApi from '../../../api/stop/stopApi';\n\nimport StopListItem from './components/StopListItem';\nimport StopInfoPanel from './components/StopInfoPanel';\nimport PopupTitle from '../components/container/PopupTitle';\nimport PopupList from '../components/list/PopupList';\n\nconst PopupStops = () => {\n const [loading, setLoading] = useState(false);\n const [stops, setStops] = useState([]);\n const [selectedStop, setSelectedStop] = useState(null);\n const [editMode, setEditMode] = useState(false);\n\n useEffect(() => {\n fetchStops();\n }, []);\n\n const fetchStops = async () => {\n setLoading(true);\n const response = await stopApi.getAll();\n\n if (response && response.stops) {\n const { stops } = response;\n setStops(stops);\n setSelectedStop(stops[0]);\n }\n setLoading(false);\n };\n\n const handleSelectStop = stop => {\n setEditMode(false);\n setSelectedStop(stop);\n };\n\n const enableEditMode = async (e, stop) => {\n e.stopPropagation();\n if (selectedStop.id !== stop.id) {\n // const res = await setSelectedStop(stop);\n }\n setEditMode(true);\n };\n\n const handleSearch = (e, { name, value }) => {\n fetchStops();\n };\n\n return (\n \n
\n
\n \n \n {stops.map((stop, index) => (\n handleSelectStop(stop)}\n handleEditMode={e => enableEditMode(e, stop)}\n />\n ))}\n \n \n \n \n \n \n
\n );\n};\n\nexport default PopupStops;\n","import React from 'react';\nimport styled from 'styled-components';\n\nconst StyledBackgroundDiv = styled.div`\n ${({\n backgroundUrl,\n backgroundPosition,\n theme: {\n color: { bgGeneral },\n },\n }) => `\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n background: ${bgGeneral};\n background-size: cover;\n background-position: ${backgroundPosition};\n ${backgroundUrl ? `background-image: url(${backgroundUrl});` : ''}\n `}\n`;\n\nconst Background = props => {\n return ;\n};\n\nexport default Background;\n","import React from 'react';\nimport { connect } from 'react-redux';\n\nimport { IMAGE_URL } from 'core/utils/constant';\nimport { getBackground } from 'core/background/backgroundReducer';\n\nimport Background from './Background';\nimport ImageSrcValidator from '../image/ImageSrcValidator';\n\nconst BackgroundContainer = ({\n area,\n background: { customBackgroundPosition },\n}) => {\n const backgroundUrl = area\n ? area.areaContent\n ? area.areaContent.background\n : ''\n : IMAGE_URL.background;\n\n const backgroundProps = {\n backgroundUrl,\n backgroundPosition: customBackgroundPosition,\n };\n\n return (\n \n \n \n );\n};\n\nconst mapStateToProps = state => ({\n background: getBackground(state),\n});\n\nconst mapDispatchToProps = null;\n\nexport default connect(\n mapStateToProps,\n mapDispatchToProps\n)(BackgroundContainer);\n","import React from 'react';\nimport { Sticky, Rail } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nconst StyledRail = styled(({ expandedSidebar, ...props }) => (\n \n)).attrs({\n internal: true,\n attached: true,\n position: 'right',\n})`\n ${({ visible, expandedSidebar }) => `\n &.ui.rail {\n width: ${\n !visible\n ? '100%'\n : expandedSidebar\n ? 'calc(100% - 150px)'\n : 'calc(100% - 48px)'\n };\n }\n `}\n`;\n\nconst StickyTop = ({\n contextRef,\n expandedSidebar,\n component: Component,\n visible,\n}) => (\n \n \n \n \n \n);\n\nexport default StickyTop;\n","import React from 'react';\nimport ResponsiveContainer from 'recharts/lib/component/ResponsiveContainer';\nimport LineChart from 'recharts/lib/chart/LineChart';\nimport Line from 'recharts/lib/cartesian/Line';\nimport XAxis from 'recharts/lib/cartesian/XAxis';\nimport YAxis from 'recharts/lib/cartesian/YAxis';\nimport CartesianGrid from 'recharts/lib/cartesian/CartesianGrid';\nimport Tooltip from 'recharts/lib/component/Tooltip';\n//import Legend from 'recharts/lib/component/Legend';\n\nconst data = [\n { name: 'Mon', Visits: 2200, Orders: 3400 },\n { name: 'Tue', Visits: 1280, Orders: 2398 },\n { name: 'Wed', Visits: 5000, Orders: 4300 },\n { name: 'Thu', Visits: 4780, Orders: 2908 },\n { name: 'Fri', Visits: 5890, Orders: 4800 },\n { name: 'Sat', Visits: 4390, Orders: 3800 },\n { name: 'Sun', Visits: 4490, Orders: 4300 },\n];\n\nfunction SimpleLineChart() {\n return (\n \n \n \n \n \n \n {/* */}\n \n \n \n \n );\n}\n\nexport default SimpleLineChart;\n","import React from 'react';\nimport { Table } from 'semantic-ui-react';\n\nimport { ThemedTable, ThemedPagination } from 'components';\n\nconst TableExamplePagination = () => (\n \n \n \n Header \n Header \n Header \n \n \n\n \n \n First \n Cell \n Cell \n \n \n Cell \n Cell \n Cell \n \n \n Cell \n Cell \n Cell \n \n \n\n \n \n \n \n \n \n \n \n);\n\nexport default TableExamplePagination;\n","import BaseApi from 'api/baseApi';\n\nconst appPreferenceApi = {\n post: (appPreference, params) =>\n BaseApi.post('apppreference', appPreference, params),\n put: (appPreference, property, params) =>\n BaseApi.put(`apppreference`, { property, ...appPreference }, params),\n};\n\nexport default appPreferenceApi;\n","import { locales } from 'config/i18n';\nimport { FIELD_TYPE } from 'core/utils/constant';\n\nconst structure = {\n rows: [\n {\n position: 1,\n columns: [\n {\n position: 1,\n name: 'Language',\n key: 'language',\n type: FIELD_TYPE.combolist,\n attrs: {\n options: locales,\n },\n },\n //{\n // position: 2,\n // name: 'Default module',\n // key: 'defaultModule',\n // type: FIELD_TYPE.text,\n //},\n ],\n },\n {\n position: 2,\n columns: [\n {\n position: 1,\n name: 'Collapse menu',\n key: 'smallMenu',\n type: FIELD_TYPE.checkbox,\n },\n ],\n },\n ],\n};\n\nexport default structure;\n","import React from 'react';\nimport { func, object } from 'prop-types';\nimport { withTranslation } from 'react-i18next';\n\nimport appPreferenceApi from 'api/appPreference/appPreferenceApi';\nimport preferencesStructure from 'core/dto/user/preferencesStructure';\n\nimport { EntityInfo } from 'components';\n\nconst Preferences = ({\n t,\n appPreference,\n handleSetKey,\n handleEntityChange,\n}) => {\n return (\n \n );\n};\n\nPreferences.propTypes = {\n t: func.isRequired,\n appPreference: object.isRequired,\n handleSetKey: func.isRequired,\n handleEntityChange: func.isRequired,\n};\n\nexport default withTranslation()(Preferences);\n","import React, { useState } from 'react';\nimport { any, object } from 'prop-types';\nimport { bindActionCreators } from 'redux';\nimport { withTranslation } from 'react-i18next';\nimport { connect } from 'react-redux';\n\nimport { AuthCreators } from 'core/auth/authReducer';\nimport {\n settingsActionCreators,\n getSettings,\n} from 'core/settings/settingsReducer';\nimport { dispatchPreferences } from 'core/preferences/helpers';\n\nimport Preferences from './Preferences';\n\nconst PreferencesContainer = ({\n i18n,\n user,\n updateCurrentUser,\n settings,\n settingsActionCreators,\n}) => {\n // build app preference with current settings\n const [appPreference, setAppPreference] = useState({\n ...user.appPreference,\n language: i18n.language,\n smallMenu: !settings.expandedSidebar,\n });\n\n const handleSetKey = key => {\n const newPreferences = { ...appPreference, appPreferenceID: key };\n\n // set in redux store\n updateCurrentUser({ ...user, appPreference: newPreferences });\n\n // set in state\n setAppPreference(newPreferences);\n };\n\n // apply new preferences\n const handleEntityChange = data => {\n const { toggleSidebar } = settingsActionCreators;\n dispatchPreferences(data, { toggleSidebar, i18n });\n };\n\n const props = {\n appPreference,\n handleSetKey,\n handleEntityChange,\n };\n\n return ;\n};\n\nconst mapStateToProps = state => ({\n settings: getSettings(state),\n});\n\nconst mapDispatchToProps = dispatch => ({\n settingsActionCreators: bindActionCreators(settingsActionCreators, dispatch),\n updateCurrentUser: currentUser =>\n dispatch(AuthCreators.updateCurrentUser(currentUser)),\n});\n\nPreferencesContainer.propTypes = {\n i18n: any.isRequired,\n user: object.isRequired,\n settings: object.isRequired,\n settingsActionCreators: object.isRequired,\n};\n\nexport default connect(\n mapStateToProps,\n mapDispatchToProps\n)(withTranslation()(PreferencesContainer));\n","import React from 'react';\nimport { Popup } from 'semantic-ui-react';\n\nconst Tooltip = ({ children, ...props }) => {\n const popupProps = {\n inverted: true,\n hideOnScroll: true,\n size: 'mini',\n mouseEnterDelay: 500,\n style: { opacity: 0.85 },\n ...props,\n };\n\n return ;\n};\n\nexport default Tooltip;\n","import React from 'react';\nimport styled from 'styled-components';\nimport { useTranslation } from 'react-i18next';\n\nimport Utils from 'core/utils/utils';\nimport { SegmentMenu } from 'components';\n\nconst StyledIframe = styled.iframe`\n &&& {\n margin-top: -1em;\n margin-right: -1em;\n margin-left: -1em;\n width: calc(100% + 2em);\n }\n`;\n\nconst Embedded = ({ title, url, compact }) => {\n const { t } = useTranslation();\n\n const icon = 'external';\n const text = t('See full screen');\n const onClick = () => Utils.openInNewTab(url);\n const menuButtonProps = { icon, text, onClick };\n\n return (\n <>\n \n \n >\n );\n};\n\nexport default Embedded;\n","import React from 'react';\n\nimport Utils from 'core/utils/utils';\nimport { CONTENT_TYPE } from 'core/utils/constant';\n\nimport {\n DocumentTable,\n FormSection,\n History,\n ImagePreview,\n PageSegment,\n TrackingByAddress,\n} from 'components';\n\nimport Embedded from '../components/Embedded';\n\nconst {\n title,\n iframe,\n agenda,\n table,\n map,\n cards,\n trackingByAddress,\n history,\n image,\n timeline,\n} = CONTENT_TYPE;\n\nconst buildPage = (pc, area, module, currentUser, props) => {\n const { type, value, visible, sectionID, tableKey } = pc || {};\n const key = getContentKey(pc);\n\n const { backgroundColor, color } = props;\n\n const segmentProps = { backgroundColor, color };\n return sectionID && sectionID >= 0 ? (\n pc && visible ? (\n \n \n \n ) : (\n \n )\n ) : (\n \n {type === title ? (\n {value} \n ) : type === iframe ? (\n \n ) : [table, agenda, cards, map, timeline].includes(type) ? (\n \n ) : type === trackingByAddress ? (\n Utils.canPerform(currentUser, 'trackbyaddress') ? (\n \n ) : (\n undefined\n )\n ) : type === history ? (\n props.histories ? (\n \n ) : (\n undefined\n )\n ) : type === image ? (\n \n ) : (\n // default 'text'\n {value}
\n )}\n \n );\n};\n\n/*\n * key is pageContentID or section.key\n * because pageContentID might be duplicate with section.sectionID\n */\nconst getContentKey = _ct =>\n _ct.pageContentID > 0 ? _ct.pageContentID : _ct.key;\n\nexport { buildPage, getContentKey };\n","import React from 'react';\nimport { arrayOf, number, object } from 'prop-types';\nimport { Grid } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nimport { buildPage } from '../helpers';\n\nconst GridColumn = styled(Grid.Column)`\n @media only screen and (max-width: 767px) {\n .ui.stackable.grid > .row > &.column {\n padding: 0 !important;\n }\n }\n`;\n\nconst CustomPageGridColumn = ({\n pcs,\n columnWidth,\n area,\n module,\n currentUser,\n ...props\n}) => (\n \n {pcs.map(pc => buildPage(pc, area, module, currentUser, props))}\n \n);\n\nCustomPageGridColumn.propTypes = {\n pcs: arrayOf(object).isRequired,\n columnWidth: number,\n};\n\nCustomPageGridColumn.defaultProps = { columnWidth: undefined };\n\nexport default CustomPageGridColumn;\n","import React from 'react';\nimport { arrayOf, object } from 'prop-types';\nimport { Grid } from 'semantic-ui-react';\nimport styled from 'styled-components';\n\nimport Utils from 'core/utils/utils';\n\nimport { getContentKey } from '../helpers';\nimport CustomPageGridColumn from './CustomPageGridColumn';\n\nconst GridRow = styled(Grid.Row)`\n .ui.grid > &.row {\n padding: 0;\n }\n\n @media only screen and (max-width: 767px) {\n .ui.stackable.grid:not(.vertically) > &.row {\n margin: 0;\n }\n }\n`;\n\nconst CustomPageGridRow = ({ groupedRow, ...props }) => {\n const { totalSpanInRow, colsSorted } = Utils.getRowSpan(groupedRow);\n\n return (\n \n {colsSorted.map(col => {\n const pcs = groupedRow\n .filter(r => r.column === col)\n .sort((a, b) => a.nestedRow - b.nestedRow);\n\n const hasColSpan = pcs.some(s => s.columnSpan >= 2);\n const columnWidth = hasColSpan\n ? Utils.columnWidthByColsSpan(Utils.maxColSpan(pcs), totalSpanInRow)\n : undefined;\n\n return (\n \n );\n })}\n \n );\n};\n\nCustomPageGridRow.propTypes = {\n groupedRow: arrayOf(object).isRequired,\n};\n\nexport default CustomPageGridRow;\n","import React from 'react';\nimport { Grid } from 'semantic-ui-react';\nimport styled from 'styled-components';\nimport _ from 'lodash';\n\nimport Utils from 'core/utils/utils';\n\nimport CustomPageGridRow from './components/CustomPageGridRow';\n\nconst StyledGrid = styled(Grid)`\n &&& {\n margin-top: 0;\n }\n`;\n\nconst CustomPage = ({ pageContent, area, module, currentUser, ...props }) => (\n \n {_.map(\n _.groupBy(\n _.filter(\n pageContent,\n ({ areaOnly, areas, sectionID }) =>\n Utils.showInArea({ areaOnly, areas }, area) || sectionID\n ).sort((pc1, pc2) => pc1.row - pc2.row),\n 'row'\n ), // { 'r1': [{r1, c1}, {r1, c2}] }\n groupedRow => (\n \n )\n )}\n \n);\n\nexport default CustomPage;\n","import { withRouter } from 'react-router-dom';\nimport { connect } from 'react-redux';\n\nimport { getCurrentUser } from 'core/auth/authReducer';\nimport CustomPage from './CustomPage';\n\nconst mapStateToProps = state => ({\n currentUser: getCurrentUser(state),\n});\n\nconst mapDispatchToProps = null;\n\nexport default withRouter(\n connect(\n mapStateToProps,\n mapDispatchToProps\n )(CustomPage)\n);\n","import ApiService from 'api/baseApi';\n\nexport default {\n getAddresses: (area, params) =>\n ApiService.get(`tracking/address/${area}`, params),\n track: (address, params) =>\n ApiService.post(`tracking/address`, { address }, params),\n};\n","import _ from 'lodash';\n\nconst getSortedSetOptionsHelper = items => [\n ...new Set(\n _.chain([...new Set(items)])\n .map(i => ({ key: i, value: i, text: i }))\n .sortBy('text')\n .value()\n ),\n];\n\nconst getItemsSelected = (addresses, address, key) => {\n switch (key) {\n case 'city':\n return addresses.map(a => a.city);\n case 'street':\n return addresses.filter(a => a.city === address.city).map(a => a.street);\n case 'number':\n return addresses\n .filter(a => a.city === address.city && a.street === address.street)\n .map(a => `${a.number}${a.complement ? ` - ${a.complement}` : ''}`);\n default:\n return addresses;\n }\n};\n\nexport default function getSortedSetOptions(addresses, address, key) {\n return addresses\n ? getSortedSetOptionsHelper(getItemsSelected(addresses, address, key))\n : [];\n}\n","import React from 'react';\nimport { withTranslation } from 'react-i18next';\nimport { Form, Segment } from 'semantic-ui-react';\nimport { SpinnerSegment } from 'components';\n\nimport getSortedSetOptions from './helpers/getSortedSetOptions';\n\nconst TrackingByAddress = ({\n t,\n addresses,\n address,\n date,\n ready,\n handleChangeMunicipality,\n handleChangeStreet,\n handleChangeNumber,\n}) => {\n const isAddressCityAvailable = addresses && address && address.city;\n const isAddressStreetAvailable = isAddressCityAvailable && address.street;\n const isAddressNumberAvailable = isAddressStreetAvailable && address.number;\n\n return (\n <>\n \n {t(`tracking|Tracking by address`)} \n {t('Please select your address in the form below')}
\n \n \n \n )}\n {isAddressCityAvailable && (\n \n )}\n {isAddressStreetAvailable && (\n \n )}\n {isAddressNumberAvailable && ready && !date && }\n {isAddressNumberAvailable && date && (\n <>\n {date && new Date(Date.parse(date)) < new Date() && (\n {t(`tracking|Drain is not yet planned for this address`)}
\n )}\n {date && new Date(Date.parse(date)) >= new Date() && (\n \n {t(`tracking|Your drain is planned on`)}{' '}\n {new Date(date).toLocaleDateString('fr-fr', {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n })}\n
\n )}\n >\n )}\n \n \n >\n );\n};\n\nexport default withTranslation()(TrackingByAddress);\n","import React, { useState } from 'react';\n\nimport { useApi } from 'api/useApi';\nimport trackingApi from 'api/tracking/trackingApi';\nimport { SpinnerSegment } from 'components';\n\nimport TrackingByAddress from './TrackingByAddress';\n\nconst TrackingByAddressContainer = ({ area }) => {\n const [loading, setLoading] = useState(false);\n const [address, setAddress] = useState({\n number: undefined,\n complement: undefined,\n street: undefined,\n city: undefined,\n });\n const [getArgs] = useState([area.key.toUpperCase()]);\n const [trackArgs, setTrackArgs] = useState([]);\n\n const [fetchedAddresses, pendingFetch] = useApi(\n trackingApi.getAddresses,\n getArgs\n );\n const [fetchedDate, pendingDate] = useApi(trackingApi.track, trackArgs);\n\n const handleChangeMunicipality = (e, data) => {\n setAddress({\n ...address,\n city: data.value,\n street: undefined,\n number: undefined,\n });\n };\n\n const handleChangeStreet = (e, data) => {\n setAddress({ ...address, street: data.value, number: undefined });\n };\n\n const handleChangeNumber = (e, { value }) => {\n const numberAndComplement = value.split(' - ');\n const number = numberAndComplement[0];\n const complement =\n numberAndComplement.length > 1 ? numberAndComplement[1] : undefined;\n\n const newAddress = {\n ...address,\n number: number,\n complement: complement,\n };\n\n setAddress(newAddress);\n setLoading(true);\n setTrackArgs([newAddress]);\n };\n\n return pendingFetch ? (\n \n ) : (\n \n );\n};\n\nexport default TrackingByAddressContainer;\n","import React from 'react';\nimport { bool, func, object, string } from 'prop-types';\n\nimport { PageSegment, TrackedForm } from 'components';\n\nconst EntityInfo = ({\n autosave,\n icon,\n label,\n structure,\n loading,\n saved,\n exists,\n entity,\n entityPrev,\n entityInfo,\n handleChange,\n handleSubmit,\n}) => {\n return (\n \n {entity && (\n \n )}\n \n );\n};\n\nEntityInfo.propTypes = {\n autosave: bool,\n icon: string,\n label: string,\n structure: object.isRequired,\n loading: bool.isRequired,\n saved: bool,\n exists: bool.isRequired,\n entity: object,\n entityPrev: object,\n entityInfo: object.isRequired,\n handleChange: func.isRequired,\n handleSubmit: func.isRequired,\n};\n\nexport default EntityInfo;\n","import React, { useRef, useState, useEffect } from 'react';\nimport { any, bool, func, object, string } from 'prop-types';\nimport _ from 'lodash';\n\nimport { useApi } from 'api/useApi';\nimport { useForm } from 'core/hooks/useForm';\nimport Utils from 'core/utils/utils';\n\nimport EntityInfo from './EntityInfo';\n\nconst EntityInfoContainer = ({\n autosave,\n icon,\n label,\n api,\n entityKey,\n keyName,\n entity,\n type,\n structure,\n onSetKey,\n onEntityChange,\n}) => {\n const newInfo = useRef();\n const entityRef = useRef(_.cloneDeep(entity));\n const [prevInfo, setPrevInfo] = useState(_.cloneDeep(entity));\n const [loading, setLoading] = useState(false);\n const [args, setArgs] = useState([]);\n const [exists, setExists] = useState(entityKey ? true : false);\n\n // send api request\n const triggerApiCall = (formSubmit, field) => {\n // set loading state\n setLoading(true);\n\n // store new value\n newInfo.current = formSubmit;\n\n // compute api arguments\n const newArgs =\n exists && field !== undefined\n ? [{ [type]: formSubmit }, field]\n : [{ [type]: formSubmit }];\n\n // trigger useApi hook\n setArgs(newArgs);\n };\n\n // define form state management\n const onTimeout = (formSubmit, field) => {\n // call api\n triggerApiCall(formSubmit, Utils.toPascalCase(field));\n };\n const [form, changeForm, changeFormKey] = useForm(\n prevInfo,\n autosave ? onTimeout : undefined\n );\n\n // define api call (either put or post of the entity)\n const [response, pending] = useApi(exists ? api.put : api.post, args);\n\n // receive response from api call\n useEffect(() => {\n if (response && (response.status === 201 || response.status === 204)) {\n // prevent further api call by clearing args\n setArgs([]);\n\n // remove loading state\n setLoading(false);\n\n // when api request was a post\n if (response.status === 201 && !exists) {\n if (autosave) {\n // set key\n const { id, key, username } = response.data;\n const newKey = id ? id : key ? key : username ? username : undefined;\n onSetKey(newKey);\n }\n\n // make next call a put\n setExists(true);\n }\n\n // update tracked state by setting base entity\n setPrevInfo(_.cloneDeep(newInfo.current));\n }\n }, [response, autosave, exists, onSetKey]);\n\n // update form after api post request\n useEffect(() => {\n if (\n autosave &&\n keyName &&\n entityKey &&\n newInfo.current &&\n newInfo.current[keyName] !== entityKey &&\n changeFormKey\n ) {\n newInfo.current[keyName] = entityKey;\n changeFormKey(keyName, entityKey);\n }\n }, [entityKey, autosave, keyName, changeFormKey]);\n\n // notify parent component of change\n const notifyChange = info => {\n if (onEntityChange) {\n onEntityChange(info);\n }\n };\n\n // when a value changes in form\n const handleChange = (e, data) => {\n // show change in UI\n changeForm(e, data);\n\n // if autosave\n if (autosave) {\n // notify change\n const { field, value } = Utils.getFieldValueFromEData(e, data);\n notifyChange({ [field]: value });\n }\n };\n\n // when form is submitted via submit button\n const handleSubmit = async e => {\n e.preventDefault();\n\n // call api\n triggerApiCall(form);\n\n // notify change\n notifyChange(form);\n };\n\n const infoProps = {\n autosave,\n icon,\n label,\n structure,\n loading,\n exists,\n entity: entityRef.current,\n saved:\n !pending &&\n response &&\n (response.status === 204 || response.status === 201),\n entityPrev: prevInfo,\n entityInfo: form,\n handleChange,\n handleSubmit,\n };\n\n return ;\n};\n\nEntityInfoContainer.propTypes = {\n autosave: bool,\n icon: string,\n label: string,\n api: object,\n entityKey: any,\n keyName: string,\n entity: object.isRequired,\n type: string,\n structure: object.isRequired,\n onSetKey: func,\n onEntityChange: func,\n};\n\nexport default EntityInfoContainer;\n","// theme\nexport { default as ThemedButton } from './theme/ThemedButton';\nexport { default as ThemedCheckbox } from './theme/ThemedCheckbox';\nexport { default as ThemedDropdown } from './theme/ThemedDropdown';\nexport { default as ThemedInput } from './theme/ThemedInput';\nexport { default as ThemedMessage } from './theme/ThemedMessage';\nexport { default as ThemedSearch } from './theme/ThemedSearch';\nexport { default as ThemedSegment } from './theme/ThemedSegment';\nexport * from './theme/ThemedTable';\nexport { default as ThemedTextArea } from './theme/ThemedTextArea';\nexport { default as ThemedFormField } from './theme/ThemedFormField';\nexport { default as ThemedPagination } from './theme/ThemedPagination';\nexport { default as ThemedPopup } from './theme/ThemedPopup';\nexport { default as ThemedFieldSet } from './theme/ThemedFieldSet';\nexport { default as ThemedLabel } from './theme/ThemedLabel';\nexport { default as ThemedPlaceholder } from './theme/ThemedPlaceholder';\nexport * from './theme/ThemedTypography';\nexport { default as ThemeSelector } from './theme/ThemeSelector';\n\n// icon\nexport { default as ColoredIcon } from './icon/ColoredIcon';\n\n// layout\nexport { default as Center } from './align/Center';\nexport { default as FasterFooter } from './footer/FasterFooter';\n\n// document\nexport { default as documentRoutes } from './document/documentRoutes';\n\n// form\nexport { default as FormInput } from './form/components/input/FormInput';\nexport { default as SimpleForm } from './form/simpleFormContainer';\nexport { default as TrackedForm } from './form/tracked/trackedFormContainer';\nexport { default as FormSection } from './form/components/section/FormSection';\nexport { default as History } from './form/components/history/History';\n\n// batch\nexport { default as Batch } from './batch/batchContainer';\n\n// tiles\nexport { default as TilesPanel } from './tiles/TilesPanel';\nexport { default as Tile } from './tiles/Tile';\n\n// routes\nexport { default as RedirectNotFound } from './router/RedirectNotFound';\nexport { default as PrivateRoute } from './router/PrivateRoute';\nexport { default as AdminRoute } from './router/AdminRoute';\n\n// menus\nexport { default as SegmentMenu } from './menu/SegmentMenu';\n\n// segments\nexport { default as FlexSegment } from './segments/FlexSegment';\nexport { default as TableSegment } from './segments/TableSegment';\nexport { default as PageSegment } from './segments/PageSegment';\nexport { default as SpinnerSegment } from './segments/SpinnerSegment';\n\n// tables\nexport { default as AdminTable } from './tables/AdminTable';\nexport { default as DocumentTable } from './tables/documentTableContainer';\n\n// scrollable tables\nexport { default as ScrollableTable } from './scrollable-table/ScrollableTable';\n\n// toasts\nexport { default as Toast } from './toast/Toast';\nexport { default as ToastMessage } from './toast/ToastMessage';\n\n// image\nexport { default as ImagePreview } from './image/ImagePreview';\n\n// inputs\nexport {\n default as FasterDropdown,\n} from './input/dropdown/fasterDropdownContainer';\nexport { default as FasterSearch } from './input/search/FasterSearch';\nexport { default as InputSearch } from './input/search/InputSearch';\nexport {\n default as InputDateRangePicker,\n} from './input/date/InputDateRangePicker';\nexport { default as InputAddress } from './input/address/InputAddress';\nexport { default as LinkInput } from './input/link/linkInputContainer';\nexport { default as InputFile } from './input/file/inputFileContainer';\nexport {\n default as AdditionsInput,\n} from './input/additions-input/AdditionsInput';\nexport { default as TrackedInput } from './input/tracked/TrackedInput';\nexport { default as TrackedDropdown } from './input/tracked/TrackedDropdown';\nexport { default as TrackedCheckbox } from './input/tracked/TrackedCheckbox';\nexport { default as TrackedSearch } from './input/tracked/TrackedSearch';\nexport { default as IconInput } from './input/icon/IconInput';\n\n// buttons\nexport { default as AdminGridsButtons } from './button/AdminGridsButtons';\nexport { default as AdminUsersButtons } from './button/AdminUsersButtons';\nexport { default as DownloadButton } from './button/downloadButtonContainer';\nexport { default as ButtonLink } from './button/ButtonLink';\nexport { default as DocumentButtonGroup } from './button/DocumentButtonGroup';\nexport { default as PopupTrigger } from './button/PopupTrigger';\nexport { default as ResponsiveButtonCore } from './button/ResponsiveButtonCore';\nexport {\n getSubtleStyle,\n default as SubtleIconButton,\n} from './button/SubtleIconButton';\n\n// filters\nexport { default as Filter } from './filter/Filter';\nexport { default as GridFilter } from './filter/GridFilter';\nexport {\n default as GridFilterTable,\n} from './filter/components/table/GridFilterTable';\n\n// context Menu\nexport { default as ContextMenu } from './context-menu/contextMenuContainer';\nexport {\n default as ContextMenuTrigger,\n} from './context-menu/trigger/ContextMenuTrigger';\n\n// modal\nexport { default as Modal } from './modal/Modal';\n\n// background\nexport { default as Background } from './background/backgroundContainer';\n\n// sticky Top\nexport { default as StickyTop } from './sticky-top/StickyTop';\n\n// demo\nexport { default as SimpleLineChart } from './demo/SimpleLineChart';\nexport { default as SimpleTable } from './demo/SimpleTable';\n\n// calendar\nexport { default as CalendarPicker } from './input/calendar/CalendarPicker';\n\n// preferences\nexport { default as Preferences } from './preferences/preferencesContainer';\n\n// tooltip\nexport { default as Tooltip } from './tooltip/Tooltip';\n\n// agenda\nexport {\n default as FasterAgenda,\n maskRowToEvent,\n} from './agenda/fasterAgendaContainer';\n\n// custom page\nexport { default as CustomPage } from './custom-page/customPageContainer';\n\n// tracking by address\nexport {\n default as TrackingByAddress,\n} from './tracking-address/trackingByAddressContainer';\n\n// entity info\nexport { default as EntityInfo } from './entity-info/entityInfoContainer';\n\n// map\nexport { default as FasterMap } from './map/fasterMapContainer';\n\n// cards\nexport {\n default as FasterCards,\n FasterCards as FasterCardsComponent,\n formToCard,\n} from './cards/fasterCardsContainer';\n","import _ from 'lodash';\n\n// dispatch to app settings (redux stores and local storage)\nconst dispatchPreferences = (preferences, tools) => {\n const { toggleSidebar, i18n } = tools;\n const { language, smallMenu } = preferences;\n\n if (!_.isNil(smallMenu)) {\n toggleSidebar(smallMenu);\n }\n\n if (language) {\n const currentLng = localStorage.getItem('faster-lang');\n\n if (currentLng !== language) {\n localStorage.setItem('faster-lang', language);\n i18n.changeLanguage(language);\n }\n }\n};\n\nexport { dispatchPreferences };\n","import { Component } from 'react';\n\nclass FormField extends Component {\n shouldComponentUpdate(nextProps, nextState) {\n if (this.props.label !== nextProps.label) {\n return true;\n }\n\n if (this.props.value !== nextProps.value) {\n return true;\n }\n\n if (this.props.visible !== nextProps.visible) {\n return true;\n }\n\n if (this.props.disabled !== nextProps.disabled) {\n return true;\n }\n\n return false;\n }\n}\n\nexport default FormField;\n","import React, { Fragment } from 'react';\n\nimport _ from 'lodash';\n\nimport { FIELD_TYPE, LIMIT_CHAR } from 'core/utils/constant';\nimport getValueMatch from 'core/utils/pattern/getValueMatch';\nimport { ThemedFormField } from 'components';\n\nimport FormField from './FormField';\n\nconst {\n multidates,\n date,\n decimal,\n number,\n text,\n textarea,\n time,\n datetime,\n} = FIELD_TYPE;\n\nexport const getInputType = type => {\n let typeHtml = 'number';\n switch (type) {\n case multidates:\n case date:\n typeHtml = 'date';\n break;\n case decimal:\n case number:\n typeHtml = 'number';\n break;\n case text:\n case textarea:\n typeHtml = 'text';\n break;\n case time:\n typeHtml = 'time';\n break;\n case datetime:\n typeHtml = 'datetime-local';\n break;\n default:\n typeHtml = null;\n break;\n }\n\n return typeHtml;\n};\n\nclass FormFieldInput extends FormField {\n constructor(props) {\n super(props);\n this.state = {\n prevValue: props.value,\n };\n }\n\n render() {\n const { prevValue } = this.state;\n const { type, visible, pattern, ...rest } = this.props;\n // console.log(`rerender ${this.props.label}`)\n\n if (getInputType(type) === null || _.isNil(visible)) return ;\n\n if ([text, textarea].includes(type)) {\n rest.maxLength = LIMIT_CHAR;\n\n if (pattern) {\n rest.onInput = data => {\n const sEn = data.target.selectionEnd;\n const newValue = getValueMatch(\n pattern,\n prevValue,\n data.target.value,\n sEn\n );\n\n this.setState({ prevValue: newValue });\n data.target.value = newValue;\n };\n }\n }\n\n if ([number, decimal].includes(type)) {\n rest.onInput = data => {\n if (data.target.value.length > LIMIT_CHAR) {\n data.target.value = data.target.value.slice(0, LIMIT_CHAR);\n }\n };\n }\n\n return (\n \n );\n }\n}\n\nexport default FormFieldInput;\n","module.exports = \"data:image/png;base64,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\"","import { useEffect, useState } from 'react';\nimport axios from 'axios';\n\nexport function useApi(func, data, defaultValue = undefined, xhrParams) {\n const [state, setState] = useState({\n value: defaultValue,\n isPending: func && func.length === data.length + 1 ? true : false,\n });\n const { value, isPending } = state;\n\n useEffect(() => {\n let cancelled = false;\n let source = axios.CancelToken.source();\n\n const callAPI = (endpoint, params, cancelToken, xhrParams) => {\n const promise = params\n ? endpoint(...params, { cancelToken, ...xhrParams })\n : endpoint({ cancelToken, ...xhrParams });\n\n promise.then(response => {\n if (response && !cancelled) {\n setState({ value: response, isPending: false });\n }\n });\n };\n\n if (typeof func === 'function' && func.length === data.length + 1) {\n // console.log(func, data, 'call');\n callAPI(func, data, source.token, xhrParams);\n }\n\n return () => {\n cancelled = true;\n source.cancel('');\n };\n }, [func, data, xhrParams]);\n\n return [value, isPending];\n}\n"],"sourceRoot":""}