@evergis/react 3.1.14 → 3.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Dashboard/components/Chart/styled.d.ts +16 -0
- package/dist/components/Dashboard/components/DashboardHeader/index.d.ts +3 -0
- package/dist/components/Dashboard/components/FeatureCardButtons/index.d.ts +2 -0
- package/dist/components/Dashboard/components/FeatureCardHeader/index.d.ts +2 -0
- package/dist/components/Dashboard/components/FeatureCardTitle/index.d.ts +5 -0
- package/dist/components/Dashboard/components/Pagination/index.d.ts +1 -1
- package/dist/components/Dashboard/components/index.d.ts +4 -0
- package/dist/components/Dashboard/containers/RoundedBackgroundContainer/styled.d.ts +2 -0
- package/dist/components/Dashboard/headers/DashboardDefaultHeader/index.d.ts +3 -0
- package/dist/components/Dashboard/headers/DashboardDefaultHeader/styled.d.ts +8 -0
- package/dist/components/Dashboard/headers/FeatureCardDefaultHeader/components/HeaderTitle.d.ts +4 -0
- package/dist/components/Dashboard/headers/FeatureCardDefaultHeader/index.d.ts +5 -0
- package/dist/components/Dashboard/headers/FeatureCardDefaultHeader/styled.d.ts +12 -0
- package/dist/components/Dashboard/headers/FeatureCardGradientHeader/index.d.ts +3 -0
- package/dist/components/Dashboard/headers/FeatureCardGradientHeader/styled.d.ts +4 -0
- package/dist/components/Dashboard/headers/FeatureCardIconHeader/index.d.ts +3 -0
- package/dist/components/Dashboard/headers/FeatureCardIconHeader/styled.d.ts +6 -0
- package/dist/components/Dashboard/headers/FeatureCardSlideshowHeader/index.d.ts +3 -0
- package/dist/components/Dashboard/headers/FeatureCardSlideshowHeader/styled.d.ts +8 -0
- package/dist/components/Dashboard/headers/index.d.ts +7 -0
- package/dist/components/Dashboard/hooks/index.d.ts +1 -0
- package/dist/components/Dashboard/hooks/useDashboardHeader.d.ts +2 -2
- package/dist/components/Dashboard/hooks/useGlobalContext.d.ts +0 -1
- package/dist/components/Dashboard/hooks/useHeaderRender.d.ts +2 -0
- package/dist/components/Dashboard/hooks/useWidgetContext.d.ts +8 -0
- package/dist/components/Dashboard/index.d.ts +1 -0
- package/dist/components/Dashboard/styled.d.ts +1 -0
- package/dist/components/Dashboard/types.d.ts +2 -0
- package/dist/components/Dashboard/utils/getDashboardHeader.d.ts +2 -0
- package/dist/components/Dashboard/utils/getFeatureCardHeader.d.ts +2 -0
- package/dist/components/Dashboard/utils/index.d.ts +2 -0
- package/dist/components/LayerIcon/index.d.ts +5 -0
- package/dist/components/LayerIcon/styled.d.ts +2 -0
- package/dist/components/LayerTree/types.d.ts +0 -2
- package/dist/components/index.d.ts +1 -0
- package/dist/contexts/DashboardContext/types.d.ts +8 -2
- package/dist/contexts/FeatureCardContext/types.d.ts +3 -1
- package/dist/contexts/GlobalContext/types.d.ts +1 -3
- package/dist/index.js +1460 -701
- package/dist/index.js.map +1 -1
- package/dist/react.esm.js +1185 -451
- package/dist/react.esm.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
4
|
var uilibGl = require('@evergis/uilib-gl');
|
|
5
|
-
var
|
|
5
|
+
var React = require('react');
|
|
6
6
|
var styled = require('styled-components');
|
|
7
7
|
var charts = require('@evergis/charts');
|
|
8
8
|
var api = require('@evergis/api');
|
|
@@ -19,7 +19,7 @@ var turf = require('@turf/turf');
|
|
|
19
19
|
var MapGL = require('react-map-gl/mapbox');
|
|
20
20
|
require('@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css');
|
|
21
21
|
require('mapbox-gl/dist/mapbox-gl.css');
|
|
22
|
-
var react
|
|
22
|
+
var react = require('swiper/react');
|
|
23
23
|
|
|
24
24
|
const AddFeatureButton = ({ title, icon = "feature_add" /* , layerName, geometryType*/ }) => {
|
|
25
25
|
// const [, handleAddFeature] = useFeatureCreator(layerName, geometryType);
|
|
@@ -37,14 +37,18 @@ const ChartTooltipTable = styled.table `
|
|
|
37
37
|
}
|
|
38
38
|
`;
|
|
39
39
|
const ChartTooltip = styled(uilibGl.Flex) `
|
|
40
|
-
flex-direction: row;
|
|
41
|
-
align-items: center;
|
|
42
40
|
flex-wrap: nowrap;
|
|
41
|
+
background: rgb(48, 69, 79);
|
|
42
|
+
border-radius: 0.25rem;
|
|
43
|
+
color: white;
|
|
43
44
|
|
|
44
45
|
:not(:last-child) {
|
|
45
46
|
margin-bottom: 0.25rem;
|
|
46
47
|
}
|
|
47
48
|
`;
|
|
49
|
+
const ChartTooltipLabel = styled.div `
|
|
50
|
+
margin-right: 0.25rem;
|
|
51
|
+
`;
|
|
48
52
|
const ChartTooltipColor = styled.div `
|
|
49
53
|
width: 0.625rem;
|
|
50
54
|
height: 0.625rem;
|
|
@@ -90,6 +94,107 @@ const ChartWrapperContainer = styled.div `
|
|
|
90
94
|
position: relative;
|
|
91
95
|
width: 100%;
|
|
92
96
|
`;
|
|
97
|
+
const Tooltip = styled.div `
|
|
98
|
+
position: relative;
|
|
99
|
+
border-radius: 0.25rem;
|
|
100
|
+
background-color: rgba(28, 33, 48);
|
|
101
|
+
padding: 0.5rem;
|
|
102
|
+
box-shadow: 0 0.125rem 0.25rem 0 rgba(0, 0, 0, 0.15);
|
|
103
|
+
font-size: 0.75rem;
|
|
104
|
+
transform: ${({ transform }) => transform};
|
|
105
|
+
color: white;
|
|
106
|
+
|
|
107
|
+
:before {
|
|
108
|
+
position: absolute;
|
|
109
|
+
display: block;
|
|
110
|
+
content: "";
|
|
111
|
+
width: 0;
|
|
112
|
+
height: 0;
|
|
113
|
+
}
|
|
114
|
+
`;
|
|
115
|
+
const LineChartTooltipStyles = styled.createGlobalStyle `
|
|
116
|
+
.dashboardLineChartTooltip.${charts.lineChartClassNames.lineChartMouseLabel} {
|
|
117
|
+
.${charts.lineChartClassNames.lineChartLabelFlex} {
|
|
118
|
+
justify-content: center;
|
|
119
|
+
align-items: flex-end;
|
|
120
|
+
|
|
121
|
+
${Tooltip} {
|
|
122
|
+
margin: 0 0 12px 0;
|
|
123
|
+
|
|
124
|
+
:before {
|
|
125
|
+
top: auto;
|
|
126
|
+
bottom: 0;
|
|
127
|
+
left: 50%;
|
|
128
|
+
transform: translate(-50%, 100%);
|
|
129
|
+
border-left: 4px solid transparent;
|
|
130
|
+
border-right: 4px solid transparent;
|
|
131
|
+
border-top: 4px solid rgba(28, 33, 48, 0.9);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.${charts.lineChartClassNames.lineChartYScaleGlobal}, .${charts.lineChartClassNames.lineChartXScaleGlobal} {
|
|
138
|
+
.domain {
|
|
139
|
+
visibility: hidden;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.tick {
|
|
143
|
+
text {
|
|
144
|
+
fill: ${({ theme: { palette } }) => palette.textDisabled};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
line {
|
|
148
|
+
visibility: hidden;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.${charts.lineChartClassNames.lineChartXScaleGlobal} {
|
|
154
|
+
.tick {
|
|
155
|
+
:first-of-type {
|
|
156
|
+
text {
|
|
157
|
+
text-anchor: start;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
:last-of-type {
|
|
162
|
+
text {
|
|
163
|
+
text-anchor: end;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.${charts.lineChartClassNames.lineChartLine} {
|
|
170
|
+
stroke-width: 2px;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.${charts.lineChartClassNames.lineChartLabel} {
|
|
174
|
+
color: ${({ theme: { palette } }) => palette.textPrimary};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.${charts.lineChartClassNames.lineChartMouseCircle} {
|
|
178
|
+
stroke: #ffffff;
|
|
179
|
+
stroke-width: 2px;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.${charts.lineChartClassNames.lineChartGridLineX} {
|
|
183
|
+
stroke: ${({ theme: { palette } }) => palette.element};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
text {
|
|
187
|
+
fill: ${({ theme: { palette } }) => palette.textDisabled};
|
|
188
|
+
}
|
|
189
|
+
`;
|
|
190
|
+
const BarChartStyles = styled.createGlobalStyle `
|
|
191
|
+
.dashboardBarChart {
|
|
192
|
+
.domain,
|
|
193
|
+
line {
|
|
194
|
+
display: none;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
`;
|
|
93
198
|
|
|
94
199
|
function range(start, stop, step) {
|
|
95
200
|
start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;
|
|
@@ -3684,31 +3789,31 @@ const isLayerService = (value) => isObject(value) && "name" in value;
|
|
|
3684
3789
|
|
|
3685
3790
|
const isNumeric = (number) => !isNaN(parseFloat(number)) && isFinite(number);
|
|
3686
3791
|
|
|
3687
|
-
const ConfigContext =
|
|
3688
|
-
const ConfigProvider =
|
|
3792
|
+
const ConfigContext = React.createContext({});
|
|
3793
|
+
const ConfigProvider = React.memo(({ children, config }) => {
|
|
3689
3794
|
return jsxRuntime.jsx(ConfigContext.Provider, { value: { config }, children: children });
|
|
3690
3795
|
});
|
|
3691
3796
|
|
|
3692
|
-
const DashboardContext =
|
|
3693
|
-
const DashboardProvider =
|
|
3797
|
+
const DashboardContext = React.createContext({});
|
|
3798
|
+
const DashboardProvider = React.memo(({ children, ...props }) => {
|
|
3694
3799
|
return jsxRuntime.jsx(DashboardContext.Provider, { value: props, children: children });
|
|
3695
3800
|
});
|
|
3696
3801
|
|
|
3697
|
-
const FeatureCardContext =
|
|
3698
|
-
const FeatureCardProvider =
|
|
3802
|
+
const FeatureCardContext = React.createContext(null);
|
|
3803
|
+
const FeatureCardProvider = React.memo(({ settings, children }) => jsxRuntime.jsx(FeatureCardContext.Provider, { value: settings, children: children }));
|
|
3699
3804
|
|
|
3700
|
-
const GlobalContext =
|
|
3701
|
-
const GlobalProvider =
|
|
3805
|
+
const GlobalContext = React.createContext({});
|
|
3806
|
+
const GlobalProvider = React.memo(({ children, ...props }) => {
|
|
3702
3807
|
return jsxRuntime.jsx(GlobalContext.Provider, { value: props, children: children });
|
|
3703
3808
|
});
|
|
3704
3809
|
|
|
3705
|
-
const MapContext =
|
|
3810
|
+
const MapContext = React.createContext({});
|
|
3706
3811
|
|
|
3707
3812
|
const MapProvider = ({ basemapItems, defaultBasemap, children }) => {
|
|
3708
|
-
const map =
|
|
3709
|
-
const draw =
|
|
3710
|
-
const [loaded, setLoaded] =
|
|
3711
|
-
const [basemapName, setBasemapName] =
|
|
3813
|
+
const map = React.useRef();
|
|
3814
|
+
const draw = React.useRef();
|
|
3815
|
+
const [loaded, setLoaded] = React.useState(false);
|
|
3816
|
+
const [basemapName, setBasemapName] = React.useState(defaultBasemap);
|
|
3712
3817
|
return (jsxRuntime.jsx(MapContext.Provider, { value: {
|
|
3713
3818
|
map,
|
|
3714
3819
|
draw,
|
|
@@ -3727,12 +3832,12 @@ exports.BaseMapTheme = void 0;
|
|
|
3727
3832
|
BaseMapTheme["Dark"] = "dark";
|
|
3728
3833
|
})(exports.BaseMapTheme || (exports.BaseMapTheme = {}));
|
|
3729
3834
|
|
|
3730
|
-
const ServerNotificationsContext =
|
|
3835
|
+
const ServerNotificationsContext = React.createContext({});
|
|
3731
3836
|
|
|
3732
3837
|
const useServerNotifications = (url, initialized) => {
|
|
3733
|
-
const hubConnection =
|
|
3734
|
-
const [connection, setConnection] =
|
|
3735
|
-
|
|
3838
|
+
const hubConnection = React.useRef(null);
|
|
3839
|
+
const [connection, setConnection] = React.useState(null);
|
|
3840
|
+
React.useEffect(() => {
|
|
3736
3841
|
if (!initialized) {
|
|
3737
3842
|
return;
|
|
3738
3843
|
}
|
|
@@ -3748,7 +3853,7 @@ const useServerNotifications = (url, initialized) => {
|
|
|
3748
3853
|
.catch(err => console.info("Ошибка:", err))
|
|
3749
3854
|
.finally(() => setConnection(hubConnection.current));
|
|
3750
3855
|
}, [initialized]); // eslint-disable-line
|
|
3751
|
-
|
|
3856
|
+
React.useEffect(() => {
|
|
3752
3857
|
if (!connection || connection.state !== "Connected") {
|
|
3753
3858
|
return;
|
|
3754
3859
|
}
|
|
@@ -3762,7 +3867,7 @@ const useServerNotifications = (url, initialized) => {
|
|
|
3762
3867
|
|
|
3763
3868
|
const ServerNotificationsProvider = ({ url, initialized, children }) => {
|
|
3764
3869
|
const connection = useServerNotifications(url, initialized);
|
|
3765
|
-
const addSubscription =
|
|
3870
|
+
const addSubscription = React.useCallback(async (payload) => {
|
|
3766
3871
|
if (!connection || connection.state !== "Connected" || !payload) {
|
|
3767
3872
|
return;
|
|
3768
3873
|
}
|
|
@@ -3776,7 +3881,7 @@ const ServerNotificationsProvider = ({ url, initialized, children }) => {
|
|
|
3776
3881
|
return Promise.resolve(null);
|
|
3777
3882
|
}
|
|
3778
3883
|
}, [connection]);
|
|
3779
|
-
const updateSubscription =
|
|
3884
|
+
const updateSubscription = React.useCallback(async (id, payload) => {
|
|
3780
3885
|
if (!connection || connection.state !== "Connected" || !id || !payload) {
|
|
3781
3886
|
return;
|
|
3782
3887
|
}
|
|
@@ -3787,7 +3892,7 @@ const ServerNotificationsProvider = ({ url, initialized, children }) => {
|
|
|
3787
3892
|
console.info(`Ошибка обновления подписки ${id}:`, err);
|
|
3788
3893
|
}
|
|
3789
3894
|
}, [connection]);
|
|
3790
|
-
const unsubscribeById =
|
|
3895
|
+
const unsubscribeById = React.useCallback(async (id) => {
|
|
3791
3896
|
if (!connection || connection.state !== "Connected" || !id) {
|
|
3792
3897
|
return;
|
|
3793
3898
|
}
|
|
@@ -3802,8 +3907,8 @@ const ServerNotificationsProvider = ({ url, initialized, children }) => {
|
|
|
3802
3907
|
};
|
|
3803
3908
|
|
|
3804
3909
|
const useWidgetContext = (type = exports.WidgetType.Dashboard) => {
|
|
3805
|
-
const { projectInfo, updateProject, layerInfos, geometryFilter, dashboardLayers, setDashboardLayer, pageIndex: projectPageIndex, selectedTabId: projectSelectedTabId, setSelectedTabId: setProjectSelectedTabId, dataSources: projectDataSources, loading: projectLoading, filters: projectFilters, changeFilters: projectChangeFilters, expandContainer: projectExpandContainer, expandedContainers: projectExpandedContainers, nextPage: projectNextPage, prevPage: projectPrevPage, changePage: projectChangePage, } =
|
|
3806
|
-
const { layerInfo, attributes, pageIndex: featurePageIndex, selectedTabId: featureSelectedTabId, setSelectedTabId: setFeatureSelectedTabId, dataSources: featureDataSources, loading: featureLoading, filters: featureFilters, changeFilters: featureChangeFilters, expandContainer: featureExpandContainer, expandedContainers: featureExpandedContainers, nextPage: featureNextPage, prevPage: featurePrevPage, changePage: featureChangePage, } =
|
|
3910
|
+
const { projectInfo, updateProject, layerInfos, geometryFilter, dashboardLayers, setDashboardLayer, components: dashboardComponents, pageIndex: projectPageIndex, selectedTabId: projectSelectedTabId, setSelectedTabId: setProjectSelectedTabId, dataSources: projectDataSources, loading: projectLoading, filters: projectFilters, changeFilters: projectChangeFilters, expandContainer: projectExpandContainer, expandedContainers: projectExpandedContainers, nextPage: projectNextPage, prevPage: projectPrevPage, changePage: projectChangePage, } = React.useContext(DashboardContext) || {};
|
|
3911
|
+
const { layerInfo, attributes, feature, closeFeatureCard, pageIndex: featurePageIndex, selectedTabId: featureSelectedTabId, setSelectedTabId: setFeatureSelectedTabId, dataSources: featureDataSources, loading: featureLoading, filters: featureFilters, changeFilters: featureChangeFilters, expandContainer: featureExpandContainer, expandedContainers: featureExpandedContainers, nextPage: featureNextPage, prevPage: featurePrevPage, changePage: featureChangePage, } = React.useContext(FeatureCardContext) || {};
|
|
3807
3912
|
return {
|
|
3808
3913
|
projectInfo,
|
|
3809
3914
|
layerInfos,
|
|
@@ -3813,6 +3918,9 @@ const useWidgetContext = (type = exports.WidgetType.Dashboard) => {
|
|
|
3813
3918
|
geometryFilter,
|
|
3814
3919
|
layerInfo,
|
|
3815
3920
|
attributes,
|
|
3921
|
+
feature,
|
|
3922
|
+
closeFeatureCard,
|
|
3923
|
+
components: dashboardComponents,
|
|
3816
3924
|
isLoading: type === exports.WidgetType.Dashboard ? projectLoading : featureLoading,
|
|
3817
3925
|
pageIndex: type === exports.WidgetType.Dashboard ? projectPageIndex : featurePageIndex,
|
|
3818
3926
|
filters: type === exports.WidgetType.Dashboard ? projectFilters : featureFilters,
|
|
@@ -3829,15 +3937,14 @@ const useWidgetContext = (type = exports.WidgetType.Dashboard) => {
|
|
|
3829
3937
|
};
|
|
3830
3938
|
|
|
3831
3939
|
const useGlobalContext = () => {
|
|
3832
|
-
const { t, language, themeName, api, ewktGeometry
|
|
3833
|
-
return
|
|
3940
|
+
const { t, language, themeName, api, ewktGeometry } = React.useContext(GlobalContext) || {};
|
|
3941
|
+
return React.useMemo(() => ({
|
|
3834
3942
|
t,
|
|
3835
3943
|
language,
|
|
3836
3944
|
themeName,
|
|
3837
3945
|
api,
|
|
3838
3946
|
ewktGeometry,
|
|
3839
|
-
|
|
3840
|
-
}), [language, t, api, ewktGeometry, themeName, LayerItemComponent]);
|
|
3947
|
+
}), [language, t, api, ewktGeometry, themeName]);
|
|
3841
3948
|
};
|
|
3842
3949
|
|
|
3843
3950
|
const HEIGHT_OFFSET = 20;
|
|
@@ -3920,12 +4027,12 @@ const useChartChange = ({ dataSources, chartId, width, height, relatedAttributes
|
|
|
3920
4027
|
const { t } = useGlobalContext();
|
|
3921
4028
|
const { layerInfos } = useWidgetContext();
|
|
3922
4029
|
const strokeColors = relatedAttributes.filter(({ chartAxis }) => chartAxis === "y").map(({ axisColor }) => axisColor);
|
|
3923
|
-
const ref =
|
|
4030
|
+
const ref = React.useRef({
|
|
3924
4031
|
path: null,
|
|
3925
4032
|
area: null,
|
|
3926
4033
|
points: [],
|
|
3927
4034
|
});
|
|
3928
|
-
const onChange =
|
|
4035
|
+
const onChange = React.useCallback((range) => {
|
|
3929
4036
|
const { path, area, points } = ref.current;
|
|
3930
4037
|
let filteredPoints = [...points];
|
|
3931
4038
|
if (range) {
|
|
@@ -3937,7 +4044,7 @@ const useChartChange = ({ dataSources, chartId, width, height, relatedAttributes
|
|
|
3937
4044
|
path && path.attr("d", lineGenerator(filteredPoints));
|
|
3938
4045
|
area && area.attr("d", areaGenerator(height)(filteredPoints));
|
|
3939
4046
|
}, [height, width]);
|
|
3940
|
-
const customize =
|
|
4047
|
+
const customize = React.useCallback(({ svg }) => {
|
|
3941
4048
|
svg.style("overflow", "visible");
|
|
3942
4049
|
svg
|
|
3943
4050
|
.selectAll(`.${charts.lineChartClassNames.lineChartXScaleGlobal} line,
|
|
@@ -4708,7 +4815,7 @@ const customStyles = [
|
|
|
4708
4815
|
];
|
|
4709
4816
|
|
|
4710
4817
|
const useMapContext = () => {
|
|
4711
|
-
return
|
|
4818
|
+
return React.useContext(MapContext);
|
|
4712
4819
|
};
|
|
4713
4820
|
|
|
4714
4821
|
const draw = new MapboxDraw({
|
|
@@ -4722,14 +4829,14 @@ const draw = new MapboxDraw({
|
|
|
4722
4829
|
});
|
|
4723
4830
|
const useMapDraw = (triggerDeps = []) => {
|
|
4724
4831
|
const { map, draw: drawContext, loaded, basemapName } = useMapContext();
|
|
4725
|
-
|
|
4832
|
+
React.useEffect(() => {
|
|
4726
4833
|
if (!loaded || !map.current) {
|
|
4727
4834
|
return;
|
|
4728
4835
|
}
|
|
4729
4836
|
drawContext.current = draw;
|
|
4730
4837
|
map.current.addControl(drawContext.current);
|
|
4731
4838
|
}, [loaded]); // eslint-disable-line
|
|
4732
|
-
|
|
4839
|
+
React.useEffect(() => {
|
|
4733
4840
|
if (map.current && map.current.hasControl(drawContext.current)) {
|
|
4734
4841
|
map.current.removeControl(drawContext.current);
|
|
4735
4842
|
map.current.addControl(drawContext.current);
|
|
@@ -4739,7 +4846,7 @@ const useMapDraw = (triggerDeps = []) => {
|
|
|
4739
4846
|
|
|
4740
4847
|
const useRedrawLayer = () => {
|
|
4741
4848
|
const { map } = useMapContext();
|
|
4742
|
-
return
|
|
4849
|
+
return React.useCallback((layerName) => {
|
|
4743
4850
|
const layerTileSource = map.current.getSource(layerName);
|
|
4744
4851
|
layerTileSource.setTiles(layerTileSource.tiles);
|
|
4745
4852
|
}, [map]);
|
|
@@ -4802,7 +4909,7 @@ const convertSpToTurfFeature = (geometry) => {
|
|
|
4802
4909
|
|
|
4803
4910
|
const useZoomToFeatures = () => {
|
|
4804
4911
|
const { map } = useMapContext();
|
|
4805
|
-
return
|
|
4912
|
+
return React.useCallback((features, padding) => {
|
|
4806
4913
|
if (!features) {
|
|
4807
4914
|
return;
|
|
4808
4915
|
}
|
|
@@ -4816,7 +4923,7 @@ const useZoomToFeatures = () => {
|
|
|
4816
4923
|
|
|
4817
4924
|
const useZoomToPoint = () => {
|
|
4818
4925
|
const { map } = useMapContext();
|
|
4819
|
-
return
|
|
4926
|
+
return React.useCallback((options, callback) => {
|
|
4820
4927
|
if (map.current) {
|
|
4821
4928
|
if (callback) {
|
|
4822
4929
|
map.current.once("moveend", () => {
|
|
@@ -4833,8 +4940,8 @@ const useZoomToPoint = () => {
|
|
|
4833
4940
|
|
|
4834
4941
|
const useLayerParams = (layer) => {
|
|
4835
4942
|
const { api } = useGlobalContext();
|
|
4836
|
-
const [layerParams, setLayerParams] =
|
|
4837
|
-
|
|
4943
|
+
const [layerParams, setLayerParams] = React.useState({});
|
|
4944
|
+
React.useEffect(() => {
|
|
4838
4945
|
if (layer?.type !== "QueryLayerService") {
|
|
4839
4946
|
return;
|
|
4840
4947
|
}
|
|
@@ -4847,27 +4954,27 @@ const useLayerParams = (layer) => {
|
|
|
4847
4954
|
};
|
|
4848
4955
|
|
|
4849
4956
|
const useServerNotificationsContext = () => {
|
|
4850
|
-
return
|
|
4957
|
+
return React.useContext(ServerNotificationsContext);
|
|
4851
4958
|
};
|
|
4852
4959
|
|
|
4853
4960
|
const useDebouncedCallback = (interval) => {
|
|
4854
|
-
return
|
|
4961
|
+
return React.useMemo(() => debounce((cb) => {
|
|
4855
4962
|
cb();
|
|
4856
4963
|
}, interval), [interval]);
|
|
4857
4964
|
};
|
|
4858
4965
|
|
|
4859
4966
|
const useToggle = (initial) => {
|
|
4860
|
-
const [state, setState] =
|
|
4861
|
-
const toggle =
|
|
4967
|
+
const [state, setState] = React.useState(initial !== undefined ? initial : false);
|
|
4968
|
+
const toggle = React.useCallback(() => setState(!state), [state]);
|
|
4862
4969
|
return [state, toggle, setState];
|
|
4863
4970
|
};
|
|
4864
4971
|
|
|
4865
4972
|
const DEBOUNCE_DELAY = 144;
|
|
4866
4973
|
const useWindowResize = (callback, delay) => {
|
|
4867
|
-
const debounceCallback =
|
|
4974
|
+
const debounceCallback = React.useMemo(() => {
|
|
4868
4975
|
return callback ? debounce(callback, delay || DEBOUNCE_DELAY) : undefined;
|
|
4869
4976
|
}, [callback, delay]);
|
|
4870
|
-
|
|
4977
|
+
React.useEffect(() => {
|
|
4871
4978
|
debounceCallback && window.addEventListener("resize", debounceCallback);
|
|
4872
4979
|
return () => debounceCallback && window.removeEventListener("resize", debounceCallback);
|
|
4873
4980
|
}, [debounceCallback]);
|
|
@@ -4875,8 +4982,8 @@ const useWindowResize = (callback, delay) => {
|
|
|
4875
4982
|
|
|
4876
4983
|
const useLayerGroupMenu = () => {
|
|
4877
4984
|
const [isMenuOpen, toggleMenu] = useToggle(false);
|
|
4878
|
-
const options =
|
|
4879
|
-
const selectOption =
|
|
4985
|
+
const options = React.useMemo(() => [], []);
|
|
4986
|
+
const selectOption = React.useCallback(() => {
|
|
4880
4987
|
// ...
|
|
4881
4988
|
}, [toggleMenu]);
|
|
4882
4989
|
return {
|
|
@@ -4891,7 +4998,7 @@ const LayerGroup = ({ group, onlyMainTools }) => {
|
|
|
4891
4998
|
const { projectInfo, updateProject } = useWidgetContext();
|
|
4892
4999
|
const { pageIndex } = useWidgetPage();
|
|
4893
5000
|
const { isMenuOpen, toggleMenu, options, selectOption } = useLayerGroupMenu();
|
|
4894
|
-
const onToggleExpand =
|
|
5001
|
+
const onToggleExpand = React.useCallback((name, isExpanded) => {
|
|
4895
5002
|
if (!projectInfo) {
|
|
4896
5003
|
return;
|
|
4897
5004
|
}
|
|
@@ -4900,7 +5007,7 @@ const LayerGroup = ({ group, onlyMainTools }) => {
|
|
|
4900
5007
|
page.layers = findAnd.changeProps(projectInfo.content.items, { name }, { isExpanded });
|
|
4901
5008
|
updateProject(newProjectInfo);
|
|
4902
5009
|
}, [pageIndex, projectInfo, updateProject]);
|
|
4903
|
-
const onToggleVisibility =
|
|
5010
|
+
const onToggleVisibility = React.useCallback((name, isVisible) => {
|
|
4904
5011
|
if (!projectInfo) {
|
|
4905
5012
|
return;
|
|
4906
5013
|
}
|
|
@@ -4944,11 +5051,11 @@ const treeNodesToProjectItems = (currentProjectItems, treeNodes) => {
|
|
|
4944
5051
|
return combineProjectItems(treeNodes);
|
|
4945
5052
|
};
|
|
4946
5053
|
|
|
4947
|
-
const LayerTree = ({ layers,
|
|
4948
|
-
const { projectInfo, updateProject } = useWidgetContext();
|
|
5054
|
+
const LayerTree = ({ layers, onlyMainTools }) => {
|
|
5055
|
+
const { projectInfo, updateProject, components: { LayerItem } } = useWidgetContext();
|
|
4949
5056
|
const { pageIndex } = useWidgetPage();
|
|
4950
|
-
const nodes =
|
|
4951
|
-
const onUpdate =
|
|
5057
|
+
const nodes = React.useMemo(() => layers?.map(layer => createTreeNode(layer, LayerItem, onlyMainTools)), [LayerItem, layers, onlyMainTools]);
|
|
5058
|
+
const onUpdate = React.useCallback((updatedNodes) => {
|
|
4952
5059
|
const newProjectInfo = JSON.parse(JSON.stringify(projectInfo));
|
|
4953
5060
|
const page = getPagesFromProjectInfo(newProjectInfo)?.[pageIndex - 1];
|
|
4954
5061
|
if (!page) {
|
|
@@ -5229,6 +5336,18 @@ const AttributeLabel = styled(uilibGl.Description) `
|
|
|
5229
5336
|
margin-bottom: ${({ forCheckbox }) => (forCheckbox ? "0.75rem" : "0.25rem")} !important;
|
|
5230
5337
|
padding-left: ${({ isEdit }) => (isEdit ? "0.5rem" : "0")};
|
|
5231
5338
|
`;
|
|
5339
|
+
const FeatureControls = styled(uilibGl.Flex) `
|
|
5340
|
+
align-items: center;
|
|
5341
|
+
gap: 1rem;
|
|
5342
|
+
flex-wrap: nowrap;
|
|
5343
|
+
position: relative;
|
|
5344
|
+
flex-shrink: 0;
|
|
5345
|
+
|
|
5346
|
+
button {
|
|
5347
|
+
padding: 0;
|
|
5348
|
+
width: auto;
|
|
5349
|
+
}
|
|
5350
|
+
`;
|
|
5232
5351
|
|
|
5233
5352
|
const getAttributeByName = (attributeName, attributes) => {
|
|
5234
5353
|
return Array.isArray(attributeName)
|
|
@@ -5254,7 +5373,7 @@ const formatElementValue = ({ t, value, elementConfig, attributes, wrap, }) => {
|
|
|
5254
5373
|
: valueOrDefault;
|
|
5255
5374
|
if (!wrap)
|
|
5256
5375
|
return resultValue;
|
|
5257
|
-
return (jsxRuntime.jsxs(
|
|
5376
|
+
return (jsxRuntime.jsxs(React.Fragment, { children: [tagView ? (jsxRuntime.jsx(DashboardChip$1, { text: resultValue, "$bgColor": bgColor, "$fontColor": fontColor, "$fontSize": fontSize, "$radius": radius, style: style })) : (jsxRuntime.jsx(ElementValueWrapper, { "data-id": id, "data-templatename": templateName, style: style, children: resultValue })), withDivider && jsxRuntime.jsx(uilibGl.Divider, {})] }, id));
|
|
5258
5377
|
};
|
|
5259
5378
|
|
|
5260
5379
|
const getAttributeValue = (element, attributes) => {
|
|
@@ -5287,7 +5406,7 @@ const getChartMarkers = (items, markers) => {
|
|
|
5287
5406
|
})) || []);
|
|
5288
5407
|
};
|
|
5289
5408
|
|
|
5290
|
-
const ContainersGroupContainer =
|
|
5409
|
+
const ContainersGroupContainer = React.memo(({ elementConfig, type, renderElement }) => {
|
|
5291
5410
|
const { expandedContainers } = useWidgetContext(type);
|
|
5292
5411
|
const { id, children, options, style } = elementConfig || {};
|
|
5293
5412
|
const { column, expandable, expanded } = options || {};
|
|
@@ -5296,7 +5415,7 @@ const ContainersGroupContainer = react.memo(({ elementConfig, type, renderElemen
|
|
|
5296
5415
|
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsx(Container, { style: style, isColumn: isColumn, children: jsxRuntime.jsx(ContainerChildren, { items: children, elementConfig: elementConfig, isColumn: isColumn, isMain: id?.startsWith(CONFIG_PAGE_ID), renderElement: renderElement }) }))] }));
|
|
5297
5416
|
});
|
|
5298
5417
|
|
|
5299
|
-
const OneColumnContainer =
|
|
5418
|
+
const OneColumnContainer = React.memo(({ elementConfig, renderElement }) => {
|
|
5300
5419
|
const { options, style } = elementConfig || {};
|
|
5301
5420
|
const { innerTemplateStyle, hideEmpty } = options || {};
|
|
5302
5421
|
const value = renderElement({ id: "value" });
|
|
@@ -5306,10 +5425,10 @@ const OneColumnContainer = react.memo(({ elementConfig, renderElement }) => {
|
|
|
5306
5425
|
return (jsxRuntime.jsxs(Container, { style: innerTemplateStyle || style, children: [jsxRuntime.jsxs(ContainerAlias, { hasBottomMargin: true, children: [renderElement({ id: "alias" }), renderElement({ id: "tooltip" })] }), jsxRuntime.jsxs(ContainerValue, { children: [value, hasUnits && jsxRuntime.jsx(ContainerUnits, { children: renderElement({ id: "units" }) })] })] }));
|
|
5307
5426
|
});
|
|
5308
5427
|
|
|
5309
|
-
const TwoColumnContainer =
|
|
5428
|
+
const TwoColumnContainer = React.memo(({ config, elementConfig, type, renderElement }) => {
|
|
5310
5429
|
const { selectedTabId, layerInfo, attributes } = useWidgetContext(type);
|
|
5311
5430
|
const { attributes: renderAttributes } = elementConfig?.options || {};
|
|
5312
|
-
const renderContainer =
|
|
5431
|
+
const renderContainer = React.useCallback((element, attribute) => {
|
|
5313
5432
|
const { options, style, children } = element || {};
|
|
5314
5433
|
const { hideEmpty, innerTemplateStyle } = options || {};
|
|
5315
5434
|
const hasUnits = children?.some(({ id }) => id === "units");
|
|
@@ -5359,7 +5478,7 @@ const InnerContainerWrapper = styled.div `
|
|
|
5359
5478
|
opacity: ${({ hasAnyFilter, isFiltered }) => (isFiltered ? 1 : hasAnyFilter ? FILTERED_VALUE_OPACITY / 100 : 1)};
|
|
5360
5479
|
`;
|
|
5361
5480
|
|
|
5362
|
-
const DataSourceInnerContainer =
|
|
5481
|
+
const DataSourceInnerContainer = React.memo(({ config, elementConfig, feature, maxValue, type, index, innerComponent }) => {
|
|
5363
5482
|
const { t } = useGlobalContext();
|
|
5364
5483
|
const { expandedContainers, selectedTabId, setSelectedTabId, dataSources } = useWidgetContext(type);
|
|
5365
5484
|
const { pageIndex, currentPage } = useWidgetPage(type);
|
|
@@ -5371,12 +5490,12 @@ const DataSourceInnerContainer = react.memo(({ config, elementConfig, feature, m
|
|
|
5371
5490
|
});
|
|
5372
5491
|
const { options, children } = elementConfig || {};
|
|
5373
5492
|
const { relatedDataSource, filterName, column } = options || {};
|
|
5374
|
-
const aliasElement =
|
|
5375
|
-
const valueElement =
|
|
5376
|
-
const aliasAttribute =
|
|
5493
|
+
const aliasElement = React.useMemo(() => children?.find(({ id }) => id === "alias"), [children]);
|
|
5494
|
+
const valueElement = React.useMemo(() => children?.find(({ id }) => id === "value"), [children]);
|
|
5495
|
+
const aliasAttribute = React.useMemo(() => (aliasElement ? attributes?.find(({ name }) => name === aliasElement.attributeName) : null), [aliasElement, attributes]);
|
|
5377
5496
|
const value = aliasAttribute?.value;
|
|
5378
5497
|
const InnerContainer = innerComponent;
|
|
5379
|
-
const data =
|
|
5498
|
+
const data = React.useMemo(() => getDataFromRelatedFeatures({
|
|
5380
5499
|
t,
|
|
5381
5500
|
config: elementConfig,
|
|
5382
5501
|
filters: currentPage?.filters,
|
|
@@ -5399,7 +5518,7 @@ const DataSourceInnerContainer = react.memo(({ config, elementConfig, feature, m
|
|
|
5399
5518
|
valueElement?.attributeName
|
|
5400
5519
|
]);
|
|
5401
5520
|
const { hasAnyFilter, isFiltered, onFilter } = useFeatureFilters(type, filterName, data);
|
|
5402
|
-
const render =
|
|
5521
|
+
const render = React.useMemo(() => getRenderElement({
|
|
5403
5522
|
config,
|
|
5404
5523
|
elementConfig,
|
|
5405
5524
|
attributes,
|
|
@@ -5530,7 +5649,7 @@ const ProgressTotal = styled(uilibGl.Flex) `
|
|
|
5530
5649
|
margin-top: 1rem;
|
|
5531
5650
|
`;
|
|
5532
5651
|
|
|
5533
|
-
const DataSourceProgressContainer =
|
|
5652
|
+
const DataSourceProgressContainer = React.memo(({ config, elementConfig, type, innerComponent, renderElement }) => {
|
|
5534
5653
|
const { t } = useGlobalContext();
|
|
5535
5654
|
const { dataSources, expandedContainers } = useWidgetContext(type);
|
|
5536
5655
|
const { dataSource, layerInfo } = useRelatedDataSourceAttributes({
|
|
@@ -5544,17 +5663,17 @@ const DataSourceProgressContainer = react.memo(({ config, elementConfig, type, i
|
|
|
5544
5663
|
const valueElement = children?.find(item => item.id === "value");
|
|
5545
5664
|
const unitsElement = children?.find(item => item.id === "units");
|
|
5546
5665
|
const { sliceItems, checkIsSliced, showMore, onShowMore } = useShownOtherItems(options);
|
|
5547
|
-
const totalUnits =
|
|
5666
|
+
const totalUnits = React.useMemo(() => unitsElement?.type === "attributeUnits"
|
|
5548
5667
|
? attributes?.find(({ attributeName }) => attributeName === unitsElement.attributeName)?.stringFormat
|
|
5549
5668
|
?.unitsLabel
|
|
5550
5669
|
: dataSource?.features?.[0]?.attributes[unitsElement?.attributeName], [attributes, dataSource?.features, unitsElement?.attributeName, unitsElement?.type]);
|
|
5551
|
-
const totalValue =
|
|
5670
|
+
const totalValue = React.useMemo(() => {
|
|
5552
5671
|
const attribute = attributes?.find(({ attributeName }) => attributeName === valueElement?.attributeName);
|
|
5553
5672
|
const { type: attributeType, stringFormat } = attribute || {};
|
|
5554
5673
|
const result = dataSource?.features?.reduce((total, feature) => total + feature.attributes[valueElement?.attributeName], 0);
|
|
5555
5674
|
return formatAttributeValue({ t, type: attributeType, value: result, stringFormat, noUnits: !!unitsElement?.type });
|
|
5556
5675
|
}, [attributes, dataSource?.features, unitsElement?.type, valueElement?.attributeName]);
|
|
5557
|
-
const currentMaxValue =
|
|
5676
|
+
const currentMaxValue = React.useMemo(() => {
|
|
5558
5677
|
if (typeof maxValue === "string") {
|
|
5559
5678
|
return dataSource?.features?.[0]?.attributes[maxValue];
|
|
5560
5679
|
}
|
|
@@ -5570,7 +5689,7 @@ const DataSourceProgressContainer = react.memo(({ config, elementConfig, type, i
|
|
|
5570
5689
|
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), !isVisible ? null : dataSource ? (jsxRuntime.jsxs(DataSourceProgressContainerWrapper, { children: [sliceItems(dataSource?.features)?.map((feature, index) => (jsxRuntime.jsx(DataSourceInnerContainer, { type: type, index: index, feature: feature, config: config, elementConfig: elementConfig, maxValue: currentMaxValue, innerComponent: innerComponent }, index))), checkIsSliced(dataSource?.features) && (jsxRuntime.jsx(ContainerToggler, { toggled: showMore, onClick: onShowMore, children: showMore ? t("hide", { ns: "dashboard" }) : t("showAll", { ns: "dashboard" }) })), showTotal && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(uilibGl.Divider, {}), jsxRuntime.jsxs(ProgressTotal, { children: [jsxRuntime.jsx(ProgressTotalTitle, { children: t("total", { ns: "dashboard" }) }), jsxRuntime.jsxs(ProgressValue, { children: [totalValue, jsxRuntime.jsx(ProgressUnits, { children: totalUnits })] })] })] }))] })) : (jsxRuntime.jsx(ContainerLoading, {})), jsxRuntime.jsx(HiddenTitleItems, { elementConfig: elementConfig, config: config, type: type })] }));
|
|
5571
5690
|
});
|
|
5572
5691
|
|
|
5573
|
-
const ProgressContainer =
|
|
5692
|
+
const ProgressContainer = React.memo(({ type, elementConfig, feature, maxValue, index, renderElement }) => {
|
|
5574
5693
|
const { t } = useGlobalContext();
|
|
5575
5694
|
const { dataSources } = useWidgetContext(type);
|
|
5576
5695
|
const { attributes } = useRelatedDataSourceAttributes({
|
|
@@ -5588,22 +5707,22 @@ const ProgressContainer = react.memo(({ type, elementConfig, feature, maxValue,
|
|
|
5588
5707
|
const value = !lodash.isNil(valueAttribute?.value) ? +valueAttribute.value : +valueElement.value || 0;
|
|
5589
5708
|
const currentMaxValue = (maxValue || optionMaxValue);
|
|
5590
5709
|
const width = `${Math.min(100, (value / currentMaxValue) * 100).toFixed(2)}%`;
|
|
5591
|
-
const renderTooltipAlias =
|
|
5710
|
+
const renderTooltipAlias = React.useMemo(() => renderElement({
|
|
5592
5711
|
id: "alias",
|
|
5593
5712
|
wrap: false
|
|
5594
5713
|
}), [renderElement]);
|
|
5595
|
-
const renderTooltipValue =
|
|
5714
|
+
const renderTooltipValue = React.useMemo(() => renderElement({
|
|
5596
5715
|
id: "value",
|
|
5597
5716
|
wrap: false
|
|
5598
5717
|
}), [renderElement]);
|
|
5599
|
-
const renderAlias =
|
|
5600
|
-
const renderValue =
|
|
5601
|
-
const renderIcon =
|
|
5718
|
+
const renderAlias = React.useMemo(() => renderElement({ id: "alias" }), [renderElement]);
|
|
5719
|
+
const renderValue = React.useMemo(() => renderElement({ id: "value" }), [renderElement]);
|
|
5720
|
+
const renderIcon = React.useMemo(() => renderElement({
|
|
5602
5721
|
id: "icon",
|
|
5603
5722
|
wrap: false
|
|
5604
5723
|
}), [renderElement]);
|
|
5605
|
-
const renderTooltip =
|
|
5606
|
-
const color =
|
|
5724
|
+
const renderTooltip = React.useMemo(() => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ProgressTooltipAlias, { children: renderTooltipAlias }), jsxRuntime.jsxs(ProgressTooltipValueContainer, { children: [jsxRuntime.jsx(ProgressTooltipValue, { children: renderTooltipValue }), jsxRuntime.jsx(ProgressTooltipValueOf, { children: t("of", { ns: "dashboard" }) }), jsxRuntime.jsx("div", { children: formatAttributeValue({ t, type: valueType, value: currentMaxValue, stringFormat }) })] })] })), [currentMaxValue, renderTooltipAlias, renderTooltipValue, stringFormat, t, valueType]);
|
|
5725
|
+
const color = React.useMemo(() => colorAttribute
|
|
5607
5726
|
? attributes?.find(({ name }) => name === colorAttribute)?.value
|
|
5608
5727
|
: colors?.[index] || bgColor, [attributes, bgColor, colorAttribute, colors, index]);
|
|
5609
5728
|
return (jsxRuntime.jsx(uilibGl.Tooltip, { content: renderTooltip, placement: "top", arrow: true, children: ref => (jsxRuntime.jsxs(ProgressContainerWrapper, { ref: ref, style: innerTemplateStyle || style, children: [renderIcon && jsxRuntime.jsx(ProgressIcon, { children: renderIcon }), jsxRuntime.jsxs(ProgressContent, { children: [!hideTitle && (jsxRuntime.jsxs(ProgressAlias, { children: [jsxRuntime.jsx("div", { children: renderAlias }), jsxRuntime.jsxs(ProgressValue, { children: [renderValue, unitsElement && jsxRuntime.jsx(ProgressUnits, { children: renderElement({ id: "units" }) })] })] })), jsxRuntime.jsxs(ProgressBarContainer, { innerValue: innerValue, children: [jsxRuntime.jsx(ProgressBarWrapper, { children: jsxRuntime.jsx(ProgressBar, { "$width": width, "$color": color }) }), !!(hideTitle || innerValue) && jsxRuntime.jsx(ProgressInnerValue, { children: renderValue })] })] })] })) }));
|
|
@@ -5702,7 +5821,6 @@ const AnyChartWrapper = styled.div `
|
|
|
5702
5821
|
`;
|
|
5703
5822
|
const BarChartWrapper = styled(AnyChartWrapper) `
|
|
5704
5823
|
width: 100%;
|
|
5705
|
-
max-width: ${MAX_CHART_WIDTH}px;
|
|
5706
5824
|
margin: 0 auto ${BAR_CHART_FOOTER_MARGIN}px;
|
|
5707
5825
|
|
|
5708
5826
|
:hover {
|
|
@@ -5787,29 +5905,29 @@ const TooltipContainer = styled.div `
|
|
|
5787
5905
|
}
|
|
5788
5906
|
`;
|
|
5789
5907
|
|
|
5790
|
-
const FiltersContainer =
|
|
5908
|
+
const FiltersContainer = React.memo(({ elementConfig, config, type, renderElement }) => {
|
|
5791
5909
|
const { filters, dataSources, expandedContainers } = useWidgetContext(type);
|
|
5792
5910
|
const { currentPage } = useWidgetPage(type);
|
|
5793
5911
|
const { filters: configFilters } = currentPage;
|
|
5794
5912
|
const { id, style, options } = elementConfig || {};
|
|
5795
5913
|
const { padding, bgColor, fontColor, fontSize, expandable, expanded } = options || {};
|
|
5796
|
-
const isLoading =
|
|
5797
|
-
const filterItems =
|
|
5798
|
-
const renderFilter =
|
|
5914
|
+
const isLoading = React.useMemo(() => checkIsLoading(dataSources, config, configFilters), [configFilters, config, dataSources]);
|
|
5915
|
+
const filterItems = React.useMemo(() => elementConfig?.children?.filter(child => child.options?.filterName), [elementConfig?.children]);
|
|
5916
|
+
const renderFilter = React.useCallback((filter, index) => {
|
|
5799
5917
|
const FilterComponent = getFilterComponent(filter.type);
|
|
5800
5918
|
return jsxRuntime.jsx(FilterComponent, { type: type, filter: filter, config: config, elementConfig: filter }, index);
|
|
5801
5919
|
}, [config, type]);
|
|
5802
5920
|
const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
|
|
5803
|
-
const selectedItems =
|
|
5921
|
+
const selectedItems = React.useMemo(() => getFilterSelectedItems(filterItems, filters, configFilters), [configFilters, filters, filterItems]);
|
|
5804
5922
|
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(uilibGl.Flex, { mb: !isVisible && selectedItems.length ? "2rem" : 0, children: jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }) }), isLoading && jsxRuntime.jsx(ContainerLoading, {}), !isLoading && isVisible && (jsxRuntime.jsx(FiltersContainerWrapper, { style: style, "$padding": padding, "$bgColor": bgColor, "$fontSize": fontSize, "$fontColor": fontColor, children: filterItems?.map(renderFilter) })), jsxRuntime.jsx(HiddenTitleItems, { elementConfig: elementConfig, config: config, type: type, filter: filterItems[0].options?.filterName })] }));
|
|
5805
5923
|
});
|
|
5806
5924
|
|
|
5807
|
-
const DefaultAttributesContainer =
|
|
5925
|
+
const DefaultAttributesContainer = React.memo(({ type, renderElement }) => {
|
|
5808
5926
|
const { attributes } = useWidgetContext(type);
|
|
5809
5927
|
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: attributes?.map(({ name }) => (jsxRuntime.jsx(Container, { children: renderElement({ id: name }) }, name))) }));
|
|
5810
5928
|
});
|
|
5811
5929
|
|
|
5812
|
-
const ChartContainer =
|
|
5930
|
+
const ChartContainer = React.memo(({ elementConfig, isVisible, type, renderElement }) => {
|
|
5813
5931
|
const { options, children } = elementConfig || {};
|
|
5814
5932
|
const { twoColumns, hideEmpty } = options || {};
|
|
5815
5933
|
const aliasElement = children.find(({ id }) => id === "alias");
|
|
@@ -5827,17 +5945,17 @@ const ChartContainer = react.memo(({ elementConfig, isVisible, type, renderEleme
|
|
|
5827
5945
|
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsxs(Container, { isColumn: true, children: [aliasElement && jsxRuntime.jsx(ContainerAlias, { hasBottomMargin: true, children: renderElement({ id: "alias" }) }), jsxRuntime.jsx(ContainerValue, { column: !twoColumns, alignItems: "center", children: hasItems ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ContainerChart, { children: renderElement({ id: "chart" }) }), jsxRuntime.jsx(ContainerLegend, { children: renderElement({ id: "legend" }) })] })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: "\u2014" })) })] }))] }));
|
|
5828
5946
|
});
|
|
5829
5947
|
|
|
5830
|
-
const PagesContainer =
|
|
5948
|
+
const PagesContainer = React.memo(({ type }) => {
|
|
5831
5949
|
const { config } = useWidgetConfig(type);
|
|
5832
5950
|
const { pageIndex, currentPage } = useWidgetPage(type);
|
|
5833
5951
|
const { selectedTabId, setSelectedTabId, expandedContainers, attributes } = useWidgetContext(type);
|
|
5834
5952
|
const { options } = config || {};
|
|
5835
|
-
const { column } = options || {};
|
|
5953
|
+
const { column, width } = options || {};
|
|
5836
5954
|
const isColumn = column === undefined || column;
|
|
5837
|
-
const filteredChildren =
|
|
5955
|
+
const filteredChildren = React.useMemo(() => !selectedTabId
|
|
5838
5956
|
? currentPage.children
|
|
5839
5957
|
: currentPage.children.filter(item => !item.options?.tabId || item.options.tabId === selectedTabId), [currentPage.children, selectedTabId]);
|
|
5840
|
-
const renderElement =
|
|
5958
|
+
const renderElement = React.useMemo(() => getRenderElement({
|
|
5841
5959
|
type,
|
|
5842
5960
|
config,
|
|
5843
5961
|
elementConfig: currentPage,
|
|
@@ -5857,14 +5975,14 @@ const PagesContainer = react.memo(({ type }) => {
|
|
|
5857
5975
|
setSelectedTabId,
|
|
5858
5976
|
type,
|
|
5859
5977
|
]);
|
|
5860
|
-
return (jsxRuntime.jsxs(
|
|
5978
|
+
return (jsxRuntime.jsxs("div", { style: { width }, children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: config, type: type, renderElement: renderElement }), jsxRuntime.jsx(Container, { isColumn: isColumn, isMain: true, children: jsxRuntime.jsx(ContainerChildren, { items: filteredChildren, isMain: true, renderElement: renderElement }) })] }));
|
|
5861
5979
|
});
|
|
5862
5980
|
|
|
5863
|
-
const TwoColumnsInnerContainer =
|
|
5981
|
+
const TwoColumnsInnerContainer = React.memo(({ renderElement }) => {
|
|
5864
5982
|
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs(TwoColumnContainerWrapper, { children: [jsxRuntime.jsxs(Container, { children: [jsxRuntime.jsx(ContainerAlias, { children: renderElement({ id: "firstAlias" }) }), jsxRuntime.jsx(ContainerValue, { big: true, children: renderElement({ id: "firstValue" }) })] }), jsxRuntime.jsxs(Container, { children: [jsxRuntime.jsx(ContainerAlias, { children: renderElement({ id: "secondAlias" }) }), jsxRuntime.jsx(ContainerValue, { big: true, children: renderElement({ id: "secondValue" }) })] })] }), renderElement({ id: "thirdContainer" })] }));
|
|
5865
5983
|
});
|
|
5866
5984
|
|
|
5867
|
-
const ImageContainerBg = styled.div `
|
|
5985
|
+
const ImageContainerBg$1 = styled.div `
|
|
5868
5986
|
position: absolute;
|
|
5869
5987
|
top: 0;
|
|
5870
5988
|
bottom: 0;
|
|
@@ -5924,9 +6042,9 @@ const ImageContainerWrapper = styled(uilibGl.Flex) `
|
|
|
5924
6042
|
}
|
|
5925
6043
|
`;
|
|
5926
6044
|
|
|
5927
|
-
const ImageContainer =
|
|
6045
|
+
const ImageContainer = React.memo(({ elementConfig, renderElement }) => {
|
|
5928
6046
|
const { style } = elementConfig || {};
|
|
5929
|
-
return (jsxRuntime.jsxs(ImageContainerWrapper, { style: style, children: [jsxRuntime.jsx(ImageContainerTitle, { children: renderElement({ id: "alias" }) }), jsxRuntime.jsx(ImageContainerText, { children: renderElement({ id: "text" }) }), renderElement({ id: "button" }), jsxRuntime.jsx(ImageContainerBg, { children: renderElement({ id: "image" }) })] }));
|
|
6047
|
+
return (jsxRuntime.jsxs(ImageContainerWrapper, { style: style, children: [jsxRuntime.jsx(ImageContainerTitle, { children: renderElement({ id: "alias" }) }), jsxRuntime.jsx(ImageContainerText, { children: renderElement({ id: "text" }) }), renderElement({ id: "button" }), jsxRuntime.jsx(ImageContainerBg$1, { children: renderElement({ id: "image" }) })] }));
|
|
5930
6048
|
});
|
|
5931
6049
|
|
|
5932
6050
|
const IconContainerWrapper = styled(uilibGl.Flex) `
|
|
@@ -5977,16 +6095,16 @@ const IconContainerText = styled.div `
|
|
|
5977
6095
|
color: ${({ theme: { palette } }) => palette.textSecondary};
|
|
5978
6096
|
`;
|
|
5979
6097
|
|
|
5980
|
-
const IconContainer =
|
|
6098
|
+
const IconContainer = React.memo(({ elementConfig, renderElement }) => {
|
|
5981
6099
|
return (jsxRuntime.jsxs(IconContainerWrapper, { style: elementConfig?.style, children: [jsxRuntime.jsxs(IconContainerHeaderWrapper, { children: [jsxRuntime.jsxs(IconContainerHeader, { children: [renderElement({ id: "icon" }), jsxRuntime.jsx(IconContainerTitle, { children: renderElement({ id: "alias" }) })] }), renderElement({ id: "link" })] }), jsxRuntime.jsx(IconContainerText, { children: renderElement({ id: "text" }) })] }));
|
|
5982
6100
|
});
|
|
5983
6101
|
|
|
5984
|
-
const DataSourceContainer =
|
|
6102
|
+
const DataSourceContainer = React.memo(({ config, elementConfig, type, innerComponent, renderElement }) => {
|
|
5985
6103
|
const { dataSources, expandedContainers } = useWidgetContext(type);
|
|
5986
6104
|
const { id, style, options } = elementConfig || {};
|
|
5987
6105
|
const { column = true, relatedDataSource, expandable, expanded } = options || {};
|
|
5988
6106
|
const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
|
|
5989
|
-
const dataSource =
|
|
6107
|
+
const dataSource = React.useMemo(() => dataSources?.find(({ name }) => name === relatedDataSource), [dataSources, relatedDataSource]);
|
|
5990
6108
|
if (!relatedDataSource)
|
|
5991
6109
|
return null;
|
|
5992
6110
|
if (dataSource && !dataSource.features) {
|
|
@@ -6075,26 +6193,26 @@ const ContainerTitle = styled(uilibGl.Flex) `
|
|
|
6075
6193
|
`}
|
|
6076
6194
|
`;
|
|
6077
6195
|
|
|
6078
|
-
const TitleContainer =
|
|
6196
|
+
const TitleContainer = React.memo(({ containerId, templateName, layerNames, fontColor, expandable, expanded, isVisible, elementConfig, renderElement, type, }) => {
|
|
6079
6197
|
const { expandContainer, expandedContainers, setDashboardLayer } = useWidgetContext(type);
|
|
6080
6198
|
const [layersVisibility, toggleVisibility] = useToggle(true);
|
|
6081
6199
|
const { palette } = styled.useTheme();
|
|
6082
6200
|
const { style, options } = elementConfig || {};
|
|
6083
6201
|
const { simple } = options || {};
|
|
6084
6202
|
const isLayers = templateName === exports.ContainerTemplate.Layers;
|
|
6085
|
-
const onClick =
|
|
6203
|
+
const onClick = React.useCallback(() => {
|
|
6086
6204
|
if (!expandable)
|
|
6087
6205
|
return;
|
|
6088
6206
|
expandContainer(containerId, expanded);
|
|
6089
6207
|
}, [containerId, expandContainer, expandable, expanded]);
|
|
6090
|
-
const onToggleVisibility =
|
|
6208
|
+
const onToggleVisibility = React.useCallback(() => {
|
|
6091
6209
|
toggleVisibility();
|
|
6092
6210
|
layerNames?.forEach(layerName => {
|
|
6093
6211
|
setDashboardLayer({ name: layerName, isVisible: !layersVisibility });
|
|
6094
6212
|
});
|
|
6095
6213
|
}, [layerNames, layersVisibility, setDashboardLayer, toggleVisibility]);
|
|
6096
|
-
const renderVisibility =
|
|
6097
|
-
const renderToggler =
|
|
6214
|
+
const renderVisibility = React.useMemo(() => isLayers && (jsxRuntime.jsx(uilibGl.FlexSpan, { mr: "-1rem", children: jsxRuntime.jsx(uilibGl.IconToggle, { kind: layersVisibility ? "password_show" : "password_hide", className: "feature-visible", isSelected: layersVisibility, onClick: onToggleVisibility }) })), [isLayers, layersVisibility, onToggleVisibility]);
|
|
6215
|
+
const renderToggler = React.useMemo(() => !!containerId &&
|
|
6098
6216
|
expandable && (jsxRuntime.jsx("div", { children: jsxRuntime.jsx(uilibGl.LegendToggler, { color: palette.icon, toggled: expandedContainers?.[containerId] !== undefined ? expandedContainers[containerId] : expanded, onClick: onClick }) })), [containerId, expandable, expanded, expandedContainers, onClick, palette.icon]);
|
|
6099
6217
|
return (jsxRuntime.jsx(Container, { isTitle: isVisible, style: style, children: jsxRuntime.jsxs(ContainerTitle, { simple: simple, children: [jsxRuntime.jsxs(ContainerIconTitle, { fontColor: fontColor, children: [renderElement({ id: "titleIcon", wrap: false }), renderElement({ id: "title" }), isLayers && renderToggler] }), !isLayers && renderToggler, renderVisibility] }) }));
|
|
6100
6218
|
});
|
|
@@ -6104,11 +6222,11 @@ const ContainerDivider = styled(uilibGl.Divider) `
|
|
|
6104
6222
|
border-color: ${({ theme: { palette }, $bgColor }) => $bgColor || palette.elementDeep};
|
|
6105
6223
|
`;
|
|
6106
6224
|
|
|
6107
|
-
const DividerContainer =
|
|
6225
|
+
const DividerContainer = React.memo(({ elementConfig, config }) => {
|
|
6108
6226
|
return (jsxRuntime.jsx(Container, { style: elementConfig?.style, children: jsxRuntime.jsx(ContainerDivider, { "$bgColor": config?.options?.bgColor }) }));
|
|
6109
6227
|
});
|
|
6110
6228
|
|
|
6111
|
-
const SlideshowContainer =
|
|
6229
|
+
const SlideshowContainer = React.memo(({ config, elementConfig, type }) => {
|
|
6112
6230
|
const { pageIndex, expandedContainers, selectedTabId, setSelectedTabId, dataSources } = useWidgetContext(type);
|
|
6113
6231
|
const { attributes, layerInfo } = useRelatedDataSourceAttributes({
|
|
6114
6232
|
type,
|
|
@@ -6118,7 +6236,7 @@ const SlideshowContainer = react.memo(({ config, elementConfig, type }) => {
|
|
|
6118
6236
|
const { id, options } = elementConfig || {};
|
|
6119
6237
|
const { expandable, expanded } = options || {};
|
|
6120
6238
|
const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
|
|
6121
|
-
const render =
|
|
6239
|
+
const render = React.useMemo(() => getRenderElement({
|
|
6122
6240
|
config,
|
|
6123
6241
|
elementConfig,
|
|
6124
6242
|
attributes,
|
|
@@ -6146,7 +6264,7 @@ const SlideshowContainer = react.memo(({ config, elementConfig, type }) => {
|
|
|
6146
6264
|
}) })] }))] }));
|
|
6147
6265
|
});
|
|
6148
6266
|
|
|
6149
|
-
const CameraContainer =
|
|
6267
|
+
const CameraContainer = React.memo(({ elementConfig, type, renderElement }) => {
|
|
6150
6268
|
const { expandedContainers } = useWidgetContext(type);
|
|
6151
6269
|
const { id, options, style } = elementConfig || {};
|
|
6152
6270
|
const { expandable, expanded } = options || {};
|
|
@@ -6232,30 +6350,31 @@ const SwiperContainer = styled.div `
|
|
|
6232
6350
|
}
|
|
6233
6351
|
`;
|
|
6234
6352
|
|
|
6235
|
-
const TabsContainer =
|
|
6353
|
+
const TabsContainer = React.memo(({ elementConfig, type }) => {
|
|
6236
6354
|
const { palette } = styled.useTheme();
|
|
6237
6355
|
const { selectedTabId, setSelectedTabId } = useWidgetContext(type);
|
|
6238
6356
|
const { options, style, children: tabs } = elementConfig || {};
|
|
6239
6357
|
const { radius, column, bgColor, noBg, onlyIcon, shownItems, maxLength = 12 } = options || {};
|
|
6240
|
-
const renderIcon =
|
|
6358
|
+
const renderIcon = React.useCallback((icon, active) => {
|
|
6241
6359
|
if (!icon)
|
|
6242
6360
|
return null;
|
|
6243
6361
|
if (!icon.includes("."))
|
|
6244
6362
|
return jsxRuntime.jsx(uilibGl.Icon, { kind: icon });
|
|
6245
6363
|
return icon.endsWith(".svg") ? (jsxRuntime.jsx(SvgImage, { url: icon, width: 16, fontColor: active ? palette.textContrast : palette.textSecondary })) : (jsxRuntime.jsx("img", { src: icon, alt: "" }));
|
|
6246
6364
|
}, [palette.textContrast, palette.textSecondary]);
|
|
6247
|
-
const onClick =
|
|
6365
|
+
const onClick = React.useCallback((id) => {
|
|
6248
6366
|
setSelectedTabId(id);
|
|
6249
6367
|
window.location.hash = `#${id}`;
|
|
6250
6368
|
}, [setSelectedTabId]);
|
|
6251
|
-
|
|
6369
|
+
React.useEffect(() => {
|
|
6252
6370
|
if (!selectedTabId) {
|
|
6253
6371
|
setSelectedTabId(tabs[0].id);
|
|
6254
6372
|
}
|
|
6255
6373
|
}, []);
|
|
6256
|
-
return (jsxRuntime.jsx(SwiperContainer, { style: style, children: jsxRuntime.jsx(react
|
|
6374
|
+
return (jsxRuntime.jsx(SwiperContainer, { style: style, children: jsxRuntime.jsx(react.Swiper, { spaceBetween: 0, slidesPerView: shownItems || 2, children: tabs.map(({ id, value, options: tabOptions }) => (jsxRuntime.jsxs(react.SwiperSlide, { children: [jsxRuntime.jsxs(TabContainer, { href: `#${id}`, active: selectedTabId === id, column: column, bgColor: bgColor, noBg: noBg, radius: radius, onlyIcon: onlyIcon, hasIcon: !!tabOptions?.icon, onClick: () => onClick(id), children: [renderIcon(tabOptions?.icon, selectedTabId === id), !onlyIcon && (jsxRuntime.jsx(TabValue, { children: jsxRuntime.jsx(TextTrim, { maxLength: maxLength, children: value }) }))] }), jsxRuntime.jsx(TabAnchor, { id: id })] }, id))) }) }));
|
|
6257
6375
|
});
|
|
6258
6376
|
|
|
6377
|
+
const ContainerIconValue = styled(uilibGl.Flex) ``;
|
|
6259
6378
|
const RoundedBackgroundContainerWrapper = styled(uilibGl.Flex) `
|
|
6260
6379
|
position: relative;
|
|
6261
6380
|
flex-direction: ${({ $bigIcon }) => ($bigIcon ? "row" : "column")};
|
|
@@ -6273,13 +6392,10 @@ const RoundedBackgroundContainerWrapper = styled(uilibGl.Flex) `
|
|
|
6273
6392
|
styled.css `
|
|
6274
6393
|
align-items: center;
|
|
6275
6394
|
|
|
6276
|
-
* {
|
|
6395
|
+
> * {
|
|
6277
6396
|
display: flex;
|
|
6278
6397
|
justify-content: center;
|
|
6279
6398
|
text-align: center;
|
|
6280
|
-
}
|
|
6281
|
-
|
|
6282
|
-
> * {
|
|
6283
6399
|
width: 100%;
|
|
6284
6400
|
}
|
|
6285
6401
|
`};
|
|
@@ -6312,8 +6428,32 @@ const RoundedBackgroundContainerWrapper = styled(uilibGl.Flex) `
|
|
|
6312
6428
|
}
|
|
6313
6429
|
`};
|
|
6314
6430
|
|
|
6431
|
+
${ContainerIconValue} {
|
|
6432
|
+
align-items: center;
|
|
6433
|
+
flex-direction: column;
|
|
6434
|
+
|
|
6435
|
+
${({ $big }) => $big &&
|
|
6436
|
+
styled.css `
|
|
6437
|
+
flex-direction: row;
|
|
6438
|
+
margin-bottom: 0.5rem;
|
|
6439
|
+
|
|
6440
|
+
> * {
|
|
6441
|
+
text-align: left;
|
|
6442
|
+
}
|
|
6443
|
+
|
|
6444
|
+
span[kind] {
|
|
6445
|
+
margin-right: 0.5rem;
|
|
6446
|
+
}
|
|
6447
|
+
|
|
6448
|
+
${ContainerValue} {
|
|
6449
|
+
width: auto;
|
|
6450
|
+
}
|
|
6451
|
+
`};
|
|
6452
|
+
}
|
|
6453
|
+
|
|
6315
6454
|
${ContainerValue} {
|
|
6316
6455
|
flex-direction: ${({ $inlineUnits }) => ($inlineUnits ? "row" : "column")};
|
|
6456
|
+
justify-content: ${({ $big }) => ($big ? "flex-start" : "flex-end")};
|
|
6317
6457
|
align-items: ${({ $inlineUnits }) => ($inlineUnits ? "center" : "flex-start")};
|
|
6318
6458
|
line-height: 1;
|
|
6319
6459
|
}
|
|
@@ -6328,7 +6468,7 @@ const RoundedBackgroundContainerWrapper = styled(uilibGl.Flex) `
|
|
|
6328
6468
|
`;
|
|
6329
6469
|
|
|
6330
6470
|
const ALIAS_DEFAULT_MAX_LENGTH = 28;
|
|
6331
|
-
const RoundedBackgroundContainer =
|
|
6471
|
+
const RoundedBackgroundContainer = React.memo(({ type, elementConfig, feature, renderElement }) => {
|
|
6332
6472
|
const { dataSources } = useWidgetContext(type);
|
|
6333
6473
|
const { attributes } = useRelatedDataSourceAttributes({
|
|
6334
6474
|
type,
|
|
@@ -6337,18 +6477,20 @@ const RoundedBackgroundContainer = react.memo(({ type, elementConfig, feature, r
|
|
|
6337
6477
|
feature
|
|
6338
6478
|
});
|
|
6339
6479
|
const { options, style, children } = elementConfig || {};
|
|
6340
|
-
const { maxLength, center, fontColor, innerTemplateStyle, inlineUnits, bigIcon, hideEmpty, colorAttribute } = options || {};
|
|
6480
|
+
const { maxLength, center, fontColor, innerTemplateStyle, inlineUnits, big, bigIcon, hideEmpty, colorAttribute } = options || {};
|
|
6341
6481
|
const aliasElement = children?.find(({ id }) => id === "alias");
|
|
6342
6482
|
const unitsElement = children?.find(({ id }) => id === "units");
|
|
6343
6483
|
const valueElement = children?.find(({ id }) => id === "value");
|
|
6344
6484
|
const value = renderElement({ id: "value" });
|
|
6345
|
-
const color =
|
|
6485
|
+
const color = React.useMemo(() => attributes?.find(({ name }) => name === colorAttribute)?.value || fontColor, [attributes, colorAttribute, fontColor]);
|
|
6486
|
+
const renderAlias = React.useMemo(() => (jsxRuntime.jsx(ContainerAlias, { style: aliasElement?.style, children: jsxRuntime.jsx(TextTrim, { maxLength: maxLength || ALIAS_DEFAULT_MAX_LENGTH, children: renderElement({ id: "alias", wrap: false }) }) })), [aliasElement?.style, maxLength, renderElement]);
|
|
6487
|
+
const renderValue = React.useMemo(() => (jsxRuntime.jsxs(ContainerValue, { style: valueElement?.style, big: true, children: [value, !!unitsElement && (jsxRuntime.jsx(ContainerUnits, { style: unitsElement?.style, children: renderElement({ id: "units" }) }))] })), [valueElement?.style, value, unitsElement, renderElement]);
|
|
6346
6488
|
if (!value && hideEmpty)
|
|
6347
6489
|
return null;
|
|
6348
|
-
return (jsxRuntime.jsxs(RoundedBackgroundContainerWrapper, { style: innerTemplateStyle || style, "$center": center, "$color": color, "$inlineUnits": inlineUnits, "$
|
|
6490
|
+
return (jsxRuntime.jsxs(RoundedBackgroundContainerWrapper, { style: innerTemplateStyle || style, "$center": center, "$color": color, "$inlineUnits": inlineUnits, "$big": big, "$bigIcon": bigIcon, children: [jsxRuntime.jsxs(ContainerIconValue, { children: [renderElement({ id: "icon", wrap: false }), big ? renderAlias : renderValue] }), big ? renderValue : renderAlias] }));
|
|
6349
6491
|
});
|
|
6350
6492
|
|
|
6351
|
-
const AddFeatureContainer =
|
|
6493
|
+
const AddFeatureContainer = React.memo(({ elementConfig }) => {
|
|
6352
6494
|
const { children, style } = elementConfig || {};
|
|
6353
6495
|
return (jsxRuntime.jsx(Container, { style: style, children: children
|
|
6354
6496
|
.filter(({ type }) => type === "button")
|
|
@@ -6371,21 +6513,20 @@ const LayersContainerWrapper = styled(Container) `
|
|
|
6371
6513
|
}
|
|
6372
6514
|
`;
|
|
6373
6515
|
|
|
6374
|
-
const LayersContainer =
|
|
6375
|
-
const { LayerItemComponent } = useGlobalContext();
|
|
6516
|
+
const LayersContainer = React.memo(({ type, elementConfig, renderElement }) => {
|
|
6376
6517
|
const { expandedContainers } = useWidgetContext(type);
|
|
6377
6518
|
const { currentPage } = useWidgetPage(type);
|
|
6378
6519
|
const { id, options, style } = elementConfig || {};
|
|
6379
6520
|
const { layerNames, expandable, expanded } = options || {};
|
|
6380
6521
|
const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
|
|
6381
|
-
const layers =
|
|
6522
|
+
const layers = React.useMemo(() => {
|
|
6382
6523
|
if (!currentPage?.layers)
|
|
6383
6524
|
return [];
|
|
6384
6525
|
if (!layerNames?.length)
|
|
6385
6526
|
return currentPage.layers;
|
|
6386
6527
|
return currentPage.layers.filter(({ name }) => layerNames.includes(name));
|
|
6387
6528
|
}, [currentPage?.layers, layerNames]);
|
|
6388
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsx(LayersContainerWrapper, { style: style, children: jsxRuntime.jsx(LayerTree, { layers: layers,
|
|
6529
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsx(LayersContainerWrapper, { style: style, children: jsxRuntime.jsx(LayerTree, { layers: layers, onlyMainTools: true }) }))] }));
|
|
6389
6530
|
});
|
|
6390
6531
|
|
|
6391
6532
|
const containerComponents = {
|
|
@@ -6414,157 +6555,480 @@ const containerComponents = {
|
|
|
6414
6555
|
|
|
6415
6556
|
const getContainerComponent = (innerTemplateName) => innerTemplateName ? containerComponents[innerTemplateName] || containerComponents.default : null;
|
|
6416
6557
|
|
|
6417
|
-
const getDataFromAttributes = (t, config, attributes) => {
|
|
6418
|
-
const colors = config?.options?.colors || FEATURE_CARD_DEFAULT_COLORS;
|
|
6419
|
-
const data = config?.children?.map(({ attributeName }, index) => {
|
|
6420
|
-
const attribute = attributes?.find(({ name }) => name === attributeName);
|
|
6421
|
-
return {
|
|
6422
|
-
name: attribute?.name || "",
|
|
6423
|
-
value: attribute ? Number(attribute.value) : 0,
|
|
6424
|
-
color: colors[index] || FEATURE_CARD_OTHER_COLOR
|
|
6425
|
-
};
|
|
6426
|
-
});
|
|
6427
|
-
if (config?.options?.orderByValue) {
|
|
6428
|
-
data.sort((a, b) => b.value - a.value);
|
|
6429
|
-
}
|
|
6430
|
-
const isOtherSliced = config?.options?.otherItems && config.options.otherItems < data.length;
|
|
6431
|
-
if (!isOtherSliced)
|
|
6432
|
-
return data;
|
|
6433
|
-
const otherValue = data
|
|
6434
|
-
.slice(0, config?.options?.otherItems)
|
|
6435
|
-
.reduce((prev, { value }) => prev + value, 0);
|
|
6436
|
-
return [
|
|
6437
|
-
...data?.slice(0, config.options?.otherItems),
|
|
6438
|
-
{
|
|
6439
|
-
name: t("other", { ns: "dashboard" }),
|
|
6440
|
-
color: FEATURE_CARD_OTHER_COLOR,
|
|
6441
|
-
value: Number(otherValue)
|
|
6442
|
-
}
|
|
6443
|
-
];
|
|
6444
|
-
};
|
|
6445
|
-
|
|
6446
|
-
const getDataFromRelatedFeatures = ({ t, config, filters, relatedConfig, dataSource, layerInfo }) => {
|
|
6447
|
-
if (!dataSource || !dataSource?.features?.length) {
|
|
6448
|
-
return [];
|
|
6449
|
-
}
|
|
6450
|
-
const { colors } = config.options;
|
|
6451
|
-
const layerDefinition = getLayerDefinition(layerInfo);
|
|
6452
|
-
let data = JSON.parse(JSON.stringify(dataSource?.features));
|
|
6453
|
-
const sortAttribute = config?.options?.orderByValue
|
|
6454
|
-
? relatedConfig.attributeName
|
|
6455
|
-
: config?.options?.orderByTitle
|
|
6456
|
-
? relatedConfig.attributeTitle
|
|
6457
|
-
: null;
|
|
6458
|
-
if (sortAttribute) {
|
|
6459
|
-
data.sort((a, b) => b.attributes[sortAttribute] - a.attributes[sortAttribute]);
|
|
6460
|
-
}
|
|
6461
|
-
const isOtherSliced = config?.options?.otherItems && config.options.otherItems < data.length;
|
|
6462
|
-
const otherValue = isOtherSliced
|
|
6463
|
-
? data
|
|
6464
|
-
.slice(config.options.otherItems)
|
|
6465
|
-
.reduce((prev, { attributes }) => prev + attributes[relatedConfig.attributeName], 0)
|
|
6466
|
-
: null;
|
|
6467
|
-
if (isOtherSliced) {
|
|
6468
|
-
data = data.slice(0, config?.options?.otherItems);
|
|
6469
|
-
}
|
|
6470
|
-
const gradientArray = relatedConfig.chartAxis && colors?.length < data.length
|
|
6471
|
-
? new Gradient()
|
|
6472
|
-
.setColorGradient(colors[0], colors[colors.length - 1])
|
|
6473
|
-
.setMidpoint(data.length)
|
|
6474
|
-
.getColors()
|
|
6475
|
-
: colors;
|
|
6476
|
-
const filter = getConfigFilter(relatedConfig?.filterName, filters);
|
|
6477
|
-
const result = data.reduce((acc, feature, index) => {
|
|
6478
|
-
if (relatedConfig?.filterName && !filter) {
|
|
6479
|
-
return acc;
|
|
6480
|
-
}
|
|
6481
|
-
const attributeName = feature.attributes[relatedConfig.attributeName];
|
|
6482
|
-
const attributeTitle = feature.attributes[relatedConfig.attributeTitle];
|
|
6483
|
-
const attributeColor = feature.attributes[relatedConfig.attributeColor];
|
|
6484
|
-
return [
|
|
6485
|
-
...acc,
|
|
6486
|
-
{
|
|
6487
|
-
name: formatAttributeValue({
|
|
6488
|
-
t,
|
|
6489
|
-
type: layerDefinition.attributes[relatedConfig.attributeTitle]?.type,
|
|
6490
|
-
value: attributeTitle,
|
|
6491
|
-
stringFormat: layerDefinition.attributes[relatedConfig.attributeTitle]?.stringFormat
|
|
6492
|
-
}),
|
|
6493
|
-
value: attributeName === null ? null : Number(attributeName),
|
|
6494
|
-
color: attributeColor || gradientArray?.[index] || FEATURE_CARD_OTHER_COLOR,
|
|
6495
|
-
min: filter?.attributeMin ? feature.attributes[filter.attributeMin] : null,
|
|
6496
|
-
max: filter?.attributeMin ? feature.attributes[filter.attributeMax] : null
|
|
6497
|
-
}
|
|
6498
|
-
];
|
|
6499
|
-
}, []);
|
|
6500
|
-
if (isOtherSliced) {
|
|
6501
|
-
result.push({
|
|
6502
|
-
name: t("other", { ns: "dashboard" }),
|
|
6503
|
-
color: FEATURE_CARD_OTHER_COLOR,
|
|
6504
|
-
value: Number(otherValue)
|
|
6505
|
-
});
|
|
6506
|
-
}
|
|
6507
|
-
return result;
|
|
6508
|
-
};
|
|
6509
|
-
|
|
6510
|
-
const getDefaultConfig = ({ title, defaultTitle, items, baseMapName, position, resolution, srid, }) => {
|
|
6511
|
-
const dashboardConfiguration = JSON.parse(JSON.stringify(DEFAULT_DASHBOARD_CONFIG));
|
|
6512
|
-
const defaultPages = JSON.parse(JSON.stringify(DEFAULT_PAGES_CONFIG));
|
|
6513
|
-
const defaultPage = createConfigPage({ title, baseMapName, position, resolution, defaultTitle });
|
|
6514
|
-
if (items?.length) {
|
|
6515
|
-
const contentItems = items.map(item => createConfigLayer(item.name));
|
|
6516
|
-
defaultPage.layers.push(...contentItems);
|
|
6517
|
-
}
|
|
6518
|
-
defaultPages.children.push(defaultPage);
|
|
6519
|
-
dashboardConfiguration.children.push(defaultPages);
|
|
6520
|
-
return dashboardConfiguration;
|
|
6521
|
-
};
|
|
6522
|
-
|
|
6523
|
-
const ElementImage = react.memo(({ type, elementConfig }) => {
|
|
6524
|
-
const { attributes } = useWidgetContext(type);
|
|
6525
|
-
const { value, attributeName, options } = elementConfig || {};
|
|
6526
|
-
const { width } = options || {};
|
|
6527
|
-
const firstImage = react.useMemo(() => {
|
|
6528
|
-
if (value) {
|
|
6529
|
-
return value.toString();
|
|
6530
|
-
}
|
|
6531
|
-
if (!attributeName || Array.isArray(attributeName)) {
|
|
6532
|
-
return null;
|
|
6533
|
-
}
|
|
6534
|
-
const attribute = attributes?.find(item => item.name === attributeName);
|
|
6535
|
-
return attribute?.value?.split(";")?.[0];
|
|
6536
|
-
}, [attributeName, attributes, value]);
|
|
6537
|
-
return firstImage ? jsxRuntime.jsx("img", { src: firstImage, alt: firstImage, width: width }) : null;
|
|
6538
|
-
});
|
|
6539
|
-
|
|
6540
|
-
const SmallPreviewContainer$1 = styled.div `
|
|
6541
|
-
width: 100%;
|
|
6542
|
-
height: 100%;
|
|
6543
|
-
`;
|
|
6558
|
+
var img$3 = "data:image/png;base64,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";
|
|
6544
6559
|
|
|
6545
|
-
const
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
|
|
6560
|
+
const getMaskColor = (isDark) => (isDark ? "0, 0, 0" : "255, 255, 255");
|
|
6561
|
+
const DefaultHeaderContainer = styled(uilibGl.Flex) `
|
|
6562
|
+
flex-direction: column;
|
|
6563
|
+
position: relative;
|
|
6564
|
+
flex-shrink: 0;
|
|
6565
|
+
min-height: 8.375rem;
|
|
6566
|
+
margin-bottom: -1.5rem;
|
|
6567
|
+
padding: 1.5rem 1.5rem 0;
|
|
6568
|
+
border-top-left-radius: 0.5rem;
|
|
6569
|
+
border-top-right-radius: 0.5rem;
|
|
6570
|
+
overflow: hidden;
|
|
6549
6571
|
|
|
6550
|
-
|
|
6551
|
-
|
|
6572
|
+
> * {
|
|
6573
|
+
z-index: 1;
|
|
6574
|
+
}
|
|
6552
6575
|
|
|
6553
|
-
|
|
6576
|
+
&::before {
|
|
6577
|
+
content: "";
|
|
6578
|
+
position: absolute;
|
|
6579
|
+
top: 0;
|
|
6580
|
+
left: 0;
|
|
6554
6581
|
width: 100%;
|
|
6582
|
+
height: 100%;
|
|
6583
|
+
|
|
6584
|
+
${({ image, isDark }) => image
|
|
6585
|
+
? styled.css `
|
|
6586
|
+
background: url(${image}) 0 0 no-repeat;
|
|
6587
|
+
background-size: cover;
|
|
6588
|
+
`
|
|
6589
|
+
: styled.css `
|
|
6590
|
+
background: url(${img$3}) 50% 0 no-repeat;
|
|
6591
|
+
opacity: ${isDark ? 1 : 0.5};
|
|
6592
|
+
`}
|
|
6555
6593
|
}
|
|
6556
|
-
`;
|
|
6557
|
-
const LinearProgressContainer = styled(uilibGl.Flex) `
|
|
6558
|
-
align-items: center;
|
|
6559
|
-
justify-content: center;
|
|
6560
|
-
min-height: inherit;
|
|
6561
6594
|
|
|
6595
|
+
${({ image, isDark }) => image &&
|
|
6596
|
+
styled.css `
|
|
6597
|
+
&::before {
|
|
6598
|
+
-webkit-mask-image: linear-gradient(
|
|
6599
|
+
to bottom,
|
|
6600
|
+
rgba(${getMaskColor(isDark)}, 1),
|
|
6601
|
+
rgba(${getMaskColor(isDark)}, 0)
|
|
6602
|
+
);
|
|
6603
|
+
mask-image: linear-gradient(to bottom, rgba(${getMaskColor(isDark)}, 1), rgba(${getMaskColor(isDark)}, 0));
|
|
6604
|
+
}
|
|
6605
|
+
`}
|
|
6562
6606
|
${uilibGl.LinearProgress} {
|
|
6563
|
-
|
|
6607
|
+
position: absolute;
|
|
6608
|
+
top: 0;
|
|
6609
|
+
left: 0;
|
|
6564
6610
|
}
|
|
6565
6611
|
`;
|
|
6566
|
-
const
|
|
6567
|
-
|
|
6612
|
+
const TopContainer = styled(uilibGl.Flex) `
|
|
6613
|
+
z-index: 1;
|
|
6614
|
+
position: relative;
|
|
6615
|
+
justify-content: space-between;
|
|
6616
|
+
flex-wrap: nowrap;
|
|
6617
|
+
width: 100%;
|
|
6618
|
+
align-items: flex-start;
|
|
6619
|
+
`;
|
|
6620
|
+
const TopContainerButtons = styled(uilibGl.Flex) `
|
|
6621
|
+
align-items: center;
|
|
6622
|
+
width: auto;
|
|
6623
|
+
margin-right: -0.5rem;
|
|
6624
|
+
|
|
6625
|
+
button {
|
|
6626
|
+
width: auto;
|
|
6627
|
+
height: 1rem;
|
|
6628
|
+
padding: 0 0.5rem;
|
|
6629
|
+
}
|
|
6630
|
+
`;
|
|
6631
|
+
const LogoContainer = styled(uilibGl.Flex) `
|
|
6632
|
+
max-width: calc(100% - 1.4rem);
|
|
6633
|
+
flex-grow: 1;
|
|
6634
|
+
font-size: 0;
|
|
6635
|
+
|
|
6636
|
+
& > span::after {
|
|
6637
|
+
font-size: 2rem;
|
|
6638
|
+
}
|
|
6639
|
+
|
|
6640
|
+
img {
|
|
6641
|
+
max-height: 1.875rem;
|
|
6642
|
+
}
|
|
6643
|
+
`;
|
|
6644
|
+
const PageTitle = styled(uilibGl.H2) `
|
|
6645
|
+
display: -webkit-box;
|
|
6646
|
+
-webkit-line-clamp: 3;
|
|
6647
|
+
-webkit-box-orient: vertical;
|
|
6648
|
+
overflow: hidden;
|
|
6649
|
+
margin: 0;
|
|
6650
|
+
font-size: 1.25rem;
|
|
6651
|
+
font-weight: 600;
|
|
6652
|
+
pointer-events: initial;
|
|
6653
|
+
font-family: "Nunito Sans", serif;
|
|
6654
|
+
`;
|
|
6655
|
+
|
|
6656
|
+
exports.ThemeName = void 0;
|
|
6657
|
+
(function (ThemeName) {
|
|
6658
|
+
ThemeName["Light"] = "light";
|
|
6659
|
+
ThemeName["Dark"] = "dark";
|
|
6660
|
+
})(exports.ThemeName || (exports.ThemeName = {}));
|
|
6661
|
+
|
|
6662
|
+
exports.TmsType = void 0;
|
|
6663
|
+
(function (TmsType) {
|
|
6664
|
+
TmsType["WMS"] = "WMS";
|
|
6665
|
+
TmsType["TMS"] = "TMS";
|
|
6666
|
+
TmsType["ArcGIS"] = "ArcGIS";
|
|
6667
|
+
})(exports.TmsType || (exports.TmsType = {}));
|
|
6668
|
+
exports.EditGeometryType = void 0;
|
|
6669
|
+
(function (EditGeometryType) {
|
|
6670
|
+
EditGeometryType["Raster"] = "raster";
|
|
6671
|
+
})(exports.EditGeometryType || (exports.EditGeometryType = {}));
|
|
6672
|
+
|
|
6673
|
+
const DashboardDefaultHeader = React.memo(() => {
|
|
6674
|
+
const { components: { ProjectCatalogMenu, ProjectPanelMenu, ProjectPagesMenu }, } = useWidgetContext();
|
|
6675
|
+
const { pageId, image, icon, tooltip, themeName } = useDashboardHeader();
|
|
6676
|
+
return (jsxRuntime.jsxs(DefaultHeaderContainer, { image: image, isDark: themeName === exports.ThemeName.Dark, children: [!pageId && jsxRuntime.jsx(uilibGl.LinearProgress, {}), jsxRuntime.jsxs(uilibGl.Flex, { column: true, gap: "1rem", children: [jsxRuntime.jsx(uilibGl.FlexSpan, { children: jsxRuntime.jsxs(TopContainer, { children: [jsxRuntime.jsx(LogoContainer, { children: icon }), jsxRuntime.jsxs(TopContainerButtons, { children: [jsxRuntime.jsx(ProjectCatalogMenu, {}), jsxRuntime.jsx(ProjectPanelMenu, {})] })] }) }), jsxRuntime.jsx(uilibGl.FlexSpan, { children: jsxRuntime.jsx(uilibGl.Flex, { column: true, gap: "0.25rem", children: jsxRuntime.jsx(uilibGl.FlexSpan, { children: jsxRuntime.jsxs(uilibGl.Flex, { alignItems: "center", children: [jsxRuntime.jsx(uilibGl.FlexSpan, { flexGrow: 1, children: jsxRuntime.jsx(uilibGl.Tooltip, { arrow: true, content: tooltip, children: ref => (jsxRuntime.jsx(PageTitle, { ref: ref, children: jsxRuntime.jsx(ProjectPagesMenu, {}) })) }) }), jsxRuntime.jsx(uilibGl.FlexSpan, { children: jsxRuntime.jsx(Pagination, {}) })] }) }) }) })] })] }));
|
|
6677
|
+
});
|
|
6678
|
+
|
|
6679
|
+
const HeaderFrontView = styled(uilibGl.Flex) `
|
|
6680
|
+
z-index: 10;
|
|
6681
|
+
position: relative;
|
|
6682
|
+
justify-content: space-between;
|
|
6683
|
+
align-items: ${({ isDefault }) => (isDefault ? "center" : "flex-start")};
|
|
6684
|
+
width: 100%;
|
|
6685
|
+
font: ${({ theme: { fonts } }) => fonts.subtitle};
|
|
6686
|
+
`;
|
|
6687
|
+
const HeaderContainer = styled(uilibGl.FlexSpan) `
|
|
6688
|
+
display: flex;
|
|
6689
|
+
flex-grow: 1;
|
|
6690
|
+
flex-wrap: nowrap;
|
|
6691
|
+
width: calc(100% - 48px);
|
|
6692
|
+
`;
|
|
6693
|
+
const FeatureTitleContainer = styled.div `
|
|
6694
|
+
display: -webkit-box;
|
|
6695
|
+
max-width: 100%;
|
|
6696
|
+
width: 100%;
|
|
6697
|
+
margin: 0.5rem 0;
|
|
6698
|
+
-webkit-line-clamp: 2;
|
|
6699
|
+
-webkit-box-orient: vertical;
|
|
6700
|
+
overflow: hidden;
|
|
6701
|
+
text-overflow: ellipsis;
|
|
6702
|
+
color: ${({ theme: { palette } }) => palette.textPrimary};
|
|
6703
|
+
|
|
6704
|
+
& > ${uilibGl.FlexSpan} {
|
|
6705
|
+
cursor: ${({ clickable }) => clickable && "pointer"};
|
|
6706
|
+
|
|
6707
|
+
&:hover {
|
|
6708
|
+
color: ${({ clickable, theme: { palette } }) => clickable && palette.primary};
|
|
6709
|
+
}
|
|
6710
|
+
}
|
|
6711
|
+
`;
|
|
6712
|
+
const LayerDescription = styled(uilibGl.Description) `
|
|
6713
|
+
width: calc(100% - 4rem);
|
|
6714
|
+
display: -webkit-box;
|
|
6715
|
+
-webkit-line-clamp: 2;
|
|
6716
|
+
-webkit-box-orient: vertical;
|
|
6717
|
+
overflow: hidden;
|
|
6718
|
+
text-overflow: ellipsis;
|
|
6719
|
+
`;
|
|
6720
|
+
const HeaderTitleContainer = styled(uilibGl.Flex) `
|
|
6721
|
+
flex-direction: column;
|
|
6722
|
+
width: 100%;
|
|
6723
|
+
`;
|
|
6724
|
+
const RowHeaderMixin = styled.css `
|
|
6725
|
+
&&& {
|
|
6726
|
+
min-height: auto;
|
|
6727
|
+
|
|
6728
|
+
${FeatureTitleContainer}, ${LayerDescription} {
|
|
6729
|
+
text-align: left;
|
|
6730
|
+
}
|
|
6731
|
+
}
|
|
6732
|
+
|
|
6733
|
+
${HeaderContainer} {
|
|
6734
|
+
flex-direction: row;
|
|
6735
|
+
}
|
|
6736
|
+
|
|
6737
|
+
${FeatureTitleContainer} {
|
|
6738
|
+
max-width: calc(100% - 3.8rem);
|
|
6739
|
+
}
|
|
6740
|
+
`;
|
|
6741
|
+
const Header = styled(uilibGl.Flex) `
|
|
6742
|
+
z-index: 1;
|
|
6743
|
+
position: relative;
|
|
6744
|
+
top: 0;
|
|
6745
|
+
flex-shrink: 0;
|
|
6746
|
+
overflow: hidden;
|
|
6747
|
+
padding: 0.5rem;
|
|
6748
|
+
|
|
6749
|
+
${HeaderContainer} {
|
|
6750
|
+
flex-direction: column;
|
|
6751
|
+
}
|
|
6752
|
+
|
|
6753
|
+
${({ $isRow }) => $isRow && RowHeaderMixin};
|
|
6754
|
+
`;
|
|
6755
|
+
|
|
6756
|
+
const HeaderTitle = ({ noFeature }) => {
|
|
6757
|
+
const { t } = useGlobalContext();
|
|
6758
|
+
const { attributes, layerInfo, feature } = useWidgetContext(exports.WidgetType.FeatureCard);
|
|
6759
|
+
const zoomToFeatures = useZoomToFeatures();
|
|
6760
|
+
const { alias, name, layerDefinition } = layerInfo || {};
|
|
6761
|
+
const resultDescription = alias || name || "";
|
|
6762
|
+
const resultTitle = React.useMemo(() => {
|
|
6763
|
+
const layerDefinitionAttribute = layerDefinition && attributes?.length
|
|
6764
|
+
? attributes.find(item => item.name === layerDefinition.titleAttribute)
|
|
6765
|
+
: null;
|
|
6766
|
+
const layerDefinitionTitle = layerDefinition?.titleAttribute && layerDefinitionAttribute?.value
|
|
6767
|
+
? layerDefinitionAttribute.value
|
|
6768
|
+
: null;
|
|
6769
|
+
return ((!!layerDefinitionTitle &&
|
|
6770
|
+
formatAttributeValue({
|
|
6771
|
+
t,
|
|
6772
|
+
type: layerDefinitionAttribute.type,
|
|
6773
|
+
value: layerDefinitionTitle,
|
|
6774
|
+
stringFormat: layerDefinitionAttribute.stringFormat,
|
|
6775
|
+
})) ||
|
|
6776
|
+
feature?.id);
|
|
6777
|
+
}, [attributes, feature, layerDefinition]);
|
|
6778
|
+
return (jsxRuntime.jsxs(HeaderTitleContainer, { children: [noFeature ? (jsxRuntime.jsx(FeatureTitleContainer, { children: t("noObjectFound", { ns: "dashboard" }) })) : (jsxRuntime.jsx(FeatureTitleContainer, { clickable: true, children: jsxRuntime.jsx(uilibGl.Tooltip, { arrow: true, placement: "top", content: t("zoomToFeature", { ns: "dashboard" }), delay: [600, 0], children: ref => (jsxRuntime.jsx(uilibGl.FlexSpan, { ref: ref, onClick: () => zoomToFeatures([feature]), children: resultTitle })) }) })), jsxRuntime.jsx(LayerDescription, { title: resultDescription, children: resultDescription })] }));
|
|
6779
|
+
};
|
|
6780
|
+
|
|
6781
|
+
const LayerIconContainer = styled.div `
|
|
6782
|
+
display: flex;
|
|
6783
|
+
align-items: center;
|
|
6784
|
+
margin-right: 0.75rem;
|
|
6785
|
+
`;
|
|
6786
|
+
const AlertIconContainer = styled(uilibGl.Flex) `
|
|
6787
|
+
align-items: center;
|
|
6788
|
+
justify-content: center;
|
|
6789
|
+
width: 2rem;
|
|
6790
|
+
height: 2rem;
|
|
6791
|
+
|
|
6792
|
+
${uilibGl.Icon} {
|
|
6793
|
+
:after {
|
|
6794
|
+
color: ${({ theme: { palette } }) => palette.error};
|
|
6795
|
+
}
|
|
6796
|
+
}
|
|
6797
|
+
`;
|
|
6798
|
+
|
|
6799
|
+
var img$2 = "data:image/svg+xml,%3csvg width='32' height='32' viewBox='0 0 32 32' fill='none' xmlns='http://www.w3.org/2000/svg'%3e %3crect width='32' height='32' fill='transparent'/%3e %3cpath d='M20.248 9.67787C18.5318 8.04035 15.9473 7.54977 13.7024 8.43543C11.4576 9.32109 9.99566 11.4081 10 13.721C10 18.2894 16 24 16 24C16 24 22 18.2894 22 13.721C22.0028 12.2054 21.3726 10.7509 20.248 9.67787Z' fill='url(%23paint0_linear_6459_10338)'/%3e %3ccircle cx='16' cy='14' r='2' fill='white'/%3e %3cdefs%3e %3clinearGradient id='paint0_linear_6459_10338' x1='10' y1='8' x2='25.36' y2='19.52' gradientUnits='userSpaceOnUse'%3e %3cstop stop-color='%230084D6'/%3e %3cstop offset='0.489583' stop-color='%230084D6'/%3e %3cstop offset='0.489683' stop-color='%2305A9FF'/%3e %3cstop offset='0.921875' stop-color='%2305A9FF'/%3e %3c/linearGradient%3e %3c/defs%3e%3c/svg%3e";
|
|
6800
|
+
|
|
6801
|
+
var img$1 = "data:image/svg+xml,%3csvg width='32' height='32' viewBox='0 0 32 32' fill='none' xmlns='http://www.w3.org/2000/svg'%3e %3crect width='32' height='32' fill='transparent'/%3e %3cpath d='M4 17.9574H10.1538L13.5385 12L18.4615 20L22 13.8723H28' stroke='url(%23paint0_linear_6459_10369)' stroke-width='2' stroke-linejoin='round'/%3e %3cdefs%3e %3clinearGradient id='paint0_linear_6459_10369' x1='4' y1='9.54167' x2='28.7229' y2='20.1484' gradientUnits='userSpaceOnUse'%3e %3cstop offset='0.525942' stop-color='%2306AAFF'/%3e %3cstop offset='0.526042' stop-color='%230184D7'/%3e %3c/linearGradient%3e %3c/defs%3e%3c/svg%3e";
|
|
6802
|
+
|
|
6803
|
+
var img = "data:image/svg+xml,%3csvg width='32' height='32' viewBox='0 0 32 32' fill='none' xmlns='http://www.w3.org/2000/svg'%3e %3crect width='32' height='32' fill='transparent'/%3e %3crect x='8' y='8' width='16' height='16' rx='2' fill='url(%23paint0_linear_6459_10399)'/%3e %3cdefs%3e %3clinearGradient id='paint0_linear_6459_10399' x1='8' y1='8' x2='24' y2='24' gradientUnits='userSpaceOnUse'%3e %3cstop stop-color='%230084D6'/%3e %3cstop offset='0.489583' stop-color='%230084D6'/%3e %3cstop offset='0.489683' stop-color='%2305A9FF'/%3e %3cstop offset='0.921875' stop-color='%2305A9FF'/%3e %3c/linearGradient%3e %3c/defs%3e%3c/svg%3e";
|
|
6804
|
+
|
|
6805
|
+
const LayerIcon = ({ layerInfo }) => {
|
|
6806
|
+
const renderSymbol = React.useMemo(() => {
|
|
6807
|
+
if (!layerInfo.geometryType) {
|
|
6808
|
+
return (jsxRuntime.jsx(AlertIconContainer, { children: jsxRuntime.jsx(uilibGl.Icon, { kind: "warning" }) }));
|
|
6809
|
+
}
|
|
6810
|
+
switch (layerInfo.geometryType) {
|
|
6811
|
+
case api.GeometryType.Polyline:
|
|
6812
|
+
return jsxRuntime.jsx("img", { src: img$1, alt: "" });
|
|
6813
|
+
case api.GeometryType.Polygon:
|
|
6814
|
+
return jsxRuntime.jsx("img", { src: img, alt: "" });
|
|
6815
|
+
case api.GeometryType.Point:
|
|
6816
|
+
default:
|
|
6817
|
+
return jsxRuntime.jsx("img", { src: img$2, alt: "" });
|
|
6818
|
+
}
|
|
6819
|
+
}, [layerInfo.geometryType]);
|
|
6820
|
+
return jsxRuntime.jsx(LayerIconContainer, { children: renderSymbol });
|
|
6821
|
+
};
|
|
6822
|
+
|
|
6823
|
+
const FeatureCardDefaultHeader = ({ noFeature }) => {
|
|
6824
|
+
const { layerInfo } = useWidgetContext(exports.WidgetType.FeatureCard);
|
|
6825
|
+
return (jsxRuntime.jsx(Header, { "$isRow": true, children: jsxRuntime.jsxs(HeaderFrontView, { isDefault: true, children: [jsxRuntime.jsxs(HeaderContainer, { children: [!!layerInfo?.name && jsxRuntime.jsx(LayerIcon, { layerInfo: layerInfo }), jsxRuntime.jsx(HeaderTitle, { noFeature: noFeature })] }), jsxRuntime.jsx(FeatureCardButtons, {})] }) }));
|
|
6826
|
+
};
|
|
6827
|
+
|
|
6828
|
+
const HeaderFontColorMixin$1 = styled.css `
|
|
6829
|
+
${HeaderTitleContainer}, ${LayerDescription} {
|
|
6830
|
+
color: ${({ $fontColor }) => $fontColor};
|
|
6831
|
+
}
|
|
6832
|
+
`;
|
|
6833
|
+
const HeaderWrapperMixin$1 = styled.css `
|
|
6834
|
+
padding: 0.5rem 0.5rem 0;
|
|
6835
|
+
|
|
6836
|
+
${Header} {
|
|
6837
|
+
min-height: 5.25rem;
|
|
6838
|
+
}
|
|
6839
|
+
|
|
6840
|
+
${HeaderContainer} {
|
|
6841
|
+
max-width: 100%;
|
|
6842
|
+
width: 100%;
|
|
6843
|
+
}
|
|
6844
|
+
|
|
6845
|
+
${FeatureControls} {
|
|
6846
|
+
max-width: calc(100% - 2rem);
|
|
6847
|
+
width: calc(100% - 2rem);
|
|
6848
|
+
margin-top: -0.5rem;
|
|
6849
|
+
padding-top: 1rem;
|
|
6850
|
+
border-radius: ${({ theme: { borderRadius } }) => borderRadius.medium};
|
|
6851
|
+
}
|
|
6852
|
+
|
|
6853
|
+
${({ $fontColor }) => !!$fontColor && HeaderFontColorMixin$1};
|
|
6854
|
+
`;
|
|
6855
|
+
const GradientHeaderWrapper = styled.div `
|
|
6856
|
+
${Header} {
|
|
6857
|
+
background: ${({ $bgColor }) => $bgColor || "radial-gradient(129.21% 133.22% at 51.94% 0%, #e8fffe 9.48%, #5fcaff 100%)"};
|
|
6858
|
+
}
|
|
6859
|
+
|
|
6860
|
+
${HeaderContainer} {
|
|
6861
|
+
align-items: center;
|
|
6862
|
+
}
|
|
6863
|
+
|
|
6864
|
+
${HeaderTitleContainer} {
|
|
6865
|
+
margin-left: 0;
|
|
6866
|
+
text-align: center;
|
|
6867
|
+
}
|
|
6868
|
+
|
|
6869
|
+
${FeatureTitleContainer} {
|
|
6870
|
+
text-align: center;
|
|
6871
|
+
}
|
|
6872
|
+
|
|
6873
|
+
${LayerDescription} {
|
|
6874
|
+
text-align: center;
|
|
6875
|
+
}
|
|
6876
|
+
|
|
6877
|
+
${HeaderWrapperMixin$1};
|
|
6878
|
+
`;
|
|
6879
|
+
|
|
6880
|
+
const FeatureCardGradientHeader = ({ isRow }) => {
|
|
6881
|
+
const { layerInfo } = useWidgetContext(exports.WidgetType.FeatureCard);
|
|
6882
|
+
const { config } = useWidgetConfig(exports.WidgetType.FeatureCard);
|
|
6883
|
+
const { header, options } = config || {};
|
|
6884
|
+
const renderElement = useHeaderRender(header);
|
|
6885
|
+
return (jsxRuntime.jsx(GradientHeaderWrapper, { "$fontColor": options?.fontColor, "$bgColor": options?.bgColor, children: jsxRuntime.jsx(uilibGl.ThemeProvider, { theme: uilibGl.defaultTheme, children: jsxRuntime.jsx(Header, { "$isRow": isRow, children: jsxRuntime.jsxs(HeaderFrontView, { children: [jsxRuntime.jsxs(HeaderContainer, { children: [jsxRuntime.jsx(LayerIcon, { layerInfo: layerInfo }), jsxRuntime.jsx(FeatureCardTitle, { title: renderElement({
|
|
6886
|
+
id: "title",
|
|
6887
|
+
wrap: false,
|
|
6888
|
+
}), description: renderElement({
|
|
6889
|
+
id: "description",
|
|
6890
|
+
wrap: false,
|
|
6891
|
+
}) })] }), jsxRuntime.jsx(FeatureCardButtons, {})] }) }) }) }));
|
|
6892
|
+
};
|
|
6893
|
+
|
|
6894
|
+
const HeaderFontColorMixin = styled.css `
|
|
6895
|
+
${HeaderTitleContainer}, ${LayerDescription} {
|
|
6896
|
+
color: ${({ $fontColor }) => $fontColor};
|
|
6897
|
+
}
|
|
6898
|
+
`;
|
|
6899
|
+
const HeaderWrapperMixin = styled.css `
|
|
6900
|
+
padding: 0.5rem 0.5rem 0;
|
|
6901
|
+
|
|
6902
|
+
${Header} {
|
|
6903
|
+
min-height: 5.25rem;
|
|
6904
|
+
}
|
|
6905
|
+
|
|
6906
|
+
${HeaderContainer} {
|
|
6907
|
+
max-width: 100%;
|
|
6908
|
+
width: 100%;
|
|
6909
|
+
}
|
|
6910
|
+
|
|
6911
|
+
${FeatureControls} {
|
|
6912
|
+
max-width: calc(100% - 2rem);
|
|
6913
|
+
width: calc(100% - 2rem);
|
|
6914
|
+
margin-top: -0.5rem;
|
|
6915
|
+
padding-top: 1rem;
|
|
6916
|
+
border-radius: ${({ theme: { borderRadius } }) => borderRadius.medium};
|
|
6917
|
+
}
|
|
6918
|
+
|
|
6919
|
+
${({ $fontColor }) => !!$fontColor && HeaderFontColorMixin};
|
|
6920
|
+
`;
|
|
6921
|
+
const HeaderIcon = styled(uilibGl.Flex) `
|
|
6922
|
+
position: absolute;
|
|
6923
|
+
top: 0;
|
|
6924
|
+
right: 0;
|
|
6925
|
+
justify-content: flex-end;
|
|
6926
|
+
align-items: center;
|
|
6927
|
+
min-width: 7.5rem;
|
|
6928
|
+
height: 100%;
|
|
6929
|
+
|
|
6930
|
+
span[kind]:after {
|
|
6931
|
+
font-size: 7.5rem;
|
|
6932
|
+
}
|
|
6933
|
+
|
|
6934
|
+
span[kind]:after,
|
|
6935
|
+
path,
|
|
6936
|
+
line,
|
|
6937
|
+
circle {
|
|
6938
|
+
fill: rgba(255, 255, 255, 0.36);
|
|
6939
|
+
}
|
|
6940
|
+
|
|
6941
|
+
&& > * {
|
|
6942
|
+
display: flex;
|
|
6943
|
+
align-items: center;
|
|
6944
|
+
height: 100%;
|
|
6945
|
+
}
|
|
6946
|
+
`;
|
|
6947
|
+
const BigIconHeaderMixin = styled.css `
|
|
6948
|
+
${HeaderIcon} {
|
|
6949
|
+
min-width: 14rem;
|
|
6950
|
+
right: -3rem;
|
|
6951
|
+
|
|
6952
|
+
span[kind]:after {
|
|
6953
|
+
font-size: 14rem;
|
|
6954
|
+
}
|
|
6955
|
+
}
|
|
6956
|
+
`;
|
|
6957
|
+
const IconHeaderWrapper = styled.div `
|
|
6958
|
+
${Header} {
|
|
6959
|
+
width: calc(100% + 3rem);
|
|
6960
|
+
margin: -1.5rem -1.5rem 0 -1.5rem;
|
|
6961
|
+
padding: 1.5rem;
|
|
6962
|
+
border-top-left-radius: 0.5rem;
|
|
6963
|
+
border-top-right-radius: 0.5rem;
|
|
6964
|
+
background: ${({ $bgColor }) => $bgColor || "linear-gradient(96.55deg, #FFFCD3 0%, #B4DC47 100%)"};
|
|
6965
|
+
}
|
|
6966
|
+
|
|
6967
|
+
${HeaderWrapperMixin};
|
|
6968
|
+
|
|
6969
|
+
${({ $bigIcon }) => $bigIcon && BigIconHeaderMixin};
|
|
6970
|
+
`;
|
|
6971
|
+
|
|
6972
|
+
const FeatureCardIconHeader = ({ isRow }) => {
|
|
6973
|
+
const { layerInfo } = useWidgetContext(exports.WidgetType.FeatureCard);
|
|
6974
|
+
const { config } = useWidgetConfig(exports.WidgetType.FeatureCard);
|
|
6975
|
+
const { header, options } = config || {};
|
|
6976
|
+
const renderElement = useHeaderRender(header);
|
|
6977
|
+
return (jsxRuntime.jsx(IconHeaderWrapper, { "$fontColor": options?.fontColor, "$bgColor": options?.bgColor, "$bigIcon": options?.bigIcon, children: jsxRuntime.jsx(uilibGl.ThemeProvider, { theme: uilibGl.defaultTheme, children: jsxRuntime.jsxs(Header, { "$isRow": isRow, children: [jsxRuntime.jsxs(HeaderFrontView, { children: [jsxRuntime.jsxs(HeaderContainer, { children: [jsxRuntime.jsx(LayerIcon, { layerInfo: layerInfo }), jsxRuntime.jsx(FeatureCardTitle, { title: renderElement({
|
|
6978
|
+
id: "title",
|
|
6979
|
+
wrap: false,
|
|
6980
|
+
}), description: renderElement({
|
|
6981
|
+
id: "description",
|
|
6982
|
+
wrap: false,
|
|
6983
|
+
}) })] }), jsxRuntime.jsx(FeatureCardButtons, {})] }), jsxRuntime.jsx(HeaderIcon, { children: renderElement({
|
|
6984
|
+
id: "icon",
|
|
6985
|
+
wrap: false,
|
|
6986
|
+
}) })] }) }) }));
|
|
6987
|
+
};
|
|
6988
|
+
|
|
6989
|
+
const ImageContainerButton = styled(uilibGl.FlatButton) `
|
|
6990
|
+
min-height: 1.5rem;
|
|
6991
|
+
border-radius: ${({ theme: { borderRadius } }) => borderRadius.large};
|
|
6992
|
+
background-color: ${({ theme: { palette } }) => palette.primary};
|
|
6993
|
+
text-transform: none;
|
|
6994
|
+
|
|
6995
|
+
:hover {
|
|
6996
|
+
background-color: ${({ theme: { palette } }) => palette.primaryDeep};
|
|
6997
|
+
}
|
|
6998
|
+
`;
|
|
6999
|
+
|
|
7000
|
+
const ElementButton = React.memo(({ type, elementConfig }) => {
|
|
7001
|
+
const { attributes } = useWidgetContext(type);
|
|
7002
|
+
const attribute = getAttributeByName(elementConfig?.attributeName, attributes);
|
|
7003
|
+
const link = attribute?.value;
|
|
7004
|
+
if (!link || typeof link !== "string")
|
|
7005
|
+
return null;
|
|
7006
|
+
return (jsxRuntime.jsx(ImageContainerButton, { onClick: () => window.open(attribute?.value), children: elementConfig.value || "" }));
|
|
7007
|
+
});
|
|
7008
|
+
|
|
7009
|
+
const AttributeGalleryContainer = styled.div `
|
|
7010
|
+
&& {
|
|
7011
|
+
width: calc(100% + 3rem);
|
|
7012
|
+
}
|
|
7013
|
+
|
|
7014
|
+
min-height: 12.625rem;
|
|
7015
|
+
background-color: ${({ theme: { palette } }) => palette.element};
|
|
7016
|
+
|
|
7017
|
+
img {
|
|
7018
|
+
width: 100%;
|
|
7019
|
+
}
|
|
7020
|
+
`;
|
|
7021
|
+
const LinearProgressContainer = styled(uilibGl.Flex) `
|
|
7022
|
+
align-items: center;
|
|
7023
|
+
justify-content: center;
|
|
7024
|
+
min-height: inherit;
|
|
7025
|
+
|
|
7026
|
+
${uilibGl.LinearProgress} {
|
|
7027
|
+
max-width: 4rem;
|
|
7028
|
+
}
|
|
7029
|
+
`;
|
|
7030
|
+
const NoLiveSnapshotContainer = styled(uilibGl.Flex) `
|
|
7031
|
+
flex-direction: column;
|
|
6568
7032
|
align-items: center;
|
|
6569
7033
|
|
|
6570
7034
|
span[kind="alert"] {
|
|
@@ -6651,7 +7115,7 @@ const imgSlideShowMixin = styled.css `
|
|
|
6651
7115
|
}
|
|
6652
7116
|
}
|
|
6653
7117
|
`;
|
|
6654
|
-
const SmallPreviewContainer = styled.div `
|
|
7118
|
+
const SmallPreviewContainer$1 = styled.div `
|
|
6655
7119
|
cursor: ${({ onClick }) => (onClick ? "pointer" : "default")};
|
|
6656
7120
|
position: relative;
|
|
6657
7121
|
width: 100%;
|
|
@@ -6696,19 +7160,23 @@ const SmallPreviewContainer = styled.div `
|
|
|
6696
7160
|
`;
|
|
6697
7161
|
const SmallPreviewImages = styled.div ``;
|
|
6698
7162
|
|
|
7163
|
+
const NoLiveSnapshot = () => {
|
|
7164
|
+
return (jsxRuntime.jsxs(NoLiveSnapshotContainer, { children: [jsxRuntime.jsx(uilibGl.Icon, { kind: "alert" }), jsxRuntime.jsx(uilibGl.Description, { children: "\u0421\u043D\u0438\u043C\u043E\u043A \u043D\u0435 \u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D" })] }));
|
|
7165
|
+
};
|
|
7166
|
+
|
|
6699
7167
|
const SmallPreview = ({ images, totalCount, currentIndex, isLoading, setCurrentIndex, onClick, onNextPage }) => {
|
|
6700
7168
|
const { t } = useGlobalContext();
|
|
6701
|
-
const [prevIndex, setPrevIndex] =
|
|
7169
|
+
const [prevIndex, setPrevIndex] = React.useState(currentIndex + 1);
|
|
6702
7170
|
const isPrevDisabled = currentIndex === 0;
|
|
6703
7171
|
const total = totalCount || images?.length || 0;
|
|
6704
7172
|
const isNextDisabled = currentIndex === total - 1;
|
|
6705
|
-
const prev =
|
|
7173
|
+
const prev = React.useCallback(() => {
|
|
6706
7174
|
if (isPrevDisabled)
|
|
6707
7175
|
return;
|
|
6708
7176
|
setPrevIndex(currentIndex);
|
|
6709
7177
|
setCurrentIndex(currentIndex - 1);
|
|
6710
7178
|
}, [currentIndex, isPrevDisabled, setCurrentIndex]);
|
|
6711
|
-
const next =
|
|
7179
|
+
const next = React.useCallback(() => {
|
|
6712
7180
|
if (isNextDisabled)
|
|
6713
7181
|
return;
|
|
6714
7182
|
setPrevIndex(currentIndex);
|
|
@@ -6717,40 +7185,151 @@ const SmallPreview = ({ images, totalCount, currentIndex, isLoading, setCurrentI
|
|
|
6717
7185
|
onNextPage();
|
|
6718
7186
|
}
|
|
6719
7187
|
}, [currentIndex, images, isNextDisabled, onNextPage, setCurrentIndex]);
|
|
6720
|
-
return (jsxRuntime.jsxs(SmallPreviewContainer, { currentIndex: currentIndex + 1, prevIndex: prevIndex + 1, children: [isLoading && jsxRuntime.jsx(uilibGl.LinearProgress, {}), images.length > 1 && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(SmallPreviewLeft, { "$isDisabled": isPrevDisabled, onClick: prev }), jsxRuntime.jsx(SmallPreviewRight, { "$isDisabled": isNextDisabled, onClick: next }), jsxRuntime.jsx(SmallPreviewCounter, { children: jsxRuntime.jsxs("div", { children: [currentIndex + 1, " ", t("of", { ns: "dashboard" }), " ", total] }) })] })), jsxRuntime.jsx(SmallPreviewImages, { onClick: onClick, children: images.map(image => (jsxRuntime.jsx("img", { src: image.src, alt: "" }, image.src))) })] }));
|
|
7188
|
+
return (jsxRuntime.jsxs(SmallPreviewContainer$1, { currentIndex: currentIndex + 1, prevIndex: prevIndex + 1, children: [isLoading && jsxRuntime.jsx(uilibGl.LinearProgress, {}), images.length > 1 && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(SmallPreviewLeft, { "$isDisabled": isPrevDisabled, onClick: prev }), jsxRuntime.jsx(SmallPreviewRight, { "$isDisabled": isNextDisabled, onClick: next }), jsxRuntime.jsx(SmallPreviewCounter, { children: jsxRuntime.jsxs("div", { children: [currentIndex + 1, " ", t("of", { ns: "dashboard" }), " ", total] }) })] })), jsxRuntime.jsx(SmallPreviewImages, { onClick: onClick, children: images.map(image => (jsxRuntime.jsx("img", { src: image.src, alt: "" }, image.src))) })] }));
|
|
6721
7189
|
};
|
|
6722
7190
|
|
|
6723
|
-
const
|
|
6724
|
-
|
|
6725
|
-
|
|
7191
|
+
const DEFAULT_ARCHIVED_PERIOD = "#24h";
|
|
7192
|
+
const SNAPSHOTS_PER_PAGE = 10;
|
|
7193
|
+
const getDuration = (archivePeriod) => {
|
|
7194
|
+
const lastLetter = archivePeriod[archivePeriod.length - 1];
|
|
7195
|
+
const value = archivePeriod.slice(1, -1);
|
|
7196
|
+
const prop = lastLetter === "d"
|
|
7197
|
+
? "days"
|
|
7198
|
+
: lastLetter === "h"
|
|
7199
|
+
? "hours"
|
|
7200
|
+
: lastLetter === "m"
|
|
7201
|
+
? "minutes"
|
|
7202
|
+
: lastLetter === "s"
|
|
7203
|
+
? "seconds"
|
|
7204
|
+
: null;
|
|
7205
|
+
if (!lastLetter || !value || !prop)
|
|
7206
|
+
return {};
|
|
7207
|
+
return { [prop]: Number(value) };
|
|
7208
|
+
};
|
|
7209
|
+
const useCameraAttribute = (cameraId) => {
|
|
7210
|
+
const { api } = useGlobalContext();
|
|
7211
|
+
const [currentIndex, setCurrentIndex] = React.useState(0);
|
|
7212
|
+
const [currentPage, setCurrentPage] = React.useState(0);
|
|
7213
|
+
const [timeline, setTimeline] = React.useState([]);
|
|
7214
|
+
const [isLoadingSnapshot, setLoadingSnapshot] = React.useState(false);
|
|
7215
|
+
const [isLoadingTimeline, setLoadingTimeline] = React.useState(false);
|
|
6726
7216
|
const [isOpenGallery, toggleGallery] = useToggle();
|
|
6727
|
-
const
|
|
6728
|
-
const
|
|
6729
|
-
|
|
6730
|
-
const
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
7217
|
+
const [galleryImages, setGalleryImages] = React.useState([]);
|
|
7218
|
+
const imagesRef = React.useRef([]);
|
|
7219
|
+
// Todo get archivePeriod from project configuration
|
|
7220
|
+
const archivePeriod = /* appConfig?.settings?.cameraAttribute?.archivePeriod ||*/ DEFAULT_ARCHIVED_PERIOD;
|
|
7221
|
+
const onNextPage = React.useCallback(() => {
|
|
7222
|
+
setCurrentPage(currentPage + 1);
|
|
7223
|
+
}, [currentPage]);
|
|
7224
|
+
React.useEffect(() => {
|
|
7225
|
+
(async () => {
|
|
7226
|
+
if (!cameraId)
|
|
7227
|
+
return;
|
|
7228
|
+
setLoadingSnapshot(true);
|
|
7229
|
+
const snapshot = null; // await api.cameras.getLiveSnapshot(cameraId);
|
|
7230
|
+
const url = URL.createObjectURL(snapshot);
|
|
7231
|
+
setLoadingSnapshot(false);
|
|
7232
|
+
setLoadingTimeline(true);
|
|
7233
|
+
imagesRef.current = [
|
|
7234
|
+
{
|
|
7235
|
+
src: url,
|
|
7236
|
+
startTime: new Date(),
|
|
7237
|
+
},
|
|
7238
|
+
];
|
|
7239
|
+
setGalleryImages([
|
|
7240
|
+
{
|
|
7241
|
+
src: url,
|
|
7242
|
+
fileName: formatDate$1(new Date()),
|
|
7243
|
+
},
|
|
7244
|
+
]);
|
|
7245
|
+
const formatDateOptions = { dateFormat: exports.DateFormat.UTC };
|
|
7246
|
+
const startTime = formatDate$1(dateFns.sub(new Date(), getDuration(archivePeriod)), formatDateOptions);
|
|
7247
|
+
const endTime = formatDate$1(new Date(), formatDateOptions);
|
|
7248
|
+
const timelineResponse = await api.cameras.getArchiveTimeline({ cameraId, startTime, endTime });
|
|
7249
|
+
if (!timelineResponse.success || !timelineResponse.timeline.length)
|
|
7250
|
+
return;
|
|
7251
|
+
timelineResponse.timeline.reverse();
|
|
7252
|
+
setTimeline(timelineResponse.timeline);
|
|
7253
|
+
})();
|
|
7254
|
+
}, [cameraId]);
|
|
7255
|
+
React.useEffect(() => {
|
|
7256
|
+
if (!timeline.length)
|
|
7257
|
+
return;
|
|
7258
|
+
const timelinePage = timeline.slice(currentPage * SNAPSHOTS_PER_PAGE, (currentPage + 1) * SNAPSHOTS_PER_PAGE);
|
|
7259
|
+
for (const item of timelinePage) {
|
|
7260
|
+
if (!item)
|
|
7261
|
+
continue;
|
|
7262
|
+
api.cameras
|
|
7263
|
+
.getArchiveSnapshot({
|
|
7264
|
+
cameraId,
|
|
7265
|
+
time: item.startTime,
|
|
7266
|
+
})
|
|
7267
|
+
.then(response => {
|
|
7268
|
+
const newImages = [
|
|
7269
|
+
...imagesRef.current,
|
|
7270
|
+
{ src: URL.createObjectURL(response), startTime: new Date(item.startTime) },
|
|
7271
|
+
];
|
|
7272
|
+
newImages.sort((a, b) => (a.startTime < b.startTime ? 1 : a.startTime > b.startTime ? -1 : 0));
|
|
7273
|
+
imagesRef.current = newImages;
|
|
7274
|
+
setGalleryImages(newImages.map(newImage => ({
|
|
7275
|
+
src: newImage.src,
|
|
7276
|
+
fileName: formatDate$1(newImage.startTime, { dateFormat: exports.DateFormat.DateTime }),
|
|
7277
|
+
})));
|
|
7278
|
+
if (newImages.length === timelinePage.length) {
|
|
7279
|
+
setLoadingTimeline(false);
|
|
7280
|
+
}
|
|
6737
7281
|
});
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
7282
|
+
}
|
|
7283
|
+
}, [timeline, currentPage]);
|
|
7284
|
+
return [
|
|
7285
|
+
{
|
|
7286
|
+
currentIndex,
|
|
7287
|
+
currentPage,
|
|
7288
|
+
totalCount: timeline.length,
|
|
7289
|
+
galleryImages,
|
|
7290
|
+
isLoadingSnapshot,
|
|
7291
|
+
isLoadingTimeline,
|
|
7292
|
+
isOpenGallery,
|
|
7293
|
+
},
|
|
7294
|
+
{
|
|
7295
|
+
toggleGallery,
|
|
7296
|
+
setGalleryImages,
|
|
7297
|
+
setCurrentIndex,
|
|
7298
|
+
onNextPage,
|
|
7299
|
+
},
|
|
7300
|
+
];
|
|
7301
|
+
};
|
|
7302
|
+
|
|
7303
|
+
const ElementCamera = ({ type, renderElement, elementConfig, field }) => {
|
|
7304
|
+
const { expandedContainers, attributes } = useWidgetContext(type);
|
|
7305
|
+
const attribute = getAttributeByName(elementConfig?.attributeName, attributes);
|
|
7306
|
+
const value = attribute?.value;
|
|
7307
|
+
const { id, options } = elementConfig || {};
|
|
7308
|
+
const { expandable, expanded } = options || {};
|
|
7309
|
+
const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
|
|
7310
|
+
const [{ currentIndex /* , currentPage*/, totalCount, galleryImages, isLoadingSnapshot, isLoadingTimeline, isOpenGallery }, { setCurrentIndex, toggleGallery, onNextPage },] = useCameraAttribute(value);
|
|
7311
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [!!field && jsxRuntime.jsx(AttributeLabel, { children: field }), jsxRuntime.jsx(AttributeGalleryContainer, { children: isLoadingSnapshot ? (jsxRuntime.jsx(LinearProgressContainer, { children: jsxRuntime.jsx(uilibGl.LinearProgress, {}) })) : !galleryImages?.length && !isLoadingTimeline ? (jsxRuntime.jsx(NoLiveSnapshot, {})) : (jsxRuntime.jsx(SmallPreview, { images: galleryImages, totalCount: totalCount, currentIndex: currentIndex, isLoading: isLoadingTimeline, setCurrentIndex: setCurrentIndex, onClick: toggleGallery, onNextPage: onNextPage })) }), isOpenGallery && (jsxRuntime.jsx(uilibGl.Preview, { images: galleryImages,
|
|
6744
7312
|
// currentIndex={currentIndex}
|
|
6745
|
-
//
|
|
6746
|
-
|
|
7313
|
+
// currentPage={currentPage}
|
|
7314
|
+
// totalCount={totalCount}
|
|
7315
|
+
isOpen: isOpenGallery,
|
|
7316
|
+
// isLoading={isLoadingTimeline}
|
|
7317
|
+
// hasSidebar
|
|
7318
|
+
onClose: toggleGallery }))] }))] }));
|
|
6747
7319
|
};
|
|
6748
7320
|
|
|
6749
|
-
const
|
|
6750
|
-
const {
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
7321
|
+
const ElementChart = React.memo(({ type, elementConfig, renderElement }) => {
|
|
7322
|
+
const { config } = useWidgetConfig(type);
|
|
7323
|
+
return (jsxRuntime.jsx(Chart, { type: type, config: config, elementConfig: elementConfig, element: elementConfig, renderElement: renderElement }));
|
|
7324
|
+
});
|
|
7325
|
+
|
|
7326
|
+
const ElementChips = React.memo(({ type, elementConfig }) => {
|
|
7327
|
+
const { attributes } = useWidgetContext(type);
|
|
7328
|
+
const { attributeName, options, style } = elementConfig || {};
|
|
7329
|
+
const { separator, bgColor, fontColor, fontSize } = options || {};
|
|
7330
|
+
const attribute = getAttributeByName(attributeName, attributes);
|
|
7331
|
+
const tags = attribute?.value?.split(separator || ",");
|
|
7332
|
+
return (jsxRuntime.jsx(DashboardChipsContainer, { style: style, children: tags?.map(tag => (jsxRuntime.jsx(DashboardChip$1, { text: tag, "$bgColor": bgColor, "$fontColor": fontColor, "$fontSize": fontSize, "$isDefault": true }, tag))) }));
|
|
6754
7333
|
});
|
|
6755
7334
|
|
|
6756
7335
|
const StyledIconFontSizeMixin = styled.css `
|
|
@@ -6770,35 +7349,53 @@ const StyledIcon = styled(uilibGl.Icon) `
|
|
|
6770
7349
|
${({ fontColor }) => !!fontColor && StyledIconFontColorMixin};
|
|
6771
7350
|
`;
|
|
6772
7351
|
|
|
6773
|
-
const ElementIcon =
|
|
7352
|
+
const ElementIcon = React.memo(({ type, elementConfig }) => {
|
|
6774
7353
|
const { attributes } = useWidgetContext(type);
|
|
6775
7354
|
const { value, attributeName, options } = elementConfig || {};
|
|
6776
7355
|
const { fontSize, fontColor } = options || {};
|
|
6777
|
-
const iconValue =
|
|
7356
|
+
const iconValue = React.useMemo(() => (attributeName ? attributes?.find(item => item.name === attributeName)?.value : value), [attributeName, attributes, value]);
|
|
6778
7357
|
return jsxRuntime.jsx(StyledIcon, { kind: iconValue, fontSize: fontSize, fontColor: fontColor });
|
|
6779
7358
|
});
|
|
6780
7359
|
|
|
6781
|
-
const
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
|
|
7360
|
+
const ElementImage = React.memo(({ type, elementConfig }) => {
|
|
7361
|
+
const { attributes } = useWidgetContext(type);
|
|
7362
|
+
const { value, attributeName, options } = elementConfig || {};
|
|
7363
|
+
const { width } = options || {};
|
|
7364
|
+
const firstImage = React.useMemo(() => {
|
|
7365
|
+
if (value) {
|
|
7366
|
+
return value.toString();
|
|
7367
|
+
}
|
|
7368
|
+
if (!attributeName || Array.isArray(attributeName)) {
|
|
7369
|
+
return null;
|
|
7370
|
+
}
|
|
7371
|
+
const attribute = attributes?.find(item => item.name === attributeName);
|
|
7372
|
+
return attribute?.value?.split(";")?.[0];
|
|
7373
|
+
}, [attributeName, attributes, value]);
|
|
7374
|
+
return firstImage ? jsxRuntime.jsx("img", { src: firstImage, alt: firstImage, width: width }) : null;
|
|
7375
|
+
});
|
|
6794
7376
|
|
|
6795
|
-
const
|
|
7377
|
+
const ElementLegend = React.memo(({ type, element, elementConfig, expandedContainers }) => {
|
|
6796
7378
|
const { attributes } = useWidgetContext(type);
|
|
6797
|
-
const {
|
|
6798
|
-
const {
|
|
6799
|
-
const
|
|
6800
|
-
const
|
|
6801
|
-
|
|
7379
|
+
const { options } = elementConfig || {};
|
|
7380
|
+
const { twoColumns, chartId, relatedDataSources } = options || {};
|
|
7381
|
+
const chartElement = React.useMemo(() => findAnd.returnFound(element?.children, { id: chartId }), [chartId, element?.children]);
|
|
7382
|
+
const { data, loading } = useChartData({
|
|
7383
|
+
element: chartElement,
|
|
7384
|
+
type,
|
|
7385
|
+
});
|
|
7386
|
+
const legendData = React.useMemo(() => {
|
|
7387
|
+
if (!data[0]?.items?.length)
|
|
7388
|
+
return [];
|
|
7389
|
+
const relatedAttributes = relatedDataSources || [];
|
|
7390
|
+
const isRelated = !!relatedAttributes?.length;
|
|
7391
|
+
return isRelated
|
|
7392
|
+
? data[0].items
|
|
7393
|
+
: data[0].items.map(item => {
|
|
7394
|
+
const attribute = attributes?.find(({ name }) => name === item.name);
|
|
7395
|
+
return { ...item, name: attribute?.alias || item.name };
|
|
7396
|
+
});
|
|
7397
|
+
}, [attributes, data, relatedDataSources]);
|
|
7398
|
+
return !chartElement?.options?.expanded || expandedContainers?.[chartElement.id] ? (jsxRuntime.jsx(ChartLegend, { data: legendData, loading: loading, chartElement: chartElement, twoColumns: twoColumns, type: type })) : null;
|
|
6802
7399
|
});
|
|
6803
7400
|
|
|
6804
7401
|
const ExternalLink = styled(uilibGl.IconButton).attrs(() => ({
|
|
@@ -6850,17 +7447,17 @@ const LocalLinkCopy = styled(uilibGl.Flex) `
|
|
|
6850
7447
|
justify-content: center;
|
|
6851
7448
|
`;
|
|
6852
7449
|
|
|
6853
|
-
const LocalLink =
|
|
7450
|
+
const LocalLink = React.memo(({ link }) => {
|
|
6854
7451
|
const { t } = useGlobalContext();
|
|
6855
7452
|
const [isOpen, toggleOpen] = useToggle();
|
|
6856
|
-
const onCopy =
|
|
7453
|
+
const onCopy = React.useCallback(() => {
|
|
6857
7454
|
navigator.clipboard.writeText(link);
|
|
6858
7455
|
toggleOpen();
|
|
6859
7456
|
}, [link, toggleOpen]);
|
|
6860
7457
|
return (jsxRuntime.jsx(uilibGl.Popover, { open: isOpen, zIndex: 10, onRequestClose: toggleOpen, anchorOrigin: "bottom-right", targetOrigin: "top-right", anchor: jsxRuntime.jsx(LocalLinkButton, { onClick: toggleOpen }), children: jsxRuntime.jsxs(LocalLinkBlank, { children: [jsxRuntime.jsx("a", { href: link, target: "_blank", rel: "noreferrer", children: link }), jsxRuntime.jsx(LocalLinkCopy, { children: jsxRuntime.jsx(uilibGl.IconButton, { kind: "copy", onClick: onCopy, children: t("copy", { ns: "dashboard" }) }) })] }) }));
|
|
6861
7458
|
});
|
|
6862
7459
|
|
|
6863
|
-
const ElementLink =
|
|
7460
|
+
const ElementLink = React.memo(({ type, elementConfig }) => {
|
|
6864
7461
|
const { attributes } = useWidgetContext(type);
|
|
6865
7462
|
const attribute = getAttributeByName(elementConfig?.attributeName, attributes);
|
|
6866
7463
|
const link = attribute?.value;
|
|
@@ -6869,198 +7466,273 @@ const ElementLink = react.memo(({ type, elementConfig }) => {
|
|
|
6869
7466
|
return link.startsWith("http") ? jsxRuntime.jsx(ExternalLink, { onClick: () => window.open(link) }) : jsxRuntime.jsx(LocalLink, { link: link });
|
|
6870
7467
|
});
|
|
6871
7468
|
|
|
6872
|
-
const
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
background-color: ${({ theme: { palette } }) => palette.primary};
|
|
6876
|
-
text-transform: none;
|
|
6877
|
-
|
|
6878
|
-
:hover {
|
|
6879
|
-
background-color: ${({ theme: { palette } }) => palette.primaryDeep};
|
|
6880
|
-
}
|
|
7469
|
+
const SmallPreviewContainer = styled.div `
|
|
7470
|
+
width: 100%;
|
|
7471
|
+
height: 100%;
|
|
6881
7472
|
`;
|
|
6882
7473
|
|
|
6883
|
-
const
|
|
6884
|
-
const { attributes } = useWidgetContext(type);
|
|
6885
|
-
const
|
|
6886
|
-
const link = attribute?.value;
|
|
6887
|
-
if (!link || typeof link !== "string")
|
|
6888
|
-
return null;
|
|
6889
|
-
return (jsxRuntime.jsx(ImageContainerButton, { onClick: () => window.open(attribute?.value), children: elementConfig.value || "" }));
|
|
6890
|
-
});
|
|
6891
|
-
|
|
6892
|
-
const NoLiveSnapshot = () => {
|
|
6893
|
-
return (jsxRuntime.jsxs(NoLiveSnapshotContainer, { children: [jsxRuntime.jsx(uilibGl.Icon, { kind: "alert" }), jsxRuntime.jsx(uilibGl.Description, { children: "\u0421\u043D\u0438\u043C\u043E\u043A \u043D\u0435 \u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D" })] }));
|
|
6894
|
-
};
|
|
6895
|
-
|
|
6896
|
-
const DEFAULT_ARCHIVED_PERIOD = "#24h";
|
|
6897
|
-
const SNAPSHOTS_PER_PAGE = 10;
|
|
6898
|
-
const getDuration = (archivePeriod) => {
|
|
6899
|
-
const lastLetter = archivePeriod[archivePeriod.length - 1];
|
|
6900
|
-
const value = archivePeriod.slice(1, -1);
|
|
6901
|
-
const prop = lastLetter === "d"
|
|
6902
|
-
? "days"
|
|
6903
|
-
: lastLetter === "h"
|
|
6904
|
-
? "hours"
|
|
6905
|
-
: lastLetter === "m"
|
|
6906
|
-
? "minutes"
|
|
6907
|
-
: lastLetter === "s"
|
|
6908
|
-
? "seconds"
|
|
6909
|
-
: null;
|
|
6910
|
-
if (!lastLetter || !value || !prop)
|
|
6911
|
-
return {};
|
|
6912
|
-
return { [prop]: Number(value) };
|
|
6913
|
-
};
|
|
6914
|
-
const useCameraAttribute = (cameraId) => {
|
|
6915
|
-
const { api } = useGlobalContext();
|
|
6916
|
-
const [currentIndex, setCurrentIndex] = react.useState(0);
|
|
6917
|
-
const [currentPage, setCurrentPage] = react.useState(0);
|
|
6918
|
-
const [timeline, setTimeline] = react.useState([]);
|
|
6919
|
-
const [isLoadingSnapshot, setLoadingSnapshot] = react.useState(false);
|
|
6920
|
-
const [isLoadingTimeline, setLoadingTimeline] = react.useState(false);
|
|
7474
|
+
const ElementSlideshow = ({ elementConfig, type, renderElement }) => {
|
|
7475
|
+
const { expandedContainers, dataSources, attributes } = useWidgetContext(type);
|
|
7476
|
+
const [currentIndex, setCurrentIndex] = React.useState(0);
|
|
6921
7477
|
const [isOpenGallery, toggleGallery] = useToggle();
|
|
6922
|
-
const
|
|
6923
|
-
const
|
|
6924
|
-
// Todo get archivePeriod from project configuration
|
|
6925
|
-
const archivePeriod = /* appConfig?.settings?.cameraAttribute?.archivePeriod ||*/ DEFAULT_ARCHIVED_PERIOD;
|
|
6926
|
-
const onNextPage = react.useCallback(() => {
|
|
6927
|
-
setCurrentPage(currentPage + 1);
|
|
6928
|
-
}, [currentPage]);
|
|
6929
|
-
react.useEffect(() => {
|
|
6930
|
-
(async () => {
|
|
6931
|
-
if (!cameraId)
|
|
6932
|
-
return;
|
|
6933
|
-
setLoadingSnapshot(true);
|
|
6934
|
-
const snapshot = null; // await api.cameras.getLiveSnapshot(cameraId);
|
|
6935
|
-
const url = URL.createObjectURL(snapshot);
|
|
6936
|
-
setLoadingSnapshot(false);
|
|
6937
|
-
setLoadingTimeline(true);
|
|
6938
|
-
imagesRef.current = [
|
|
6939
|
-
{
|
|
6940
|
-
src: url,
|
|
6941
|
-
startTime: new Date(),
|
|
6942
|
-
},
|
|
6943
|
-
];
|
|
6944
|
-
setGalleryImages([
|
|
6945
|
-
{
|
|
6946
|
-
src: url,
|
|
6947
|
-
fileName: formatDate$1(new Date()),
|
|
6948
|
-
},
|
|
6949
|
-
]);
|
|
6950
|
-
const formatDateOptions = { dateFormat: exports.DateFormat.UTC };
|
|
6951
|
-
const startTime = formatDate$1(dateFns.sub(new Date(), getDuration(archivePeriod)), formatDateOptions);
|
|
6952
|
-
const endTime = formatDate$1(new Date(), formatDateOptions);
|
|
6953
|
-
const timelineResponse = await api.cameras.getArchiveTimeline({ cameraId, startTime, endTime });
|
|
6954
|
-
if (!timelineResponse.success || !timelineResponse.timeline.length)
|
|
6955
|
-
return;
|
|
6956
|
-
timelineResponse.timeline.reverse();
|
|
6957
|
-
setTimeline(timelineResponse.timeline);
|
|
6958
|
-
})();
|
|
6959
|
-
}, [cameraId]);
|
|
6960
|
-
react.useEffect(() => {
|
|
6961
|
-
if (!timeline.length)
|
|
6962
|
-
return;
|
|
6963
|
-
const timelinePage = timeline.slice(currentPage * SNAPSHOTS_PER_PAGE, (currentPage + 1) * SNAPSHOTS_PER_PAGE);
|
|
6964
|
-
for (const item of timelinePage) {
|
|
6965
|
-
if (!item)
|
|
6966
|
-
continue;
|
|
6967
|
-
api.cameras
|
|
6968
|
-
.getArchiveSnapshot({
|
|
6969
|
-
cameraId,
|
|
6970
|
-
time: item.startTime,
|
|
6971
|
-
})
|
|
6972
|
-
.then(response => {
|
|
6973
|
-
const newImages = [
|
|
6974
|
-
...imagesRef.current,
|
|
6975
|
-
{ src: URL.createObjectURL(response), startTime: new Date(item.startTime) },
|
|
6976
|
-
];
|
|
6977
|
-
newImages.sort((a, b) => (a.startTime < b.startTime ? 1 : a.startTime > b.startTime ? -1 : 0));
|
|
6978
|
-
imagesRef.current = newImages;
|
|
6979
|
-
setGalleryImages(newImages.map(newImage => ({
|
|
6980
|
-
src: newImage.src,
|
|
6981
|
-
fileName: formatDate$1(newImage.startTime, { dateFormat: exports.DateFormat.DateTime }),
|
|
6982
|
-
})));
|
|
6983
|
-
if (newImages.length === timelinePage.length) {
|
|
6984
|
-
setLoadingTimeline(false);
|
|
6985
|
-
}
|
|
6986
|
-
});
|
|
6987
|
-
}
|
|
6988
|
-
}, [timeline, currentPage]);
|
|
6989
|
-
return [
|
|
6990
|
-
{
|
|
6991
|
-
currentIndex,
|
|
6992
|
-
currentPage,
|
|
6993
|
-
totalCount: timeline.length,
|
|
6994
|
-
galleryImages,
|
|
6995
|
-
isLoadingSnapshot,
|
|
6996
|
-
isLoadingTimeline,
|
|
6997
|
-
isOpenGallery,
|
|
6998
|
-
},
|
|
6999
|
-
{
|
|
7000
|
-
toggleGallery,
|
|
7001
|
-
setGalleryImages,
|
|
7002
|
-
setCurrentIndex,
|
|
7003
|
-
onNextPage,
|
|
7004
|
-
},
|
|
7005
|
-
];
|
|
7006
|
-
};
|
|
7007
|
-
|
|
7008
|
-
const ElementCamera = ({ type, renderElement, elementConfig, field }) => {
|
|
7009
|
-
const { expandedContainers, attributes } = useWidgetContext(type);
|
|
7010
|
-
const attribute = getAttributeByName(elementConfig?.attributeName, attributes);
|
|
7011
|
-
const value = attribute?.value;
|
|
7012
|
-
const { id, options } = elementConfig || {};
|
|
7013
|
-
const { expandable, expanded } = options || {};
|
|
7478
|
+
const { id, options, attributeName } = elementConfig || {};
|
|
7479
|
+
const { expandable, expanded, relatedDataSource } = options || {};
|
|
7014
7480
|
const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
|
|
7015
|
-
const
|
|
7016
|
-
|
|
7481
|
+
const images = React.useMemo(() => {
|
|
7482
|
+
const dataSource = relatedDataSource ? dataSources?.find(({ name }) => name === relatedDataSource) : null;
|
|
7483
|
+
const array = dataSource
|
|
7484
|
+
? dataSource.features.map(feature => feature.attributes[attributeName])
|
|
7485
|
+
: getSlideshowImages({
|
|
7486
|
+
element: elementConfig,
|
|
7487
|
+
attribute: attributes?.find(({ name }) => name === attributeName),
|
|
7488
|
+
});
|
|
7489
|
+
return (array?.map(image => ({
|
|
7490
|
+
src: image,
|
|
7491
|
+
fileName: image,
|
|
7492
|
+
})) || []);
|
|
7493
|
+
}, [attributeName, attributes, dataSources, elementConfig, relatedDataSource]);
|
|
7494
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), isVisible && (jsxRuntime.jsxs(SmallPreviewContainer, { children: [jsxRuntime.jsx(SmallPreview, { images: images, currentIndex: currentIndex, setCurrentIndex: setCurrentIndex, onClick: toggleGallery }), isOpenGallery && (jsxRuntime.jsx(uilibGl.Preview, { images: images,
|
|
7017
7495
|
// currentIndex={currentIndex}
|
|
7018
|
-
//
|
|
7019
|
-
|
|
7020
|
-
isOpen: isOpenGallery,
|
|
7021
|
-
// isLoading={isLoadingTimeline}
|
|
7022
|
-
// hasSidebar
|
|
7023
|
-
onClose: toggleGallery }))] }))] }));
|
|
7496
|
+
// totalCount={images.length}
|
|
7497
|
+
isOpen: isOpenGallery, onClose: toggleGallery }))] }))] }));
|
|
7024
7498
|
};
|
|
7025
7499
|
|
|
7026
|
-
const
|
|
7027
|
-
const {
|
|
7028
|
-
return (jsxRuntime.jsx(Chart, { type: type, config: config, elementConfig: elementConfig, element: elementConfig, renderElement: renderElement }));
|
|
7029
|
-
});
|
|
7030
|
-
|
|
7031
|
-
const ElementLegend = react.memo(({ type, element, elementConfig, expandedContainers }) => {
|
|
7032
|
-
const { attributes } = useWidgetContext(type);
|
|
7500
|
+
const ElementSvg = React.memo(({ type, elementConfig }) => {
|
|
7501
|
+
const { layerInfo, attributes } = useWidgetContext(type);
|
|
7033
7502
|
const { options } = elementConfig || {};
|
|
7034
|
-
const {
|
|
7035
|
-
|
|
7036
|
-
const { data, loading } = useChartData({
|
|
7037
|
-
element: chartElement,
|
|
7038
|
-
type,
|
|
7039
|
-
});
|
|
7040
|
-
const legendData = react.useMemo(() => {
|
|
7041
|
-
if (!data[0]?.items?.length)
|
|
7042
|
-
return [];
|
|
7043
|
-
const relatedAttributes = relatedDataSources || [];
|
|
7044
|
-
const isRelated = !!relatedAttributes?.length;
|
|
7045
|
-
return isRelated
|
|
7046
|
-
? data[0].items
|
|
7047
|
-
: data[0].items.map(item => {
|
|
7048
|
-
const attribute = attributes?.find(({ name }) => name === item.name);
|
|
7049
|
-
return { ...item, name: attribute?.alias || item.name };
|
|
7050
|
-
});
|
|
7051
|
-
}, [attributes, data, relatedDataSources]);
|
|
7052
|
-
return !chartElement?.options?.expanded || expandedContainers?.[chartElement.id] ? (jsxRuntime.jsx(ChartLegend, { data: legendData, loading: loading, chartElement: chartElement, twoColumns: twoColumns, type: type })) : null;
|
|
7503
|
+
const { width, height, fontColor } = options || {};
|
|
7504
|
+
return (jsxRuntime.jsx(SvgImage, { url: getSvgUrl({ elementConfig, layerInfo, attributes }), width: width, height: height, fontColor: fontColor }));
|
|
7053
7505
|
});
|
|
7054
7506
|
|
|
7055
|
-
const
|
|
7507
|
+
const TooltipIcon = styled(uilibGl.Icon) `
|
|
7508
|
+
&&& {
|
|
7509
|
+
:after {
|
|
7510
|
+
font-size: 0.75rem;
|
|
7511
|
+
color: ${({ theme: { palette } }) => palette.iconDisabled};
|
|
7512
|
+
transition: color ${uilibGl.transition.hover};
|
|
7513
|
+
}
|
|
7514
|
+
|
|
7515
|
+
:hover:after {
|
|
7516
|
+
color: ${({ theme: { palette } }) => palette.icon};
|
|
7517
|
+
}
|
|
7518
|
+
}
|
|
7519
|
+
`;
|
|
7520
|
+
|
|
7521
|
+
const ElementTooltip = React.memo(({ type, elementConfig }) => {
|
|
7056
7522
|
const { attributes } = useWidgetContext(type);
|
|
7057
|
-
const { attributeName, options
|
|
7058
|
-
const {
|
|
7523
|
+
const { attributeName, options } = elementConfig || {};
|
|
7524
|
+
const { icon } = options || {};
|
|
7059
7525
|
const attribute = getAttributeByName(attributeName, attributes);
|
|
7060
|
-
const
|
|
7061
|
-
return (jsxRuntime.jsx(
|
|
7526
|
+
const text = (attribute?.value || elementConfig?.value);
|
|
7527
|
+
return text ? (jsxRuntime.jsx(uilibGl.Tooltip, { placement: "top", arrow: true, content: text, children: ref => jsxRuntime.jsx(TooltipIcon, { kind: icon || "question", ref: ref }) })) : null;
|
|
7062
7528
|
});
|
|
7063
7529
|
|
|
7530
|
+
const SlideshowHeaderWrapper = styled.div `
|
|
7531
|
+
padding: ${({ withPadding }) => (withPadding ? "0.5rem 0.5rem 0" : 0)};
|
|
7532
|
+
|
|
7533
|
+
${Header} {
|
|
7534
|
+
align-items: flex-start;
|
|
7535
|
+
width: calc(100% + 2rem);
|
|
7536
|
+
height: ${({ big }) => (big ? "15.5rem" : "auto")};
|
|
7537
|
+
padding: 1.5rem;
|
|
7538
|
+
margin: -1rem -1rem 0 -1rem;
|
|
7539
|
+
border-radius: ${({ theme: { borderRadius } }) => borderRadius.medium};
|
|
7540
|
+
|
|
7541
|
+
${SmallPreviewCounter} {
|
|
7542
|
+
bottom: ${({ withPadding }) => (withPadding ? 0.625 : 1.125)}rem;
|
|
7543
|
+
}
|
|
7544
|
+
|
|
7545
|
+
:before,
|
|
7546
|
+
:after {
|
|
7547
|
+
content: "";
|
|
7548
|
+
z-index: 2;
|
|
7549
|
+
position: absolute;
|
|
7550
|
+
top: 0;
|
|
7551
|
+
left: 0;
|
|
7552
|
+
width: 100%;
|
|
7553
|
+
}
|
|
7554
|
+
|
|
7555
|
+
:before {
|
|
7556
|
+
height: 100%;
|
|
7557
|
+
background: rgba(32, 46, 53, 0.25);
|
|
7558
|
+
}
|
|
7559
|
+
|
|
7560
|
+
:after {
|
|
7561
|
+
height: 4.5rem;
|
|
7562
|
+
background: linear-gradient(180deg, #000000 0%, rgba(0, 0, 0, 0) 100%);
|
|
7563
|
+
}
|
|
7564
|
+
|
|
7565
|
+
:hover {
|
|
7566
|
+
${SmallPreviewControl}, ${SmallPreviewCounter} {
|
|
7567
|
+
opacity: 1;
|
|
7568
|
+
}
|
|
7569
|
+
}
|
|
7570
|
+
}
|
|
7571
|
+
`;
|
|
7572
|
+
const ImageContainerBg = styled.div `
|
|
7573
|
+
position: absolute;
|
|
7574
|
+
top: 0;
|
|
7575
|
+
bottom: 0;
|
|
7576
|
+
left: 0;
|
|
7577
|
+
right: 0;
|
|
7578
|
+
|
|
7579
|
+
img {
|
|
7580
|
+
width: 100%;
|
|
7581
|
+
height: 100%;
|
|
7582
|
+
object-position: center;
|
|
7583
|
+
object-fit: cover;
|
|
7584
|
+
}
|
|
7585
|
+
`;
|
|
7586
|
+
const HeaderSlideshow = styled.div `
|
|
7587
|
+
position: absolute;
|
|
7588
|
+
top: 0;
|
|
7589
|
+
bottom: ${({ height }) => (height ? `${height}px` : 0)};
|
|
7590
|
+
left: 0;
|
|
7591
|
+
right: 0;
|
|
7592
|
+
|
|
7593
|
+
img {
|
|
7594
|
+
width: 100%;
|
|
7595
|
+
height: 100%;
|
|
7596
|
+
min-height: inherit;
|
|
7597
|
+
object-position: center;
|
|
7598
|
+
object-fit: cover;
|
|
7599
|
+
}
|
|
7600
|
+
`;
|
|
7601
|
+
|
|
7602
|
+
const FeatureCardSlideshowHeader = ({ isRow }) => {
|
|
7603
|
+
const { layerInfo } = useWidgetContext(exports.WidgetType.FeatureCard);
|
|
7604
|
+
const { config } = useWidgetConfig(exports.WidgetType.FeatureCard);
|
|
7605
|
+
const { header, options } = config || {};
|
|
7606
|
+
const renderElement = useHeaderRender(header);
|
|
7607
|
+
return (jsxRuntime.jsx(SlideshowHeaderWrapper, { big: true, withPadding: options?.withPadding, children: jsxRuntime.jsx(uilibGl.ThemeProvider, { theme: uilibGl.darkTheme, children: jsxRuntime.jsxs(Header, { "$isRow": isRow, children: [jsxRuntime.jsxs(HeaderFrontView, { children: [jsxRuntime.jsxs(HeaderContainer, { children: [jsxRuntime.jsx(LayerIcon, { layerInfo: layerInfo }), jsxRuntime.jsx(FeatureCardTitle, { title: renderElement({
|
|
7608
|
+
id: "title",
|
|
7609
|
+
wrap: false,
|
|
7610
|
+
}), description: renderElement({
|
|
7611
|
+
id: "description",
|
|
7612
|
+
wrap: false,
|
|
7613
|
+
}) })] }), jsxRuntime.jsx(FeatureCardButtons, {})] }), jsxRuntime.jsx(ImageContainerBg, { children: renderElement({
|
|
7614
|
+
id: "bgImage",
|
|
7615
|
+
wrap: false,
|
|
7616
|
+
}) }), jsxRuntime.jsx(HeaderSlideshow, { height: options?.height, children: renderElement({
|
|
7617
|
+
id: "slideshow",
|
|
7618
|
+
wrap: false,
|
|
7619
|
+
}) })] }) }) }));
|
|
7620
|
+
};
|
|
7621
|
+
|
|
7622
|
+
const getDashboardHeader = (templateName) => {
|
|
7623
|
+
switch (templateName) {
|
|
7624
|
+
case exports.HeaderTemplate.Default:
|
|
7625
|
+
default:
|
|
7626
|
+
return DashboardDefaultHeader;
|
|
7627
|
+
}
|
|
7628
|
+
};
|
|
7629
|
+
|
|
7630
|
+
const getDataFromAttributes = (t, config, attributes) => {
|
|
7631
|
+
const colors = config?.options?.colors || FEATURE_CARD_DEFAULT_COLORS;
|
|
7632
|
+
const data = config?.children?.map(({ attributeName }, index) => {
|
|
7633
|
+
const attribute = attributes?.find(({ name }) => name === attributeName);
|
|
7634
|
+
return {
|
|
7635
|
+
name: attribute?.name || "",
|
|
7636
|
+
value: attribute ? Number(attribute.value) : 0,
|
|
7637
|
+
color: colors[index] || FEATURE_CARD_OTHER_COLOR
|
|
7638
|
+
};
|
|
7639
|
+
});
|
|
7640
|
+
if (config?.options?.orderByValue) {
|
|
7641
|
+
data.sort((a, b) => b.value - a.value);
|
|
7642
|
+
}
|
|
7643
|
+
const isOtherSliced = config?.options?.otherItems && config.options.otherItems < data.length;
|
|
7644
|
+
if (!isOtherSliced)
|
|
7645
|
+
return data;
|
|
7646
|
+
const otherValue = data
|
|
7647
|
+
.slice(0, config?.options?.otherItems)
|
|
7648
|
+
.reduce((prev, { value }) => prev + value, 0);
|
|
7649
|
+
return [
|
|
7650
|
+
...data?.slice(0, config.options?.otherItems),
|
|
7651
|
+
{
|
|
7652
|
+
name: t("other", { ns: "dashboard" }),
|
|
7653
|
+
color: FEATURE_CARD_OTHER_COLOR,
|
|
7654
|
+
value: Number(otherValue)
|
|
7655
|
+
}
|
|
7656
|
+
];
|
|
7657
|
+
};
|
|
7658
|
+
|
|
7659
|
+
const getDataFromRelatedFeatures = ({ t, config, filters, relatedConfig, dataSource, layerInfo }) => {
|
|
7660
|
+
if (!dataSource || !dataSource?.features?.length) {
|
|
7661
|
+
return [];
|
|
7662
|
+
}
|
|
7663
|
+
const { colors } = config.options;
|
|
7664
|
+
const layerDefinition = getLayerDefinition(layerInfo);
|
|
7665
|
+
let data = JSON.parse(JSON.stringify(dataSource?.features));
|
|
7666
|
+
const sortAttribute = config?.options?.orderByValue
|
|
7667
|
+
? relatedConfig.attributeName
|
|
7668
|
+
: config?.options?.orderByTitle
|
|
7669
|
+
? relatedConfig.attributeTitle
|
|
7670
|
+
: null;
|
|
7671
|
+
if (sortAttribute) {
|
|
7672
|
+
data.sort((a, b) => b.attributes[sortAttribute] - a.attributes[sortAttribute]);
|
|
7673
|
+
}
|
|
7674
|
+
const isOtherSliced = config?.options?.otherItems && config.options.otherItems < data.length;
|
|
7675
|
+
const otherValue = isOtherSliced
|
|
7676
|
+
? data
|
|
7677
|
+
.slice(config.options.otherItems)
|
|
7678
|
+
.reduce((prev, { attributes }) => prev + attributes[relatedConfig.attributeName], 0)
|
|
7679
|
+
: null;
|
|
7680
|
+
if (isOtherSliced) {
|
|
7681
|
+
data = data.slice(0, config?.options?.otherItems);
|
|
7682
|
+
}
|
|
7683
|
+
const gradientArray = relatedConfig.chartAxis && colors?.length < data.length
|
|
7684
|
+
? new Gradient()
|
|
7685
|
+
.setColorGradient(colors[0], colors[colors.length - 1])
|
|
7686
|
+
.setMidpoint(data.length)
|
|
7687
|
+
.getColors()
|
|
7688
|
+
: colors;
|
|
7689
|
+
const filter = getConfigFilter(relatedConfig?.filterName, filters);
|
|
7690
|
+
const result = data.reduce((acc, feature, index) => {
|
|
7691
|
+
if (relatedConfig?.filterName && !filter) {
|
|
7692
|
+
return acc;
|
|
7693
|
+
}
|
|
7694
|
+
const attributeName = feature.attributes[relatedConfig.attributeName];
|
|
7695
|
+
const attributeTitle = feature.attributes[relatedConfig.attributeTitle];
|
|
7696
|
+
const attributeColor = feature.attributes[relatedConfig.attributeColor];
|
|
7697
|
+
return [
|
|
7698
|
+
...acc,
|
|
7699
|
+
{
|
|
7700
|
+
name: formatAttributeValue({
|
|
7701
|
+
t,
|
|
7702
|
+
type: layerDefinition.attributes[relatedConfig.attributeTitle]?.type,
|
|
7703
|
+
value: attributeTitle,
|
|
7704
|
+
stringFormat: layerDefinition.attributes[relatedConfig.attributeTitle]?.stringFormat
|
|
7705
|
+
}),
|
|
7706
|
+
value: attributeName === null ? null : Number(attributeName),
|
|
7707
|
+
color: attributeColor || gradientArray?.[index] || FEATURE_CARD_OTHER_COLOR,
|
|
7708
|
+
min: filter?.attributeMin ? feature.attributes[filter.attributeMin] : null,
|
|
7709
|
+
max: filter?.attributeMin ? feature.attributes[filter.attributeMax] : null
|
|
7710
|
+
}
|
|
7711
|
+
];
|
|
7712
|
+
}, []);
|
|
7713
|
+
if (isOtherSliced) {
|
|
7714
|
+
result.push({
|
|
7715
|
+
name: t("other", { ns: "dashboard" }),
|
|
7716
|
+
color: FEATURE_CARD_OTHER_COLOR,
|
|
7717
|
+
value: Number(otherValue)
|
|
7718
|
+
});
|
|
7719
|
+
}
|
|
7720
|
+
return result;
|
|
7721
|
+
};
|
|
7722
|
+
|
|
7723
|
+
const getDefaultConfig = ({ title, defaultTitle, items, baseMapName, position, resolution, srid, }) => {
|
|
7724
|
+
const dashboardConfiguration = JSON.parse(JSON.stringify(DEFAULT_DASHBOARD_CONFIG));
|
|
7725
|
+
const defaultPages = JSON.parse(JSON.stringify(DEFAULT_PAGES_CONFIG));
|
|
7726
|
+
const defaultPage = createConfigPage({ title, baseMapName, position, resolution, defaultTitle });
|
|
7727
|
+
if (items?.length) {
|
|
7728
|
+
const contentItems = items.map(item => createConfigLayer(item.name));
|
|
7729
|
+
defaultPage.layers.push(...contentItems);
|
|
7730
|
+
}
|
|
7731
|
+
defaultPages.children.push(defaultPage);
|
|
7732
|
+
dashboardConfiguration.children.push(defaultPages);
|
|
7733
|
+
return dashboardConfiguration;
|
|
7734
|
+
};
|
|
7735
|
+
|
|
7064
7736
|
const elementComponents = {
|
|
7065
7737
|
image: ElementImage,
|
|
7066
7738
|
slideshow: ElementSlideshow,
|
|
@@ -7152,6 +7824,20 @@ function getFeatureAttributes(feature = {}, layer, dataSource) {
|
|
|
7152
7824
|
});
|
|
7153
7825
|
}
|
|
7154
7826
|
|
|
7827
|
+
const getFeatureCardHeader = (templateName) => {
|
|
7828
|
+
switch (templateName) {
|
|
7829
|
+
case exports.HeaderTemplate.Slideshow:
|
|
7830
|
+
return FeatureCardSlideshowHeader;
|
|
7831
|
+
case exports.HeaderTemplate.Gradient:
|
|
7832
|
+
return FeatureCardGradientHeader;
|
|
7833
|
+
case exports.HeaderTemplate.Icon:
|
|
7834
|
+
return FeatureCardIconHeader;
|
|
7835
|
+
case exports.HeaderTemplate.Default:
|
|
7836
|
+
default:
|
|
7837
|
+
return FeatureCardDefaultHeader;
|
|
7838
|
+
}
|
|
7839
|
+
};
|
|
7840
|
+
|
|
7155
7841
|
const RangeNumberFilter = ({ type, filter }) => {
|
|
7156
7842
|
const { t } = useGlobalContext();
|
|
7157
7843
|
const { filters, changeFilters } = useWidgetContext(type);
|
|
@@ -7160,8 +7846,8 @@ const RangeNumberFilter = ({ type, filter }) => {
|
|
|
7160
7846
|
const { filters: configFilters } = currentPage;
|
|
7161
7847
|
const { filterName, width, step, label, minValue = RANGE_MIN_VALUE, maxValue = RANGE_MAX_VALUE } = filter.options;
|
|
7162
7848
|
const filterValue = [filters[filterName]?.min || minValue, filters[filterName]?.max || maxValue];
|
|
7163
|
-
const [value, setValue] =
|
|
7164
|
-
|
|
7849
|
+
const [value, setValue] = React.useState(filterValue);
|
|
7850
|
+
React.useEffect(() => {
|
|
7165
7851
|
updateDebounce(() => {
|
|
7166
7852
|
changeFilters({
|
|
7167
7853
|
[filterName]: {
|
|
@@ -7180,8 +7866,8 @@ const RangeNumberFilter = ({ type, filter }) => {
|
|
|
7180
7866
|
|
|
7181
7867
|
const TextFilter = ({ type, filter, config }) => {
|
|
7182
7868
|
const { filters, changeFilters, dataSources } = useWidgetContext(type);
|
|
7183
|
-
const suggestRef =
|
|
7184
|
-
const [totalCount, setTotalCount] =
|
|
7869
|
+
const suggestRef = React.useRef(null);
|
|
7870
|
+
const [totalCount, setTotalCount] = React.useState(0);
|
|
7185
7871
|
const { attributes, layerInfo } = useRelatedDataSourceAttributes({
|
|
7186
7872
|
type,
|
|
7187
7873
|
elementConfig: filter,
|
|
@@ -7191,10 +7877,10 @@ const TextFilter = ({ type, filter, config }) => {
|
|
|
7191
7877
|
const { filterName, searchFilterName, placeholder, width, height, multiSelect, variants } = filter.options;
|
|
7192
7878
|
const { eqlParameters } = (layerInfo?.configuration || {});
|
|
7193
7879
|
const layerParams = useLayerParams(layerInfo);
|
|
7194
|
-
const [value, setValue] =
|
|
7195
|
-
const configFilter =
|
|
7196
|
-
const searchFilter =
|
|
7197
|
-
const searchDataSource =
|
|
7880
|
+
const [value, setValue] = React.useState("");
|
|
7881
|
+
const configFilter = React.useMemo(() => getConfigFilter(filterName, configFilters), [configFilters, filterName]);
|
|
7882
|
+
const searchFilter = React.useMemo(() => getConfigFilter(searchFilterName, configFilters), [configFilters, searchFilterName]);
|
|
7883
|
+
const searchDataSource = React.useMemo(() => !!searchFilter?.relatedDataSource &&
|
|
7198
7884
|
configDataSources.find(({ name }) => name === searchFilter.relatedDataSource), [configDataSources, searchFilter?.relatedDataSource]);
|
|
7199
7885
|
const updateDataSource = useUpdateDataSource({
|
|
7200
7886
|
dataSource: searchDataSource,
|
|
@@ -7204,15 +7890,15 @@ const TextFilter = ({ type, filter, config }) => {
|
|
|
7204
7890
|
layerParams,
|
|
7205
7891
|
eqlParameters,
|
|
7206
7892
|
});
|
|
7207
|
-
const [options, setOptions] =
|
|
7208
|
-
const setFilterValue =
|
|
7893
|
+
const [options, setOptions] = React.useState([]);
|
|
7894
|
+
const setFilterValue = React.useCallback(newValue => {
|
|
7209
7895
|
changeFilters({
|
|
7210
7896
|
[filterName]: {
|
|
7211
7897
|
value: newValue,
|
|
7212
7898
|
},
|
|
7213
7899
|
}, configFilter?.resetFilters);
|
|
7214
7900
|
}, [changeFilters, configFilter?.resetFilters, filterName]);
|
|
7215
|
-
const onSelect =
|
|
7901
|
+
const onSelect = React.useCallback((newSelected) => {
|
|
7216
7902
|
const lastSelected = newSelected[newSelected.length - 1];
|
|
7217
7903
|
setFilterValue(multiSelect
|
|
7218
7904
|
? newSelected.map(item => item.value)
|
|
@@ -7221,7 +7907,7 @@ const TextFilter = ({ type, filter, config }) => {
|
|
|
7221
7907
|
: []);
|
|
7222
7908
|
setValue(multiSelect ? "" : lastSelected?.text || "");
|
|
7223
7909
|
}, [multiSelect, setFilterValue]);
|
|
7224
|
-
const onBlur =
|
|
7910
|
+
const onBlur = React.useCallback(() => {
|
|
7225
7911
|
if (variants) {
|
|
7226
7912
|
setFilterValue([value]);
|
|
7227
7913
|
}
|
|
@@ -7229,7 +7915,7 @@ const TextFilter = ({ type, filter, config }) => {
|
|
|
7229
7915
|
setOptions([]);
|
|
7230
7916
|
}
|
|
7231
7917
|
}, [variants, setFilterValue, value]);
|
|
7232
|
-
const onKeyUp =
|
|
7918
|
+
const onKeyUp = React.useCallback(e => {
|
|
7233
7919
|
if (e.key === "Enter") {
|
|
7234
7920
|
setFilterValue([value]);
|
|
7235
7921
|
}
|
|
@@ -7248,7 +7934,7 @@ const TextFilter = ({ type, filter, config }) => {
|
|
|
7248
7934
|
}));
|
|
7249
7935
|
},
|
|
7250
7936
|
});
|
|
7251
|
-
const search =
|
|
7937
|
+
const search = React.useCallback((searchValue, isLoadNext = false) => {
|
|
7252
7938
|
if (variants || !searchFilter?.attributeAlias || !searchFilter?.attributeValue)
|
|
7253
7939
|
return;
|
|
7254
7940
|
const newFilter = {
|
|
@@ -7270,11 +7956,11 @@ const TextFilter = ({ type, filter, config }) => {
|
|
|
7270
7956
|
updateDataSource,
|
|
7271
7957
|
options.length,
|
|
7272
7958
|
]);
|
|
7273
|
-
const infiniteScrollProps =
|
|
7959
|
+
const infiniteScrollProps = React.useMemo(() => ({
|
|
7274
7960
|
loadNext: () => loadNext(() => search(value, true)),
|
|
7275
7961
|
hasMore: totalCount > options.length,
|
|
7276
7962
|
}), [totalCount, options.length, loadNext, search, value]);
|
|
7277
|
-
const selected =
|
|
7963
|
+
const selected = React.useMemo(() => {
|
|
7278
7964
|
if (!filters[filterName]?.value)
|
|
7279
7965
|
return [];
|
|
7280
7966
|
return Array.isArray(filters[filterName].value)
|
|
@@ -7306,7 +7992,7 @@ const DropdownFilter = ({ type, filter, elementConfig }) => {
|
|
|
7306
7992
|
const { filterName, placeholder, width, noEmptyOption } = filter.options;
|
|
7307
7993
|
const { sliceItems } = useShownOtherItems(options);
|
|
7308
7994
|
const configFilter = getConfigFilter(filterName, configFilters);
|
|
7309
|
-
const filterOptions =
|
|
7995
|
+
const filterOptions = React.useMemo(() => {
|
|
7310
7996
|
const dataSource = getDataSource(configFilter.relatedDataSource, dataSources);
|
|
7311
7997
|
const listOptions = getListOptions(sliceItems(dataSource?.features), filterName, configFilters);
|
|
7312
7998
|
if (noEmptyOption === undefined || noEmptyOption === false) {
|
|
@@ -7314,12 +8000,12 @@ const DropdownFilter = ({ type, filter, elementConfig }) => {
|
|
|
7314
8000
|
}
|
|
7315
8001
|
return listOptions;
|
|
7316
8002
|
}, [configFilter.relatedDataSource, configFilters, dataSources, filterName, noEmptyOption, placeholder, sliceItems]);
|
|
7317
|
-
const value =
|
|
8003
|
+
const value = React.useMemo(() => filters?.[filterName] !== undefined
|
|
7318
8004
|
? Array.isArray(filters[filterName].value)
|
|
7319
8005
|
? null
|
|
7320
8006
|
: filters[filterName].value
|
|
7321
8007
|
: getConfigFilter(filterName, configFilters).defaultValue, [configFilters, filterName, filters]);
|
|
7322
|
-
const onChange =
|
|
8008
|
+
const onChange = React.useCallback((items) => {
|
|
7323
8009
|
changeFilters({ [filterName]: items[0] });
|
|
7324
8010
|
}, [changeFilters, filterName]);
|
|
7325
8011
|
if (!configFilter)
|
|
@@ -7362,7 +8048,7 @@ const ChartLoading = ({ column }) => (jsxRuntime.jsx(uilibGl.Flex, { position: "
|
|
|
7362
8048
|
|
|
7363
8049
|
const ContainerLoading = () => (jsxRuntime.jsx(uilibGl.Flex, { alignContent: "center", justifyContent: "center", width: "100%", children: jsxRuntime.jsx(uilibGl.CircularProgress, { diameter: 1.5, mono: true }) }));
|
|
7364
8050
|
|
|
7365
|
-
const ChartWrapper =
|
|
8051
|
+
const ChartWrapper = React.memo(({ width, height, column, loading, children }) => {
|
|
7366
8052
|
return (jsxRuntime.jsxs(ChartWrapperContainer, { column: column, style: { width, height }, children: [loading && jsxRuntime.jsx(ChartLoading, { column: column }), jsxRuntime.jsx(uilibGl.Flex, { opacity: loading ? FILTERED_VALUE_OPACITY / 100 : 1, children: children })] }));
|
|
7367
8053
|
});
|
|
7368
8054
|
|
|
@@ -7411,16 +8097,16 @@ const useBarChartFilter = ({ type, filter, elementConfig }) => {
|
|
|
7411
8097
|
const { t } = useGlobalContext();
|
|
7412
8098
|
const { isLoading, dataSources, filters, changeFilters } = useWidgetContext(type);
|
|
7413
8099
|
const { currentPage } = useWidgetPage(type);
|
|
7414
|
-
const [selectedPixels, setSelectedPixels] =
|
|
8100
|
+
const [selectedPixels, setSelectedPixels] = React.useState(null);
|
|
7415
8101
|
const { filterName } = filter.options;
|
|
7416
8102
|
const { options } = elementConfig;
|
|
7417
8103
|
const { barHeight, barWidth = DEFAULT_BAR_WIDTH, padding = DEFAULT_BAR_PADDING, height = DEFAULT_BAR_CHART_HEIGHT, radius = DEFAULT_BARCHART_RADIUS, width: configWidth, markers: configMarkers, colors: configColors, colorAttribute, defaultColor, primaryColor, drawMinMax } = options || {};
|
|
7418
8104
|
const barFullWidth = barWidth + padding;
|
|
7419
8105
|
const { filters: configFilters } = currentPage;
|
|
7420
|
-
const configFilter =
|
|
8106
|
+
const configFilter = React.useMemo(() => getConfigFilter(filterName, configFilters), [configFilters, filterName]);
|
|
7421
8107
|
const { relatedDataSource, attributeValue, defaultValue } = configFilter || {};
|
|
7422
|
-
const dataSource =
|
|
7423
|
-
const filterItems =
|
|
8108
|
+
const dataSource = React.useMemo(() => getDataSource(relatedDataSource, dataSources), [dataSources, relatedDataSource]);
|
|
8109
|
+
const filterItems = React.useMemo(() => getDataFromRelatedFeatures({
|
|
7424
8110
|
t,
|
|
7425
8111
|
dataSource,
|
|
7426
8112
|
config: elementConfig,
|
|
@@ -7442,32 +8128,32 @@ const useBarChartFilter = ({ type, filter, elementConfig }) => {
|
|
|
7442
8128
|
elementConfig,
|
|
7443
8129
|
t
|
|
7444
8130
|
]);
|
|
7445
|
-
const amount =
|
|
7446
|
-
const width =
|
|
7447
|
-
const data =
|
|
8131
|
+
const amount = React.useMemo(() => filterItems?.length || 0, [filterItems?.length]);
|
|
8132
|
+
const width = React.useMemo(() => configWidth || amount * barFullWidth, [amount, barFullWidth, configWidth]);
|
|
8133
|
+
const data = React.useMemo(() => getDataFromFilterItems(filterItems), [filterItems]);
|
|
7448
8134
|
const loading = isLoading && !amount;
|
|
7449
8135
|
const { formatFilterColor, onFilter } = useFeatureFilters(type, filterName, filterItems);
|
|
7450
|
-
const colors =
|
|
7451
|
-
const selectedRange =
|
|
7452
|
-
const customXAxis =
|
|
8136
|
+
const colors = React.useMemo(() => getColorsFromFilterItems(filterItems, defaultColor, formatFilterColor), [defaultColor, filterItems, formatFilterColor]);
|
|
8137
|
+
const selectedRange = React.useMemo(() => getIndexRange(selectedPixels, amount, barFullWidth), [amount, barFullWidth, selectedPixels]);
|
|
8138
|
+
const customXAxis = React.useCallback(xAxis => {
|
|
7453
8139
|
xAxis.select(".tick:first-of-type").attr("transform", "translate(0, 0)");
|
|
7454
8140
|
xAxis.select(".tick:last-of-type").attr("transform", `translate(${width}, 0)`);
|
|
7455
8141
|
}, [width]);
|
|
7456
|
-
const customXAxisBottom =
|
|
8142
|
+
const customXAxisBottom = React.useCallback(xAxisBottom => {
|
|
7457
8143
|
xAxisBottom.tickFormat((index) => (drawMinMax === undefined || drawMinMax) && (index === 0 || index === data.length - 1)
|
|
7458
8144
|
? data[index].groupName
|
|
7459
8145
|
: "");
|
|
7460
8146
|
}, [data, drawMinMax]);
|
|
7461
|
-
const customYAxis =
|
|
8147
|
+
const customYAxis = React.useCallback(yAxis => {
|
|
7462
8148
|
yAxis.remove();
|
|
7463
8149
|
}, []);
|
|
7464
|
-
const customBars =
|
|
8150
|
+
const customBars = React.useCallback(({ bars }) => {
|
|
7465
8151
|
bars.attr("rx", radius).attr("ry", radius);
|
|
7466
8152
|
}, [radius]);
|
|
7467
|
-
const tooltipY =
|
|
7468
|
-
const markers =
|
|
7469
|
-
const hasDefinedColors =
|
|
7470
|
-
const marshalledMap =
|
|
8153
|
+
const tooltipY = React.useMemo(() => (barHeight ? height - barHeight - DEFAULT_BAR_CHART_MARGINS.bottom : undefined), [barHeight, height]);
|
|
8154
|
+
const markers = React.useMemo(() => getChartMarkers(filterItems, configMarkers), [configMarkers, filterItems]);
|
|
8155
|
+
const hasDefinedColors = React.useMemo(() => configColors?.length || colorAttribute, [configColors, colorAttribute]);
|
|
8156
|
+
const marshalledMap = React.useCallback(items => {
|
|
7471
8157
|
if (hasDefinedColors)
|
|
7472
8158
|
return undefined;
|
|
7473
8159
|
return items.map(([item], index) => {
|
|
@@ -7481,22 +8167,22 @@ const useBarChartFilter = ({ type, filter, elementConfig }) => {
|
|
|
7481
8167
|
];
|
|
7482
8168
|
});
|
|
7483
8169
|
}, [defaultColor, hasDefinedColors, primaryColor, selectedRange, theme.palette.elementDeep, theme.palette.primary]);
|
|
7484
|
-
const minValue =
|
|
7485
|
-
const onBarClick =
|
|
8170
|
+
const minValue = React.useMemo(() => getMinValueFromFilterItems(filterItems), [filterItems]);
|
|
8171
|
+
const onBarClick = React.useCallback((group) => {
|
|
7486
8172
|
if (loading)
|
|
7487
8173
|
return;
|
|
7488
8174
|
setSelectedPixels([group.groupIndex * barFullWidth, group.groupIndex * barFullWidth]);
|
|
7489
8175
|
const feature = filterItems.find(({ value }) => value === group.value);
|
|
7490
8176
|
onFilter(feature.name);
|
|
7491
8177
|
}, [barFullWidth, filterItems, loading, onFilter]);
|
|
7492
|
-
const getValueRange =
|
|
8178
|
+
const getValueRange = React.useCallback((pixelRange) => {
|
|
7493
8179
|
const currentRange = pixelRange || selectedPixels;
|
|
7494
8180
|
const indexRange = getIndexRange(currentRange, filterItems?.length, barFullWidth);
|
|
7495
8181
|
if (!indexRange || lodash.isNil(filterItems[indexRange[0]]) || lodash.isNil(filterItems[indexRange[1]]))
|
|
7496
8182
|
return null;
|
|
7497
8183
|
return [filterItems[indexRange[0]].name, filterItems[indexRange[1]].name];
|
|
7498
8184
|
}, [barFullWidth, filterItems, selectedPixels]);
|
|
7499
|
-
const onSelect =
|
|
8185
|
+
const onSelect = React.useCallback((pixelRange) => {
|
|
7500
8186
|
const valueRange = getValueRange(pixelRange);
|
|
7501
8187
|
if (!valueRange)
|
|
7502
8188
|
return;
|
|
@@ -7509,25 +8195,25 @@ const useBarChartFilter = ({ type, filter, elementConfig }) => {
|
|
|
7509
8195
|
}
|
|
7510
8196
|
}, configFilter?.resetFilters);
|
|
7511
8197
|
}, [changeFilters, configFilter?.resetFilters, filterName, getValueRange]);
|
|
7512
|
-
const prevDisabled =
|
|
7513
|
-
const nextDisabled =
|
|
7514
|
-
const onPrev =
|
|
8198
|
+
const prevDisabled = React.useMemo(() => loading || !selectedPixels || selectedPixels?.[0] - barFullWidth < 0, [barFullWidth, loading, selectedPixels]);
|
|
8199
|
+
const nextDisabled = React.useMemo(() => loading || !selectedPixels || selectedPixels?.[1] + barFullWidth >= width, [barFullWidth, loading, selectedPixels, width]);
|
|
8200
|
+
const onPrev = React.useCallback(() => {
|
|
7515
8201
|
if (prevDisabled)
|
|
7516
8202
|
return;
|
|
7517
8203
|
onSelect([selectedPixels[0] - barFullWidth, selectedPixels[1] - barFullWidth]);
|
|
7518
8204
|
}, [barFullWidth, prevDisabled, onSelect, selectedPixels]);
|
|
7519
|
-
const onNext =
|
|
8205
|
+
const onNext = React.useCallback(() => {
|
|
7520
8206
|
if (nextDisabled)
|
|
7521
8207
|
return;
|
|
7522
8208
|
onSelect([selectedPixels[0] + barFullWidth, selectedPixels[1] + barFullWidth]);
|
|
7523
8209
|
}, [barFullWidth, nextDisabled, onSelect, selectedPixels]);
|
|
7524
|
-
|
|
8210
|
+
React.useEffect(() => {
|
|
7525
8211
|
if (selectedRange || !defaultValue || !filterItems?.length)
|
|
7526
8212
|
return;
|
|
7527
8213
|
const pixelRange = getPixelRange((Array.isArray(defaultValue) ? defaultValue : [defaultValue, defaultValue]), filterItems, barFullWidth);
|
|
7528
8214
|
onSelect(pixelRange);
|
|
7529
8215
|
}, [amount]);
|
|
7530
|
-
|
|
8216
|
+
React.useEffect(() => {
|
|
7531
8217
|
if (lodash.isEmpty(filters[filterName]?.value)) {
|
|
7532
8218
|
if (!lodash.isEmpty(selectedPixels)) {
|
|
7533
8219
|
setSelectedPixels(null);
|
|
@@ -7574,14 +8260,14 @@ const BarChartFilter = ({ type, config, elementConfig, filter }) => {
|
|
|
7574
8260
|
elementConfig,
|
|
7575
8261
|
filter
|
|
7576
8262
|
});
|
|
7577
|
-
const renderSelectedRange =
|
|
8263
|
+
const renderSelectedRange = React.useMemo(() => {
|
|
7578
8264
|
if (!selectedRange)
|
|
7579
8265
|
return null;
|
|
7580
8266
|
return (jsxRuntime.jsx(BarChartFilterSelected, { children: selectedRange[0] === selectedRange[1]
|
|
7581
8267
|
? data[selectedRange[0]].groupName
|
|
7582
8268
|
: `${data[selectedRange[0]].groupName} - ${data[selectedRange[1]].groupName}` }));
|
|
7583
8269
|
}, [data, selectedRange]);
|
|
7584
|
-
const renderTooltip =
|
|
8270
|
+
const renderTooltip = React.useCallback((groups) => {
|
|
7585
8271
|
const group = groups[0];
|
|
7586
8272
|
return (jsxRuntime.jsx(uilibGl.ThemeProvider, { children: jsxRuntime.jsx(TooltipContainer, { children: group.groupName === group.value.toString() ? group.value : [group.groupName, group.value].join(": ") }) }));
|
|
7587
8273
|
}, []);
|
|
@@ -7594,25 +8280,25 @@ const RangeDateFilter = ({ type, filter }) => {
|
|
|
7594
8280
|
const { t } = useGlobalContext();
|
|
7595
8281
|
const { changeFilters, dataSources } = useWidgetContext(type);
|
|
7596
8282
|
const { currentPage } = useWidgetPage(type);
|
|
7597
|
-
const [value, setValue] =
|
|
7598
|
-
const isInit =
|
|
8283
|
+
const [value, setValue] = React.useState([undefined, undefined]);
|
|
8284
|
+
const isInit = React.useRef(false);
|
|
7599
8285
|
const updateDebounce = useDebouncedCallback(FILTER_UPDATE_DEBOUNCE);
|
|
7600
8286
|
const { filters: configFilters } = currentPage;
|
|
7601
8287
|
const { filterName, label, minValue, maxValue, withTime } = filter.options;
|
|
7602
|
-
const configFilter =
|
|
7603
|
-
const dataSource =
|
|
7604
|
-
const { minFromData, maxFromData } =
|
|
8288
|
+
const configFilter = React.useMemo(() => getConfigFilter(filterName, configFilters), [configFilters, filterName]);
|
|
8289
|
+
const dataSource = React.useMemo(() => getDataSource(configFilter?.relatedDataSource, dataSources), [configFilter?.relatedDataSource, dataSources]);
|
|
8290
|
+
const { minFromData, maxFromData } = React.useMemo(() => dataSource?.features?.reduce((prev, { attributes }) => {
|
|
7605
8291
|
const date = getDate(attributes[configFilter?.attributeValue]);
|
|
7606
8292
|
return {
|
|
7607
8293
|
minFromData: !prev.minFromData ? date : date < prev.minFromData ? date : prev.minFromData,
|
|
7608
8294
|
maxFromData: !prev.maxFromData ? date : date > prev.maxFromData ? date : prev.maxFromData
|
|
7609
8295
|
};
|
|
7610
8296
|
}, DEFAULT_FROM_DATA) || DEFAULT_FROM_DATA, [configFilter?.attributeValue, dataSource?.features]);
|
|
7611
|
-
const minDate =
|
|
7612
|
-
const maxDate =
|
|
7613
|
-
const isEmpty =
|
|
7614
|
-
const isDefault =
|
|
7615
|
-
const reset =
|
|
8297
|
+
const minDate = React.useMemo(() => minValue || minFromData.toISOString(), [minFromData, minValue]);
|
|
8298
|
+
const maxDate = React.useMemo(() => maxValue || maxFromData.toISOString(), [maxFromData, maxValue]);
|
|
8299
|
+
const isEmpty = React.useMemo(() => lodash.isNil(value?.[0]) && lodash.isNil(value?.[1]), [value]);
|
|
8300
|
+
const isDefault = React.useMemo(() => value?.[0] === minDate && value?.[1] === maxDate, [maxDate, minDate, value]);
|
|
8301
|
+
const reset = React.useCallback(() => {
|
|
7616
8302
|
setValue([minDate, maxDate]);
|
|
7617
8303
|
changeFilters({
|
|
7618
8304
|
[filterName]: {
|
|
@@ -7622,15 +8308,15 @@ const RangeDateFilter = ({ type, filter }) => {
|
|
|
7622
8308
|
}
|
|
7623
8309
|
}, configFilter?.resetFilters);
|
|
7624
8310
|
}, [changeFilters, configFilter?.resetFilters, filterName, maxDate, minDate]);
|
|
7625
|
-
const onChange =
|
|
8311
|
+
const onChange = React.useCallback((newValue) => {
|
|
7626
8312
|
setValue([newValue[0].toISOString(), newValue[1].toISOString()]);
|
|
7627
8313
|
}, []);
|
|
7628
|
-
|
|
8314
|
+
React.useEffect(() => {
|
|
7629
8315
|
if (!lodash.isNil(minDate) && !lodash.isNil(maxDate)) {
|
|
7630
8316
|
reset();
|
|
7631
8317
|
}
|
|
7632
8318
|
}, []); // eslint-disable-line
|
|
7633
|
-
|
|
8319
|
+
React.useEffect(() => {
|
|
7634
8320
|
if (!isInit.current) {
|
|
7635
8321
|
isInit.current = true;
|
|
7636
8322
|
return;
|
|
@@ -7850,7 +8536,7 @@ const pieChartTooltipFromAttributes = (t, data, attributes) => {
|
|
|
7850
8536
|
const pieChartTooltipFromRelatedFeatures = (t, data, relatedAttributes, layerInfo) => {
|
|
7851
8537
|
if (!data?.length)
|
|
7852
8538
|
return "";
|
|
7853
|
-
return (jsxRuntime.jsx(uilibGl.ThemeProvider, { children: jsxRuntime.jsxs(ChartTooltip, { children: [jsxRuntime.jsx(ChartTooltipColor, { "$color": data[0].color }), jsxRuntime.jsxs("div", { children: [data[0].name, " \u00A0 ", formatChartRelatedValue(t, data[0].value, layerInfo, relatedAttributes)] })] }) }));
|
|
8539
|
+
return (jsxRuntime.jsx(uilibGl.ThemeProvider, { children: jsxRuntime.jsxs(ChartTooltip, { alignItems: "center", children: [jsxRuntime.jsx(ChartTooltipColor, { "$color": data[0].color }), jsxRuntime.jsxs("div", { children: [data[0].name, " \u00A0 ", formatChartRelatedValue(t, data[0].value, layerInfo, relatedAttributes)] })] }) }));
|
|
7854
8540
|
};
|
|
7855
8541
|
|
|
7856
8542
|
const removeDataSource = (dashboardConfiguration, name, pageIndex) => {
|
|
@@ -7908,9 +8594,9 @@ const tooltipValueFromRelatedFeatures = (t, value, relatedAttributes, layerInfo)
|
|
|
7908
8594
|
};
|
|
7909
8595
|
|
|
7910
8596
|
const useWidgetConfig = (type = exports.WidgetType.Dashboard) => {
|
|
7911
|
-
const { config: configProp } =
|
|
8597
|
+
const { config: configProp } = React.useContext(ConfigContext);
|
|
7912
8598
|
const { projectInfo, layerInfo } = useWidgetContext(type);
|
|
7913
|
-
const config =
|
|
8599
|
+
const config = React.useMemo(() => {
|
|
7914
8600
|
if (configProp) {
|
|
7915
8601
|
return configProp;
|
|
7916
8602
|
}
|
|
@@ -7919,7 +8605,7 @@ const useWidgetConfig = (type = exports.WidgetType.Dashboard) => {
|
|
|
7919
8605
|
}
|
|
7920
8606
|
return (layerInfo?.configuration?.cardConfiguration || {});
|
|
7921
8607
|
}, [configProp, layerInfo?.configuration?.cardConfiguration, projectInfo?.content?.dashboardConfiguration, type]);
|
|
7922
|
-
const pages =
|
|
8608
|
+
const pages = React.useMemo(() => (getPagesFromConfig(config) || []), [config]);
|
|
7923
8609
|
return {
|
|
7924
8610
|
config,
|
|
7925
8611
|
pages,
|
|
@@ -7930,10 +8616,11 @@ const useWidgetPage = (type = exports.WidgetType.Dashboard) => {
|
|
|
7930
8616
|
const { t } = useGlobalContext();
|
|
7931
8617
|
const { pageIndex, changePage, projectInfo, updateProject } = useWidgetContext(type);
|
|
7932
8618
|
const { config } = useWidgetConfig(type);
|
|
7933
|
-
const currentPage =
|
|
8619
|
+
const currentPage = React.useMemo(() => {
|
|
7934
8620
|
const page = getPagesFromConfig(config)?.[pageIndex - 1];
|
|
7935
8621
|
return {
|
|
7936
8622
|
...(page || {}),
|
|
8623
|
+
header: page?.header || config.header,
|
|
7937
8624
|
dataSources: [
|
|
7938
8625
|
...(page?.dataSources?.filter(({ name }) => !config.dataSources?.some(item => item.name === name)) || []),
|
|
7939
8626
|
...(config.dataSources || [])
|
|
@@ -7948,7 +8635,7 @@ const useWidgetPage = (type = exports.WidgetType.Dashboard) => {
|
|
|
7948
8635
|
})) || []
|
|
7949
8636
|
};
|
|
7950
8637
|
}, [config, pageIndex]);
|
|
7951
|
-
const updateConfigPage =
|
|
8638
|
+
const updateConfigPage = React.useCallback((newConfig) => {
|
|
7952
8639
|
const newProjectInfo = JSON.parse(JSON.stringify(projectInfo));
|
|
7953
8640
|
const pages = getPagesFromProjectInfo(newProjectInfo);
|
|
7954
8641
|
if (!pages?.[pageIndex - 1])
|
|
@@ -7956,7 +8643,7 @@ const useWidgetPage = (type = exports.WidgetType.Dashboard) => {
|
|
|
7956
8643
|
pages[pageIndex - 1] = { ...pages[pageIndex - 1], ...newConfig };
|
|
7957
8644
|
updateProject(newProjectInfo);
|
|
7958
8645
|
}, [projectInfo, pageIndex, updateProject]);
|
|
7959
|
-
const addConfigPage =
|
|
8646
|
+
const addConfigPage = React.useCallback(() => {
|
|
7960
8647
|
const newProjectInfo = JSON.parse(JSON.stringify(projectInfo));
|
|
7961
8648
|
const pages = getPagesFromProjectInfo(newProjectInfo);
|
|
7962
8649
|
if (!pages)
|
|
@@ -7965,7 +8652,7 @@ const useWidgetPage = (type = exports.WidgetType.Dashboard) => {
|
|
|
7965
8652
|
updateProject(newProjectInfo);
|
|
7966
8653
|
changePage(pages.length);
|
|
7967
8654
|
}, [changePage, projectInfo, t, updateProject]);
|
|
7968
|
-
const deleteConfigPage =
|
|
8655
|
+
const deleteConfigPage = React.useCallback((index) => {
|
|
7969
8656
|
const newProjectInfo = JSON.parse(JSON.stringify(projectInfo));
|
|
7970
8657
|
const pages = getPagesFromProjectInfo(newProjectInfo);
|
|
7971
8658
|
if (!pages?.[index] || pages.length === 1)
|
|
@@ -7983,10 +8670,10 @@ const useChartData = ({ element, type }) => {
|
|
|
7983
8670
|
const { t } = useGlobalContext();
|
|
7984
8671
|
const { dataSources, layerInfos, attributes } = useWidgetContext(type);
|
|
7985
8672
|
const { currentPage } = useWidgetPage(type);
|
|
7986
|
-
const relatedAttributes =
|
|
7987
|
-
const loading =
|
|
8673
|
+
const relatedAttributes = React.useMemo(() => element?.options?.relatedDataSources || [], [element?.options?.relatedDataSources]);
|
|
8674
|
+
const loading = React.useMemo(() => !!relatedAttributes?.length &&
|
|
7988
8675
|
!dataSources?.some(({ name }) => relatedAttributes.some(({ chartAxis, dataSourceName }) => chartAxis === "y" && dataSourceName === name)), [dataSources, relatedAttributes]);
|
|
7989
|
-
const fetchedData =
|
|
8676
|
+
const fetchedData = React.useMemo(() => {
|
|
7990
8677
|
const configDataSources = currentPage?.dataSources || [];
|
|
7991
8678
|
const isRelated = !!relatedAttributes?.length;
|
|
7992
8679
|
const filteredAttributes = relatedAttributes.filter(({ chartAxis }) => chartAxis === "y");
|
|
@@ -8039,8 +8726,8 @@ const useChartData = ({ element, type }) => {
|
|
|
8039
8726
|
layerInfos,
|
|
8040
8727
|
dataSources
|
|
8041
8728
|
]);
|
|
8042
|
-
const [data, setData] =
|
|
8043
|
-
|
|
8729
|
+
const [data, setData] = React.useState(fetchedData);
|
|
8730
|
+
React.useEffect(() => {
|
|
8044
8731
|
if (!loading && fetchedData?.length) {
|
|
8045
8732
|
setData(fetchedData);
|
|
8046
8733
|
}
|
|
@@ -8048,17 +8735,34 @@ const useChartData = ({ element, type }) => {
|
|
|
8048
8735
|
return { data, loading };
|
|
8049
8736
|
};
|
|
8050
8737
|
|
|
8051
|
-
const
|
|
8738
|
+
const useHeaderRender = (elementConfig, type = exports.WidgetType.Dashboard) => {
|
|
8739
|
+
const { layerInfo, attributes, expandedContainers, selectedTabId, setSelectedTabId } = useWidgetContext(type);
|
|
8740
|
+
const { config } = useWidgetConfig(type);
|
|
8741
|
+
const { pageIndex } = useWidgetPage(type);
|
|
8742
|
+
return React.useMemo(() => getRenderElement({
|
|
8743
|
+
config,
|
|
8744
|
+
elementConfig,
|
|
8745
|
+
attributes,
|
|
8746
|
+
layerInfo,
|
|
8747
|
+
expandedContainers,
|
|
8748
|
+
selectedTabId,
|
|
8749
|
+
setSelectedTabId,
|
|
8750
|
+
pageIndex,
|
|
8751
|
+
}), [config, elementConfig, attributes, layerInfo, expandedContainers, selectedTabId, setSelectedTabId, pageIndex]);
|
|
8752
|
+
};
|
|
8753
|
+
|
|
8754
|
+
const useDashboardHeader = () => {
|
|
8052
8755
|
const { themeName } = useGlobalContext();
|
|
8053
8756
|
const { projectInfo } = useWidgetContext();
|
|
8054
8757
|
const { currentPage } = useWidgetPage();
|
|
8055
8758
|
const { alias, name } = projectInfo || {};
|
|
8056
8759
|
const { id: pageId, header } = currentPage || {};
|
|
8057
|
-
const
|
|
8058
|
-
const
|
|
8059
|
-
const
|
|
8060
|
-
const
|
|
8061
|
-
const
|
|
8760
|
+
const renderElement = useHeaderRender(header);
|
|
8761
|
+
const image = React.useMemo(() => (header?.children?.some(({ id }) => id === "image") ? renderElement({ id: "image", wrap: false }) : null), [header?.children, renderElement]);
|
|
8762
|
+
const icon = React.useMemo(() => header?.children?.some(({ id }) => id === "icon") ? (renderElement({ id: "icon", wrap: false })) : (jsxRuntime.jsx(uilibGl.Icon, { kind: "logo", style: { width: "2rem", height: "2rem" } })), [header?.children, renderElement]);
|
|
8763
|
+
const title = React.useMemo(() => header?.children?.some(({ id }) => id === "title") ? renderElement({ id: "title" }) : currentPage?.options?.title, [header?.children, renderElement, currentPage?.options?.title]);
|
|
8764
|
+
const tooltip = React.useMemo(() => (jsxRuntime.jsxs(uilibGl.Flex, { textAlign: "left", children: [jsxRuntime.jsx("div", { children: alias || name }), jsxRuntime.jsx(uilibGl.Flex, { opacity: 0.54, children: title })] })), [alias, name, title]);
|
|
8765
|
+
const description = React.useMemo(() => (header?.children?.some(({ id }) => id === "description") ? renderElement({ id: "description" }) : ""), [header?.children, renderElement]);
|
|
8062
8766
|
return {
|
|
8063
8767
|
pageId,
|
|
8064
8768
|
image,
|
|
@@ -8067,6 +8771,7 @@ const useDashboardHeader = (renderElement) => {
|
|
|
8067
8771
|
tooltip,
|
|
8068
8772
|
description,
|
|
8069
8773
|
themeName,
|
|
8774
|
+
renderElement,
|
|
8070
8775
|
};
|
|
8071
8776
|
};
|
|
8072
8777
|
|
|
@@ -8076,8 +8781,8 @@ const useDataSources = ({ type: widgetType, config, attributes, filters, layerPa
|
|
|
8076
8781
|
const { ewktGeometry, api } = useGlobalContext();
|
|
8077
8782
|
const { dataSources } = useWidgetContext(widgetType);
|
|
8078
8783
|
const { filters: configFilters, dataSources: configDataSources } = config || {};
|
|
8079
|
-
const prevFilters =
|
|
8080
|
-
const getDataSourcePromises =
|
|
8784
|
+
const prevFilters = React.useRef({});
|
|
8785
|
+
const getDataSourcePromises = React.useCallback(async ({ ds, query, parameters, layerName, limit, condition, url, resourceId, type }, newFilters, offset = 0) => {
|
|
8081
8786
|
const selectedFilters = {
|
|
8082
8787
|
...(filters || {}),
|
|
8083
8788
|
...(newFilters || {}),
|
|
@@ -8139,7 +8844,7 @@ const useDataSources = ({ type: widgetType, config, attributes, filters, layerPa
|
|
|
8139
8844
|
: [condition, query].filter(Boolean),
|
|
8140
8845
|
});
|
|
8141
8846
|
}, [filters, dataSources, configFilters, ewktGeometry, attributes, layerParams, eqlParameters]);
|
|
8142
|
-
const getUpdatingDataSources =
|
|
8847
|
+
const getUpdatingDataSources = React.useCallback(() => {
|
|
8143
8848
|
const diffFilterNames = filters
|
|
8144
8849
|
? Object.keys(filters).filter(key => Array.isArray(filters[key].value)
|
|
8145
8850
|
? filters[key].value.length !== prevFilters.current[key]?.value?.length ||
|
|
@@ -8156,7 +8861,7 @@ const useDataSources = ({ type: widgetType, config, attributes, filters, layerPa
|
|
|
8156
8861
|
prevFilters.current = JSON.parse(JSON.stringify(filters));
|
|
8157
8862
|
return filteredDataSources;
|
|
8158
8863
|
}, [configDataSources, filters]);
|
|
8159
|
-
const getUpdatedDataSources =
|
|
8864
|
+
const getUpdatedDataSources = React.useCallback((responses, currentDataSources, otherDataSources) => {
|
|
8160
8865
|
const newDataSources = JSON.parse(JSON.stringify([...currentDataSources, ...otherDataSources]));
|
|
8161
8866
|
responses.forEach((response, index) => {
|
|
8162
8867
|
const isQueryDataSource = !lodash.isNil(currentDataSources[index].query) ||
|
|
@@ -8179,7 +8884,7 @@ const useDataSources = ({ type: widgetType, config, attributes, filters, layerPa
|
|
|
8179
8884
|
});
|
|
8180
8885
|
return newDataSources;
|
|
8181
8886
|
}, []);
|
|
8182
|
-
const zoomToLayersExtent =
|
|
8887
|
+
const zoomToLayersExtent = React.useCallback(async (layers) => {
|
|
8183
8888
|
const newExtent = await api.layers.getBulkExtents({ srId: 4326 }, layers?.map(({ layerName, conditions, parameters }) => ({
|
|
8184
8889
|
layerName,
|
|
8185
8890
|
conditions,
|
|
@@ -8210,17 +8915,17 @@ const useDataSources = ({ type: widgetType, config, attributes, filters, layerPa
|
|
|
8210
8915
|
|
|
8211
8916
|
const useDiffPage = (type) => {
|
|
8212
8917
|
const { pageIndex } = useWidgetContext(type);
|
|
8213
|
-
const prevPageIndex =
|
|
8918
|
+
const prevPageIndex = React.useRef(pageIndex);
|
|
8214
8919
|
const isDiffPage = prevPageIndex.current !== pageIndex;
|
|
8215
|
-
|
|
8920
|
+
React.useEffect(() => {
|
|
8216
8921
|
prevPageIndex.current = pageIndex;
|
|
8217
8922
|
}, [pageIndex]);
|
|
8218
|
-
return
|
|
8923
|
+
return React.useMemo(() => isDiffPage, [isDiffPage]);
|
|
8219
8924
|
};
|
|
8220
8925
|
|
|
8221
8926
|
const useExpandableContainers = () => {
|
|
8222
|
-
const [expandedContainers, setExpandedContainers] =
|
|
8223
|
-
const expandContainer =
|
|
8927
|
+
const [expandedContainers, setExpandedContainers] = React.useState({});
|
|
8928
|
+
const expandContainer = React.useCallback((id, expanded) => {
|
|
8224
8929
|
setExpandedContainers(state => ({
|
|
8225
8930
|
...state,
|
|
8226
8931
|
[id]: state?.[id] === undefined && expanded !== undefined ? !expanded : !state?.[id],
|
|
@@ -8244,11 +8949,11 @@ const useFeatureFilters = (type, filterName, items) => {
|
|
|
8244
8949
|
const theme = styled.useTheme();
|
|
8245
8950
|
const { filters, changeFilters } = useWidgetContext(type);
|
|
8246
8951
|
const { currentPage } = useWidgetPage(type);
|
|
8247
|
-
const configFilter =
|
|
8952
|
+
const configFilter = React.useMemo(() => getConfigFilter(filterName, currentPage.filters), [currentPage.filters, filterName]);
|
|
8248
8953
|
const hasAnyFilter = Array.isArray(filters?.[filterName]?.value)
|
|
8249
8954
|
? !!filters[filterName].value.length
|
|
8250
8955
|
: !!filters?.[filterName]?.value;
|
|
8251
|
-
const isFiltered =
|
|
8956
|
+
const isFiltered = React.useCallback((name) => {
|
|
8252
8957
|
const filterValue = filters[filterName]?.value || configFilter?.defaultValue;
|
|
8253
8958
|
if (!Array.isArray(filterValue)) {
|
|
8254
8959
|
return filterValue === name;
|
|
@@ -8258,7 +8963,7 @@ const useFeatureFilters = (type, filterName, items) => {
|
|
|
8258
8963
|
? filterValue.includes(name)
|
|
8259
8964
|
: filterValue?.[0] <= name && filterValue?.[1] >= name));
|
|
8260
8965
|
}, [configFilter?.defaultValue, configFilter?.valueType, filterName, filters]);
|
|
8261
|
-
const formatFilterColor =
|
|
8966
|
+
const formatFilterColor = React.useCallback((name, color, defaultColor = FEATURE_CARD_OTHER_COLOR) => {
|
|
8262
8967
|
return isFiltered(name)
|
|
8263
8968
|
? color || theme.palette.primary
|
|
8264
8969
|
: hasAnyFilter
|
|
@@ -8267,7 +8972,7 @@ const useFeatureFilters = (type, filterName, items) => {
|
|
|
8267
8972
|
: defaultColor
|
|
8268
8973
|
: color || theme.palette.primary;
|
|
8269
8974
|
}, [hasAnyFilter, isFiltered, theme.palette.primary]);
|
|
8270
|
-
const onFilter =
|
|
8975
|
+
const onFilter = React.useCallback((newValue) => {
|
|
8271
8976
|
const value = getFilterValue({
|
|
8272
8977
|
selectedFilters: filters,
|
|
8273
8978
|
configFilters: currentPage.filters,
|
|
@@ -8313,12 +9018,12 @@ const useFeatureFilters = (type, filterName, items) => {
|
|
|
8313
9018
|
|
|
8314
9019
|
const useGetConfigLayer = () => {
|
|
8315
9020
|
const { currentPage } = useWidgetPage();
|
|
8316
|
-
return
|
|
9021
|
+
return React.useCallback((layerName) => currentPage?.layers?.find(({ name }) => name === layerName), [currentPage?.layers]);
|
|
8317
9022
|
};
|
|
8318
9023
|
|
|
8319
9024
|
const useProjectDashboardInit = () => {
|
|
8320
9025
|
const { projectInfo, updateProject } = useWidgetContext();
|
|
8321
|
-
return
|
|
9026
|
+
return React.useCallback(() => {
|
|
8322
9027
|
if (!lodash.isEmpty(projectInfo?.content?.dashboardConfiguration) || !projectInfo?.content?.items?.length) {
|
|
8323
9028
|
return;
|
|
8324
9029
|
}
|
|
@@ -8335,10 +9040,10 @@ const useRelatedDataSourceAttributes = ({ type = exports.WidgetType.Dashboard, e
|
|
|
8335
9040
|
const { currentPage } = useWidgetPage(type);
|
|
8336
9041
|
const { options } = elementConfig || {};
|
|
8337
9042
|
const { relatedDataSource } = options || {};
|
|
8338
|
-
const dataSource =
|
|
8339
|
-
const layerInfo =
|
|
9043
|
+
const dataSource = React.useMemo(() => getDataSource(relatedDataSource, dataSources), [dataSources, relatedDataSource]);
|
|
9044
|
+
const layerInfo = React.useMemo(() => getLayerInfoFromDataSources(layerInfos, currentPage?.dataSources, relatedDataSource) ||
|
|
8340
9045
|
{ layerDefinition: { attributes: dataSource?.attributeDefinition || {} } }, [currentPage?.dataSources, dataSource?.attributeDefinition, layerInfos, relatedDataSource]);
|
|
8341
|
-
const attributes =
|
|
9046
|
+
const attributes = React.useMemo(() => getFeatureAttributes(feature, layerInfo, dataSource), [dataSource, feature, layerInfo]);
|
|
8342
9047
|
return { layerInfo, attributes, dataSource };
|
|
8343
9048
|
};
|
|
8344
9049
|
|
|
@@ -8347,7 +9052,7 @@ const useRenderElement = (type = exports.WidgetType.Dashboard, elementConfig) =>
|
|
|
8347
9052
|
const { selectedTabId, setSelectedTabId, expandedContainers, layerInfo, attributes } = useWidgetContext(type);
|
|
8348
9053
|
const { config } = useWidgetConfig(type);
|
|
8349
9054
|
const { pageIndex } = useWidgetPage(type);
|
|
8350
|
-
return
|
|
9055
|
+
return React.useMemo(() => getRenderElement({
|
|
8351
9056
|
t,
|
|
8352
9057
|
type,
|
|
8353
9058
|
config,
|
|
@@ -8392,7 +9097,7 @@ const useUpdateDataSource = ({ dataSource, config, filters, attributes, layerPar
|
|
|
8392
9097
|
layerParams,
|
|
8393
9098
|
eqlParameters,
|
|
8394
9099
|
});
|
|
8395
|
-
return
|
|
9100
|
+
return React.useCallback(async (newFilters, offset = 0) => {
|
|
8396
9101
|
return getDataSourcePromises(dataSource, newFilters, offset).then((response) => {
|
|
8397
9102
|
const responseDataSources = getUpdatedDataSources([response], [dataSource], dataSources);
|
|
8398
9103
|
return {
|
|
@@ -8411,17 +9116,17 @@ const StackBar = ({ data, filterName, type, alias, options, renderElement, rende
|
|
|
8411
9116
|
const { items, layerInfo, attributeName } = data?.[0] || {};
|
|
8412
9117
|
const attribute = layerInfo?.layerDefinition.attributes[attributeName];
|
|
8413
9118
|
const units = attribute?.stringFormat?.unitsLabel;
|
|
8414
|
-
const total =
|
|
8415
|
-
const getWidth =
|
|
8416
|
-
const renderGroupTooltip =
|
|
8417
|
-
const renderItem =
|
|
8418
|
-
const renderItems =
|
|
9119
|
+
const total = React.useMemo(() => items?.reduce((result, { value }) => result + Number(value), 0) || 0, [items]);
|
|
9120
|
+
const getWidth = React.useCallback(value => ((Number(value) / total) * 100).toFixed(2), [total]);
|
|
9121
|
+
const renderGroupTooltip = React.useMemo(() => (jsxRuntime.jsx(uilibGl.ThemeProvider, { children: jsxRuntime.jsx(ChartTooltipTable, { cellPadding: 0, cellSpacing: 0, children: items?.map(({ name, value, color }, index) => (jsxRuntime.jsxs("tr", { children: [jsxRuntime.jsx("td", { children: jsxRuntime.jsxs(ChartTooltip, { alignItems: "center", children: [jsxRuntime.jsx(ChartTooltipColor, { "$color": color }), jsxRuntime.jsx(ChartTooltipName, { children: name })] }) }), jsxRuntime.jsx("td", { children: value })] }, index))) }) })), [items]);
|
|
9122
|
+
const renderItem = React.useCallback(({ name, value, color }, ref) => (jsxRuntime.jsx(StackBarSection, { ref: ref, "$width": getWidth(value), "$height": height, "$color": color, cornerRadius: cornerRadius, hasAnyFilter: hasAnyFilter, isFiltered: isFiltered(name), onClick: filterName ? () => onFilter(name) : undefined })), [cornerRadius, filterName, getWidth, hasAnyFilter, height, isFiltered, onFilter]);
|
|
9123
|
+
const renderItems = React.useMemo(() => (jsxRuntime.jsx(jsxRuntime.Fragment, { children: items?.map((item, index) => (jsxRuntime.jsx(React.Fragment, { children: groupTooltip ? (renderItem(item)) : (jsxRuntime.jsx(uilibGl.ThemeProvider, { children: jsxRuntime.jsx(uilibGl.Tooltip, { placement: "top", arrow: true, content: renderTooltip([item]), children: ref => renderItem(item, ref) }) })) }, index))) })), [groupTooltip, items, renderItem, renderTooltip]);
|
|
8419
9124
|
if (!total || !attribute)
|
|
8420
9125
|
return null;
|
|
8421
9126
|
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [(alias || showTotal) && (jsxRuntime.jsxs(StackBarHeader, { children: [jsxRuntime.jsx(StackBarAlias, { children: renderElement({ id: "alias" }) }), showTotal && (jsxRuntime.jsxs(StackBarTotal, { children: [jsxRuntime.jsx(StackBarValue, { children: formatAttributeValue({ t, type: attribute.type, value: total, stringFormat: attribute.stringFormat, noUnits: true }) }), !!units && jsxRuntime.jsx(StackBarUnits, { children: units })] }))] })), groupTooltip ? (jsxRuntime.jsx(uilibGl.Tooltip, { placement: "top", arrow: true, content: renderGroupTooltip, children: ref => jsxRuntime.jsx(StackBarContainer, { ref: ref, children: renderItems }) })) : (jsxRuntime.jsx(StackBarContainer, { children: renderItems }))] }));
|
|
8422
9127
|
};
|
|
8423
9128
|
|
|
8424
|
-
const Chart =
|
|
9129
|
+
const Chart = React.memo(({ config, element, elementConfig, type, renderElement }) => {
|
|
8425
9130
|
const theme = styled.useTheme();
|
|
8426
9131
|
const { palette } = theme;
|
|
8427
9132
|
const { t } = useGlobalContext();
|
|
@@ -8440,22 +9145,17 @@ const Chart = react.memo(({ config, element, elementConfig, type, renderElement
|
|
|
8440
9145
|
const barWidth = options?.barWidth || DEFAULT_BAR_WIDTH;
|
|
8441
9146
|
const cornerRadius = options?.cornerRadius || 0;
|
|
8442
9147
|
const primaryColor = theme.palette.primary;
|
|
8443
|
-
const relatedAttributes =
|
|
8444
|
-
const axes =
|
|
9148
|
+
const relatedAttributes = React.useMemo(() => relatedDataSources || [], [relatedDataSources]);
|
|
9149
|
+
const axes = React.useMemo(() => relatedAttributes.filter(({ chartAxis }) => chartAxis === "y"), [relatedAttributes]);
|
|
8445
9150
|
const filterName = getChartFilterName(relatedDataSources);
|
|
8446
9151
|
const isRelated = !!relatedAttributes?.length;
|
|
8447
9152
|
const { data, loading } = useChartData({ element, type });
|
|
8448
9153
|
const totalWidthFromBarWidth = (data[0]?.items?.length || 0) * (barWidth + padding);
|
|
8449
|
-
const width = options?.width
|
|
8450
|
-
|
|
8451
|
-
? MAX_CHART_WIDTH
|
|
8452
|
-
: options.width
|
|
8453
|
-
: isStackBar
|
|
9154
|
+
const width = options?.width ? options.width :
|
|
9155
|
+
isStackBar
|
|
8454
9156
|
? "100%"
|
|
8455
9157
|
: isBarChart
|
|
8456
|
-
? totalWidthFromBarWidth
|
|
8457
|
-
? MAX_CHART_WIDTH
|
|
8458
|
-
: totalWidthFromBarWidth
|
|
9158
|
+
? totalWidthFromBarWidth || MAX_CHART_WIDTH
|
|
8459
9159
|
: DEFAULT_CHART_WIDTH;
|
|
8460
9160
|
const [customize] = useChartChange({
|
|
8461
9161
|
dataSources: config.dataSources,
|
|
@@ -8467,37 +9167,37 @@ const Chart = react.memo(({ config, element, elementConfig, type, renderElement
|
|
|
8467
9167
|
defaultColor: primaryColor
|
|
8468
9168
|
});
|
|
8469
9169
|
const { formatFilterColor, onFilter } = useFeatureFilters(type, filterName, data?.[0]?.items);
|
|
8470
|
-
const formattedAttributes =
|
|
8471
|
-
const totalSum =
|
|
9170
|
+
const formattedAttributes = React.useMemo(() => getFormattedAttributes(t, (data[0]?.items || []), attributes, element), [attributes, data, element, t]);
|
|
9171
|
+
const totalSum = React.useMemo(() => isRelated
|
|
8472
9172
|
? getTotalFromRelatedFeatures((data[0]?.items || []))
|
|
8473
9173
|
: getTotalFromAttributes(children, formattedAttributes), [data, children, formattedAttributes, isRelated]);
|
|
8474
|
-
const totalWord =
|
|
9174
|
+
const totalWord = React.useMemo(() => options?.totalAttribute
|
|
8475
9175
|
? attributes?.find(({ name }) => name === options.totalAttribute)?.value
|
|
8476
9176
|
: options?.totalWord, [attributes, options.totalAttribute, options?.totalWord]);
|
|
8477
|
-
const renderPieChartTooltip =
|
|
9177
|
+
const renderPieChartTooltip = React.useCallback(item => isRelated
|
|
8478
9178
|
? pieChartTooltipFromRelatedFeatures(t, item, relatedAttributes, data[0]?.layerInfo)
|
|
8479
9179
|
: pieChartTooltipFromAttributes(t, item, formattedAttributes), [data, formattedAttributes, isRelated, relatedAttributes]);
|
|
8480
|
-
const labels =
|
|
9180
|
+
const labels = React.useMemo(() => {
|
|
8481
9181
|
if (!isLineChart)
|
|
8482
9182
|
return [];
|
|
8483
9183
|
const result = data?.map(item => item?.items?.map(({ name }) => name?.toString()))?.flat();
|
|
8484
9184
|
return result?.filter((name, index) => result.indexOf(name) === index);
|
|
8485
9185
|
}, [data, isLineChart]);
|
|
8486
|
-
const renderLineChartTooltip =
|
|
8487
|
-
return (jsxRuntime.
|
|
8488
|
-
|
|
8489
|
-
|
|
8490
|
-
|
|
8491
|
-
|
|
8492
|
-
|
|
8493
|
-
|
|
9186
|
+
const renderLineChartTooltip = React.useCallback((items, { indexX }) => {
|
|
9187
|
+
return (jsxRuntime.jsxs(Tooltip, { children: [jsxRuntime.jsx(ChartTooltipLabel, { children: labels[indexX] }), items
|
|
9188
|
+
.filter(({ value }) => !isEmptyValue(value))
|
|
9189
|
+
?.map(({ layerName, attributeName, value, stroke }, index) => {
|
|
9190
|
+
const layerInfo = layerInfos?.find(({ name }) => name === layerName);
|
|
9191
|
+
const attribute = layerInfo?.layerDefinition.attributes[attributeName];
|
|
9192
|
+
return (jsxRuntime.jsxs(ChartTooltipRow, { children: [jsxRuntime.jsx(ChartLegendColor$1, { "$color": stroke }), jsxRuntime.jsx(ChartLegendValue, { children: attribute ? formatAttributeValue({ t, type: attribute.type, value, stringFormat: attribute.stringFormat }) : value })] }, index));
|
|
9193
|
+
})] }));
|
|
8494
9194
|
}, [labels, layerInfos]);
|
|
8495
|
-
const markers =
|
|
8496
|
-
const formatTooltipName =
|
|
8497
|
-
const formatTooltipValue =
|
|
9195
|
+
const markers = React.useMemo(() => getChartMarkers(data[0]?.items, configMarkers), [data, configMarkers]);
|
|
9196
|
+
const formatTooltipName = React.useCallback((name) => (isRelated ? name : tooltipNameFromAttributes(name, formattedAttributes)), [formattedAttributes, isRelated]);
|
|
9197
|
+
const formatTooltipValue = React.useCallback((value, name) => isRelated
|
|
8498
9198
|
? tooltipValueFromRelatedFeatures(t, value, relatedAttributes, data[0]?.layerInfo)
|
|
8499
9199
|
: tooltipValueFromAttributes(t, value, name, formattedAttributes), [data, formattedAttributes, isRelated, relatedAttributes]);
|
|
8500
|
-
const renderChart =
|
|
9200
|
+
const renderChart = React.useMemo(() => {
|
|
8501
9201
|
if (!element)
|
|
8502
9202
|
return null;
|
|
8503
9203
|
if (isLineChart) {
|
|
@@ -8514,16 +9214,16 @@ const Chart = react.memo(({ config, element, elementConfig, type, renderElement
|
|
|
8514
9214
|
.flat()
|
|
8515
9215
|
.map(({ values }) => values)
|
|
8516
9216
|
.flat();
|
|
8517
|
-
return (jsxRuntime.
|
|
8518
|
-
|
|
8519
|
-
|
|
8520
|
-
|
|
8521
|
-
|
|
8522
|
-
|
|
8523
|
-
|
|
8524
|
-
|
|
8525
|
-
|
|
8526
|
-
|
|
9217
|
+
return (jsxRuntime.jsxs(AnyChartWrapper, { height: height, children: [jsxRuntime.jsx(LineChartTooltipStyles, {}), jsxRuntime.jsx(charts.LineChart, { data: lineChartData, labels: labels, width: +width, height: height, xAxisPadding: 15, yAxisPadding: 0, min: Math.min(...chartValues), customYAxisSelection: yAxis => {
|
|
9218
|
+
if (isHidedY) {
|
|
9219
|
+
yAxis.remove();
|
|
9220
|
+
}
|
|
9221
|
+
}, customYAxis: yAxis => yAxis.ticks(4), renderTooltip: renderLineChartTooltip, customize: customize, dynamicTooltipEnable: true, stackedTooltip: true, tooltipClassName: "dashboardLineChartTooltip", drawGridX: !isHidedY, margin: {
|
|
9222
|
+
top: 0,
|
|
9223
|
+
right: 0,
|
|
9224
|
+
bottom: 0,
|
|
9225
|
+
left: 0
|
|
9226
|
+
} })] }));
|
|
8527
9227
|
}
|
|
8528
9228
|
if (isStackBar) {
|
|
8529
9229
|
return (jsxRuntime.jsx(AnyChartWrapper, { height: height, children: jsxRuntime.jsx(StackBar, { data: data, filterName: filterName, type: type, alias: elementConfig?.children?.find(child => child.id === "alias"), options: options, renderTooltip: renderPieChartTooltip, renderElement: renderElement }) }));
|
|
@@ -8536,16 +9236,17 @@ const Chart = react.memo(({ config, element, elementConfig, type, renderElement
|
|
|
8536
9236
|
color: formatFilterColor(item.name, item.color, defaultColor)
|
|
8537
9237
|
})) || []), width: +width, height: +width, padAngle: angle, outerRadius: radius, cornerRadius: cornerRadius, renderTooltip: renderPieChartTooltip, withTooltip: true, onClick: filterName ? item => onFilter(item.name) : undefined, children: showTotal && jsxRuntime.jsx(PieChartCenter, { children: totalWord || roundTotalSum(+totalSum) }) }) }));
|
|
8538
9238
|
}
|
|
9239
|
+
const markersMargin = options?.showMarkers ? 10 : 0;
|
|
8539
9240
|
const margin = {
|
|
8540
|
-
top:
|
|
8541
|
-
right:
|
|
8542
|
-
bottom: markers?.length ? 20 :
|
|
8543
|
-
left:
|
|
9241
|
+
top: markersMargin,
|
|
9242
|
+
right: markersMargin,
|
|
9243
|
+
bottom: markers?.length ? 20 : markersMargin,
|
|
9244
|
+
left: markersMargin
|
|
8544
9245
|
};
|
|
8545
|
-
return (jsxRuntime.jsx(BarChartWrapper, { height: height + margin.bottom, children: jsxRuntime.
|
|
8546
|
-
|
|
8547
|
-
|
|
8548
|
-
|
|
9246
|
+
return (jsxRuntime.jsx(BarChartWrapper, { height: height + margin.bottom, children: jsxRuntime.jsxs(BarChartContainer, { children: [jsxRuntime.jsx(BarChartStyles, {}), jsxRuntime.jsx(charts.BarChart, { data: getDataFromFilterItems(data[0]?.items), colors: getColorsFromFilterItems(data[0]?.items, defaultColor, formatFilterColor), minValue: getMinValueFromFilterItems(data[0]?.items), markers: markers, width: +width, height: height, barWidth: barWidth, barPadding: padding, className: "dashboardBarChart", customXAxis: axis => axis.remove(), customYAxis: axis => !options?.showMarkers && axis.remove(), customBars: ({ bars }) => {
|
|
9247
|
+
bars.attr("rx", radius);
|
|
9248
|
+
bars.attr("ry", radius);
|
|
9249
|
+
}, margin: margin, xAxisPadding: 0, yAxisPadding: 0, formatTooltipValue: formatTooltipValue, formatTooltipName: formatTooltipName, hideTooltipGroupName: true, dynamicTooltipEnable: true, isBarTooltip: true, onBarClick: filterName ? item => onFilter(item.name) : undefined })] }) }));
|
|
8549
9250
|
}, [
|
|
8550
9251
|
element,
|
|
8551
9252
|
isLineChart,
|
|
@@ -8588,16 +9289,16 @@ const Chart = react.memo(({ config, element, elementConfig, type, renderElement
|
|
|
8588
9289
|
const ChartLegend = ({ data, chartElement, type, twoColumns, loading }) => {
|
|
8589
9290
|
const { t } = useGlobalContext();
|
|
8590
9291
|
const { sliceItems, showMore, onShowMore } = useShownOtherItems(chartElement?.options);
|
|
8591
|
-
const axes =
|
|
9292
|
+
const axes = React.useMemo(() => chartElement?.options?.relatedDataSources?.filter(({ chartAxis }) => chartAxis === "y"), [chartElement?.options?.relatedDataSources]);
|
|
8592
9293
|
const { isFiltered, hasAnyFilter, onFilter } = useFeatureFilters(type, axes?.[0]?.filterName);
|
|
8593
9294
|
const { fontColor, shownItems, hideEmpty } = chartElement?.options || {};
|
|
8594
9295
|
const showMoreBtn = !!shownItems && data.length > shownItems;
|
|
8595
9296
|
if (!loading && !data?.length && !!hideEmpty)
|
|
8596
9297
|
return null;
|
|
8597
|
-
return (jsxRuntime.jsxs(uilibGl.Flex, { opacity: loading ? FILTERED_VALUE_OPACITY / 100 : 1, children: [jsxRuntime.jsx(ChartLegendContainer, { twoColumns: twoColumns, children: sliceItems(data)?.map(({ name, color }, index) => (jsxRuntime.jsxs(ChartLegendItem, { hasAnyFilter: hasAnyFilter, isFiltered: isFiltered(name), onClick: axes?.[0]?.filterName ? () => onFilter(name) : undefined, children: [jsxRuntime.jsx(ChartLegendColor, { color: color }), jsxRuntime.jsx(ChartLegendName, { "$fontColor": fontColor, children: name })] }, index))) }), showMoreBtn && (jsxRuntime.jsx(uilibGl.LegendToggler, { onClick: onShowMore, toggled: showMore, children: t("other", { ns: "dashboard" }) }))] }));
|
|
9298
|
+
return (jsxRuntime.jsxs(uilibGl.Flex, { flexDirection: "column", opacity: loading ? FILTERED_VALUE_OPACITY / 100 : 1, children: [jsxRuntime.jsx(ChartLegendContainer, { twoColumns: twoColumns, children: sliceItems(data)?.map(({ name, color }, index) => (jsxRuntime.jsxs(ChartLegendItem, { hasAnyFilter: hasAnyFilter, isFiltered: isFiltered(name), onClick: axes?.[0]?.filterName ? () => onFilter(name) : undefined, children: [jsxRuntime.jsx(ChartLegendColor, { color: color }), jsxRuntime.jsx(ChartLegendName, { "$fontColor": fontColor, children: name })] }, index))) }), showMoreBtn && (jsxRuntime.jsx(uilibGl.LegendToggler, { onClick: onShowMore, toggled: showMore, children: t("other", { ns: "dashboard" }) }))] }));
|
|
8598
9299
|
};
|
|
8599
9300
|
|
|
8600
|
-
const ContainerChildren =
|
|
9301
|
+
const ContainerChildren = React.memo(({ items, isColumn, isMain, renderElement }) => {
|
|
8601
9302
|
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: items
|
|
8602
9303
|
?.filter(item => !["title", "icon", "titleIcon"].includes(item.id))
|
|
8603
9304
|
?.map((item, index) => {
|
|
@@ -8606,19 +9307,19 @@ const ContainerChildren = react.memo(({ items, isColumn, isMain, renderElement }
|
|
|
8606
9307
|
index,
|
|
8607
9308
|
wrap: isColumn || isMain,
|
|
8608
9309
|
});
|
|
8609
|
-
return isMain ? (jsxRuntime.jsx(ContainerWrapper, { "data-id": item.id, "data-templatename": item.templateName, children: jsxRuntime.jsx(DashboardWrapper, { children: render }) }, index)) : (jsxRuntime.jsx(
|
|
9310
|
+
return isMain ? (jsxRuntime.jsx(ContainerWrapper, { "data-id": item.id, "data-templatename": item.templateName, children: jsxRuntime.jsx(DashboardWrapper, { children: render }) }, index)) : (jsxRuntime.jsx(React.Fragment, { children: render }, index));
|
|
8610
9311
|
}) }));
|
|
8611
9312
|
});
|
|
8612
9313
|
|
|
8613
|
-
const DashboardLoading =
|
|
9314
|
+
const DashboardLoading = React.memo(() => {
|
|
8614
9315
|
return (jsxRuntime.jsx(ContainerWrapper, { children: jsxRuntime.jsx(DashboardWrapper, { children: jsxRuntime.jsx(DashboardPlaceholderWrap, { children: jsxRuntime.jsxs(DashboardPlaceholder, { isLoading: true, children: [jsxRuntime.jsx(uilibGl.Icon, { kind: "dashboard_loading" }), jsxRuntime.jsx(uilibGl.Flex, { width: "8rem", children: jsxRuntime.jsx(uilibGl.LinearProgress, {}) })] }) }) }) }));
|
|
8615
9316
|
});
|
|
8616
9317
|
|
|
8617
|
-
const Dashboard =
|
|
9318
|
+
const Dashboard = React.memo(({ type = exports.WidgetType.Dashboard, config }) => {
|
|
8618
9319
|
const { dataSources, isLoading } = useWidgetContext(type);
|
|
8619
9320
|
const { currentPage } = useWidgetPage();
|
|
8620
9321
|
const isDiffPage = useDiffPage(type);
|
|
8621
|
-
const dataSourceLoading =
|
|
9322
|
+
const dataSourceLoading = React.useMemo(() => currentPage?.dataSources?.length && !dataSources?.length && isLoading, [currentPage?.dataSources?.length, dataSources?.length, isLoading]);
|
|
8622
9323
|
if (dataSourceLoading || isDiffPage) {
|
|
8623
9324
|
return (jsxRuntime.jsx(DashboardLoading, {}));
|
|
8624
9325
|
}
|
|
@@ -8635,12 +9336,18 @@ const DashboardCheckbox = ({ title, checked, onChange, }) => {
|
|
|
8635
9336
|
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(AttributeLabel, { isEdit: !!onChange, forCheckbox: !!onChange, children: title }), onChange ? jsxRuntime.jsx(CardCheckbox, { checked: checked, label: label, onChange: onChange }) : label] }));
|
|
8636
9337
|
};
|
|
8637
9338
|
|
|
9339
|
+
const DashboardHeader = React.memo(() => {
|
|
9340
|
+
const { currentPage } = useWidgetPage();
|
|
9341
|
+
const HeaderTemplate = React.useMemo(() => getDashboardHeader(currentPage?.header?.templateName), [currentPage?.header?.templateName]);
|
|
9342
|
+
return jsxRuntime.jsx(HeaderTemplate, {});
|
|
9343
|
+
});
|
|
9344
|
+
|
|
8638
9345
|
const DataSourceError = ({ name }) => {
|
|
8639
9346
|
const { t } = useGlobalContext();
|
|
8640
9347
|
return (jsxRuntime.jsxs(DataSourceErrorContainer, { children: [jsxRuntime.jsx(uilibGl.Icon, { kind: "alert" }), jsxRuntime.jsxs("div", { children: [t("block", { ns: "dashboard" }), " \"", name, "\" ", t("isNotLoaded", { ns: "dashboard" })] })] }));
|
|
8641
9348
|
};
|
|
8642
9349
|
|
|
8643
|
-
const ExpandableTitle =
|
|
9350
|
+
const ExpandableTitle = React.memo(({ elementConfig, type, renderElement }) => {
|
|
8644
9351
|
const { expandedContainers } = useWidgetContext(type);
|
|
8645
9352
|
const { id, options, templateName, children } = elementConfig || {};
|
|
8646
9353
|
const { expandable, fontColor, expanded, layerNames } = options || {};
|
|
@@ -8651,6 +9358,50 @@ const ExpandableTitle = react.memo(({ elementConfig, type, renderElement }) => {
|
|
|
8651
9358
|
return (jsxRuntime.jsx(TitleContainer, { containerId: id, elementConfig: titleElement, templateName: templateName, layerNames: layerNames, fontColor: fontColor, expandable: expandable, expanded: expanded, type: type, isVisible: isVisible, renderElement: renderElement }));
|
|
8652
9359
|
});
|
|
8653
9360
|
|
|
9361
|
+
const FeatureCardButtons = () => {
|
|
9362
|
+
const { closeFeatureCard } = useWidgetContext(exports.WidgetType.FeatureCard);
|
|
9363
|
+
return (jsxRuntime.jsx(uilibGl.FlexSpan, { children: jsxRuntime.jsx(uilibGl.IconButton, { kind: "close", style: {
|
|
9364
|
+
padding: 0,
|
|
9365
|
+
width: "1rem",
|
|
9366
|
+
}, onClick: closeFeatureCard }) }));
|
|
9367
|
+
};
|
|
9368
|
+
|
|
9369
|
+
const FeatureCardHeader = () => {
|
|
9370
|
+
const { currentPage } = useWidgetPage(exports.WidgetType.FeatureCard);
|
|
9371
|
+
const HeaderTemplate = getFeatureCardHeader(currentPage?.header?.templateName);
|
|
9372
|
+
return jsxRuntime.jsx(HeaderTemplate, {});
|
|
9373
|
+
};
|
|
9374
|
+
|
|
9375
|
+
const FeatureCardTitle = ({ title, description }) => {
|
|
9376
|
+
const { t } = useGlobalContext();
|
|
9377
|
+
const { attributes, layerInfo, feature } = useWidgetContext(exports.WidgetType.FeatureCard);
|
|
9378
|
+
const zoomToFeatures = useZoomToFeatures();
|
|
9379
|
+
const { alias, name, layerDefinition, titleAttribute } = layerInfo || {};
|
|
9380
|
+
const resultDescription = description || alias || name || "";
|
|
9381
|
+
const resultTitle = React.useMemo(() => {
|
|
9382
|
+
const layerDefinitionAttribute = layerDefinition && attributes?.length
|
|
9383
|
+
? attributes.find(item => item.name === layerDefinition.titleAttribute)
|
|
9384
|
+
: null;
|
|
9385
|
+
const layerDefinitionTitle = layerDefinition?.titleAttribute && layerDefinitionAttribute?.value
|
|
9386
|
+
? layerDefinitionAttribute.value
|
|
9387
|
+
: null;
|
|
9388
|
+
const sourceTitleAttribute = titleAttribute && attributes?.length ? attributes.find(item => item.name === titleAttribute) : null;
|
|
9389
|
+
const sourceTitle = titleAttribute && sourceTitleAttribute?.value ? sourceTitleAttribute.value : null;
|
|
9390
|
+
return (title ||
|
|
9391
|
+
(!!sourceTitle &&
|
|
9392
|
+
formatAttributeValue({ t, type: sourceTitleAttribute.type, value: sourceTitle, stringFormat: sourceTitleAttribute.stringFormat })) ||
|
|
9393
|
+
(!!layerDefinitionTitle &&
|
|
9394
|
+
formatAttributeValue({
|
|
9395
|
+
t,
|
|
9396
|
+
type: layerDefinitionAttribute.type,
|
|
9397
|
+
value: layerDefinitionTitle,
|
|
9398
|
+
stringFormat: layerDefinitionAttribute.stringFormat,
|
|
9399
|
+
})) ||
|
|
9400
|
+
feature?.id);
|
|
9401
|
+
}, [attributes, feature?.id, layerDefinition, title, titleAttribute]);
|
|
9402
|
+
return (jsxRuntime.jsxs(HeaderTitleContainer, { children: [jsxRuntime.jsx(FeatureTitleContainer, { clickable: true, children: jsxRuntime.jsx(uilibGl.Tooltip, { arrow: true, placement: "top", content: t("zoomToFeature", { ns: "dashboard" }), delay: [600, 0], children: ref => (jsxRuntime.jsx(uilibGl.FlexSpan, { ref: ref, onClick: () => zoomToFeatures([feature]), children: resultTitle })) }) }), jsxRuntime.jsx(LayerDescription, { title: resultDescription, children: resultDescription })] }));
|
|
9403
|
+
};
|
|
9404
|
+
|
|
8654
9405
|
const HiddenFilters = styled(uilibGl.Flex) `
|
|
8655
9406
|
flex-wrap: wrap;
|
|
8656
9407
|
margin-top: -1.25rem;
|
|
@@ -8673,15 +9424,15 @@ function isIsoDate(value) {
|
|
|
8673
9424
|
const d = new Date(value);
|
|
8674
9425
|
return !isNaN(d.getTime());
|
|
8675
9426
|
}
|
|
8676
|
-
const HiddenTitleItems =
|
|
9427
|
+
const HiddenTitleItems = React.memo(({ elementConfig, config, type, filter }) => {
|
|
8677
9428
|
const { filters, dataSources, changeFilters, expandedContainers } = useWidgetContext(type);
|
|
8678
9429
|
const { filters: configFilters } = config || {};
|
|
8679
9430
|
const { id, options, children } = elementConfig || {};
|
|
8680
9431
|
const { fontColor, expandable, expanded } = options || {};
|
|
8681
9432
|
const isVisible = isVisibleContainer(id, expandable, expanded, expandedContainers);
|
|
8682
|
-
const filterItems =
|
|
8683
|
-
const configFilter =
|
|
8684
|
-
const clearFilter =
|
|
9433
|
+
const filterItems = React.useMemo(() => children?.filter(child => child.options?.filterName), [children]);
|
|
9434
|
+
const configFilter = React.useMemo(() => getConfigFilter(filter, configFilters), [configFilters, filter]);
|
|
9435
|
+
const clearFilter = React.useCallback((name, value) => {
|
|
8685
9436
|
changeFilters({
|
|
8686
9437
|
[name]: {
|
|
8687
9438
|
value: value &&
|
|
@@ -8693,26 +9444,26 @@ const HiddenTitleItems = react.memo(({ elementConfig, config, type, filter }) =>
|
|
|
8693
9444
|
},
|
|
8694
9445
|
}, configFilter?.resetFilters);
|
|
8695
9446
|
}, [changeFilters, configFilter?.resetFilters, configFilter?.valueType, filters]);
|
|
8696
|
-
const selectedItems =
|
|
8697
|
-
const isLoading =
|
|
9447
|
+
const selectedItems = React.useMemo(() => getFilterSelectedItems(filterItems, filters, configFilters), [configFilters, filters, filterItems]);
|
|
9448
|
+
const isLoading = React.useMemo(() => elementConfig?.children?.some(child => {
|
|
8698
9449
|
const currentFilter = configFilters?.find(({ name }) => name === child.options?.filterName);
|
|
8699
9450
|
return (!!currentFilter &&
|
|
8700
9451
|
!!child.options?.filterName &&
|
|
8701
9452
|
!dataSources?.some(({ name }) => name === currentFilter.relatedDataSource));
|
|
8702
9453
|
}), [configFilters, dataSources, elementConfig?.children]);
|
|
8703
|
-
const chipProps =
|
|
9454
|
+
const chipProps = React.useMemo(() => ({
|
|
8704
9455
|
$fontSize: "0.75rem",
|
|
8705
9456
|
$fontColor: fontColor,
|
|
8706
9457
|
$bgColor: fontColor ? transparentizeColor(fontColor, 6) : null,
|
|
8707
9458
|
$radius: "0.25rem",
|
|
8708
9459
|
}), [fontColor]);
|
|
8709
|
-
const formatValue =
|
|
9460
|
+
const formatValue = React.useCallback((value) => {
|
|
8710
9461
|
return typeof value === "object" ? uilibGl.dateFormat(value) : isIsoDate(value) ? uilibGl.dateFormat(new Date(value)) : value;
|
|
8711
9462
|
}, []);
|
|
8712
|
-
const formatJoin =
|
|
9463
|
+
const formatJoin = React.useCallback((valueType) => {
|
|
8713
9464
|
return valueType === "range" ? " - " : ", ";
|
|
8714
9465
|
}, []);
|
|
8715
|
-
const renderItem =
|
|
9466
|
+
const renderItem = React.useCallback((filterName, value, index) => {
|
|
8716
9467
|
return (jsxRuntime.jsxs(DashboardChip$1, { ...chipProps, children: [value, " ", jsxRuntime.jsx(uilibGl.IconButton, { kind: "close", onClick: () => clearFilter(filterName, value) })] }, index));
|
|
8717
9468
|
}, [chipProps, clearFilter]);
|
|
8718
9469
|
if (isLoading || isVisible || !selectedItems.length)
|
|
@@ -8749,7 +9500,7 @@ const PageNavigator = styled(uilibGl.Flex) `
|
|
|
8749
9500
|
}
|
|
8750
9501
|
`;
|
|
8751
9502
|
|
|
8752
|
-
const Pagination =
|
|
9503
|
+
const Pagination = React.memo(({ type = exports.WidgetType.Dashboard }) => {
|
|
8753
9504
|
const { nextPage, prevPage } = useWidgetContext(type);
|
|
8754
9505
|
const { pages } = useWidgetConfig(type);
|
|
8755
9506
|
return (jsxRuntime.jsxs(PageNavigator, { children: [jsxRuntime.jsx(uilibGl.IconButton, { kind: "prev", onClick: () => prevPage(pages.length) }), jsxRuntime.jsx(uilibGl.IconButton, { kind: "next", onClick: () => nextPage(pages.length) })] }));
|
|
@@ -8784,10 +9535,10 @@ const StyledSvg = styled.div `
|
|
|
8784
9535
|
${({ $fontColor }) => !!$fontColor && StyledSvgColorMixin};
|
|
8785
9536
|
`;
|
|
8786
9537
|
|
|
8787
|
-
const SvgImage =
|
|
8788
|
-
const [svg, setSvg] =
|
|
8789
|
-
const [loading, setLoading] =
|
|
8790
|
-
|
|
9538
|
+
const SvgImage = React.memo(({ url, width, height, fontColor }) => {
|
|
9539
|
+
const [svg, setSvg] = React.useState(null);
|
|
9540
|
+
const [loading, setLoading] = React.useState(false);
|
|
9541
|
+
React.useEffect(() => {
|
|
8791
9542
|
if (!url || loading) {
|
|
8792
9543
|
return;
|
|
8793
9544
|
}
|
|
@@ -8799,7 +9550,7 @@ const SvgImage = react.memo(({ url, width, height, fontColor }) => {
|
|
|
8799
9550
|
setLoading(false);
|
|
8800
9551
|
});
|
|
8801
9552
|
}, [url]);
|
|
8802
|
-
|
|
9553
|
+
React.useEffect(() => () => {
|
|
8803
9554
|
setSvg(null);
|
|
8804
9555
|
}, []);
|
|
8805
9556
|
if (!svg?.endsWith("</svg>"))
|
|
@@ -8807,11 +9558,11 @@ const SvgImage = react.memo(({ url, width, height, fontColor }) => {
|
|
|
8807
9558
|
return (jsxRuntime.jsx(StyledSvg, { "$width": width, "$height": height, "$fontColor": fontColor, dangerouslySetInnerHTML: { __html: svg } }));
|
|
8808
9559
|
});
|
|
8809
9560
|
|
|
8810
|
-
const TextTrim =
|
|
9561
|
+
const TextTrim = React.memo(({ maxLength, expandable, lineBreak, children }) => {
|
|
8811
9562
|
const { t } = useGlobalContext();
|
|
8812
9563
|
const [expanded, toggleExpanded] = useToggle();
|
|
8813
9564
|
const text = children?.toString();
|
|
8814
|
-
const formatValue =
|
|
9565
|
+
const formatValue = React.useCallback((value) => {
|
|
8815
9566
|
if (!lineBreak)
|
|
8816
9567
|
return value;
|
|
8817
9568
|
return jsxRuntime.jsx("div", { dangerouslySetInnerHTML: { __html: lodash.unescape(value).split(lineBreak).join("<br />") } });
|
|
@@ -8884,7 +9635,7 @@ const getClientStyleItemPrefixSuffix = (geometryType, type) => {
|
|
|
8884
9635
|
const VectorLayer = ({ layer, tileUrl, visible, beforeId, getLayerTempStyle, }) => {
|
|
8885
9636
|
const clientStyle = layer?.configuration?.clientStyle;
|
|
8886
9637
|
const { idAttribute, geometryType } = layer.layerDefinition || {};
|
|
8887
|
-
const renderLayerByGeometryType =
|
|
9638
|
+
const renderLayerByGeometryType = React.useCallback(() => {
|
|
8888
9639
|
const visibility = visible ? "visible" : "none";
|
|
8889
9640
|
switch (geometryType) {
|
|
8890
9641
|
case api.GeometryType.Point:
|
|
@@ -8951,7 +9702,7 @@ const VectorLayer = ({ layer, tileUrl, visible, beforeId, getLayerTempStyle, })
|
|
|
8951
9702
|
visible,
|
|
8952
9703
|
getLayerTempStyle,
|
|
8953
9704
|
]);
|
|
8954
|
-
const renderClientStyle =
|
|
9705
|
+
const renderClientStyle = React.useCallback(() => {
|
|
8955
9706
|
return clientStyle.items.map(mockItem => {
|
|
8956
9707
|
const prefixSuffix = getClientStyleItemPrefixSuffix(geometryType, mockItem.type);
|
|
8957
9708
|
const isExtrusionItem = mockItem.type === "fill-extrusion";
|
|
@@ -8999,7 +9750,7 @@ const VectorLayer = ({ layer, tileUrl, visible, beforeId, getLayerTempStyle, })
|
|
|
8999
9750
|
};
|
|
9000
9751
|
|
|
9001
9752
|
const Layer = ({ layer, layerType, visible, beforeId, tileUrl, getLayerTempStyle, onMount = () => null, }) => {
|
|
9002
|
-
|
|
9753
|
+
React.useEffect(onMount, []); // eslint-disable-line
|
|
9003
9754
|
if (!layer) {
|
|
9004
9755
|
return null;
|
|
9005
9756
|
}
|
|
@@ -9042,23 +9793,6 @@ const Map$1 = ({ zIndex, lowerSiblings, upperSiblings, onError, children, ...res
|
|
|
9042
9793
|
}, children: children }), upperSiblings] }));
|
|
9043
9794
|
};
|
|
9044
9795
|
|
|
9045
|
-
exports.ThemeName = void 0;
|
|
9046
|
-
(function (ThemeName) {
|
|
9047
|
-
ThemeName["Light"] = "light";
|
|
9048
|
-
ThemeName["Dark"] = "dark";
|
|
9049
|
-
})(exports.ThemeName || (exports.ThemeName = {}));
|
|
9050
|
-
|
|
9051
|
-
exports.TmsType = void 0;
|
|
9052
|
-
(function (TmsType) {
|
|
9053
|
-
TmsType["WMS"] = "WMS";
|
|
9054
|
-
TmsType["TMS"] = "TMS";
|
|
9055
|
-
TmsType["ArcGIS"] = "ArcGIS";
|
|
9056
|
-
})(exports.TmsType || (exports.TmsType = {}));
|
|
9057
|
-
exports.EditGeometryType = void 0;
|
|
9058
|
-
(function (EditGeometryType) {
|
|
9059
|
-
EditGeometryType["Raster"] = "raster";
|
|
9060
|
-
})(exports.EditGeometryType || (exports.EditGeometryType = {}));
|
|
9061
|
-
|
|
9062
9796
|
exports.AddFeatureButton = AddFeatureButton;
|
|
9063
9797
|
exports.AddFeatureContainer = AddFeatureContainer;
|
|
9064
9798
|
exports.AttributeGalleryContainer = AttributeGalleryContainer;
|
|
@@ -9099,6 +9833,8 @@ exports.DashboardCheckbox = DashboardCheckbox;
|
|
|
9099
9833
|
exports.DashboardChip = DashboardChip;
|
|
9100
9834
|
exports.DashboardContent = DashboardContent;
|
|
9101
9835
|
exports.DashboardContext = DashboardContext;
|
|
9836
|
+
exports.DashboardDefaultHeader = DashboardDefaultHeader;
|
|
9837
|
+
exports.DashboardHeader = DashboardHeader;
|
|
9102
9838
|
exports.DashboardPlaceholder = DashboardPlaceholder;
|
|
9103
9839
|
exports.DashboardPlaceholderWrap = DashboardPlaceholderWrap;
|
|
9104
9840
|
exports.DashboardProvider = DashboardProvider;
|
|
@@ -9109,6 +9845,7 @@ exports.DataSourceErrorContainer = DataSourceErrorContainer;
|
|
|
9109
9845
|
exports.DataSourceInnerContainer = DataSourceInnerContainer;
|
|
9110
9846
|
exports.DataSourceProgressContainer = DataSourceProgressContainer;
|
|
9111
9847
|
exports.DefaultAttributesContainer = DefaultAttributesContainer;
|
|
9848
|
+
exports.DefaultHeaderContainer = DefaultHeaderContainer;
|
|
9112
9849
|
exports.DividerContainer = DividerContainer;
|
|
9113
9850
|
exports.ElementButton = ElementButton;
|
|
9114
9851
|
exports.ElementCamera = ElementCamera;
|
|
@@ -9127,24 +9864,40 @@ exports.FEATURE_CARD_DEFAULT_COLORS = FEATURE_CARD_DEFAULT_COLORS;
|
|
|
9127
9864
|
exports.FEATURE_CARD_OTHER_COLOR = FEATURE_CARD_OTHER_COLOR;
|
|
9128
9865
|
exports.FILTERED_VALUE_OPACITY = FILTERED_VALUE_OPACITY;
|
|
9129
9866
|
exports.FILTER_PREFIX = FILTER_PREFIX;
|
|
9867
|
+
exports.FeatureCardButtons = FeatureCardButtons;
|
|
9130
9868
|
exports.FeatureCardContext = FeatureCardContext;
|
|
9869
|
+
exports.FeatureCardDefaultHeader = FeatureCardDefaultHeader;
|
|
9870
|
+
exports.FeatureCardGradientHeader = FeatureCardGradientHeader;
|
|
9871
|
+
exports.FeatureCardHeader = FeatureCardHeader;
|
|
9872
|
+
exports.FeatureCardIconHeader = FeatureCardIconHeader;
|
|
9131
9873
|
exports.FeatureCardProvider = FeatureCardProvider;
|
|
9874
|
+
exports.FeatureCardSlideshowHeader = FeatureCardSlideshowHeader;
|
|
9875
|
+
exports.FeatureCardTitle = FeatureCardTitle;
|
|
9876
|
+
exports.FeatureControls = FeatureControls;
|
|
9877
|
+
exports.FeatureTitleContainer = FeatureTitleContainer;
|
|
9132
9878
|
exports.FiltersContainer = FiltersContainer;
|
|
9133
9879
|
exports.GEOMETRY_ATTRIBUTE = GEOMETRY_ATTRIBUTE;
|
|
9134
9880
|
exports.GlobalContext = GlobalContext;
|
|
9135
9881
|
exports.GlobalProvider = GlobalProvider;
|
|
9882
|
+
exports.Header = Header;
|
|
9883
|
+
exports.HeaderContainer = HeaderContainer;
|
|
9884
|
+
exports.HeaderFrontView = HeaderFrontView;
|
|
9885
|
+
exports.HeaderTitleContainer = HeaderTitleContainer;
|
|
9136
9886
|
exports.HiddenTitleItems = HiddenTitleItems;
|
|
9137
9887
|
exports.IconContainer = IconContainer;
|
|
9138
9888
|
exports.ImageContainer = ImageContainer;
|
|
9139
9889
|
exports.LEFT_PANEL_HEADER_HEIGHT = LEFT_PANEL_HEADER_HEIGHT;
|
|
9140
9890
|
exports.Layer = Layer;
|
|
9891
|
+
exports.LayerDescription = LayerDescription;
|
|
9141
9892
|
exports.LayerGroup = LayerGroup;
|
|
9142
9893
|
exports.LayerGroupList = LayerGroupList;
|
|
9894
|
+
exports.LayerIcon = LayerIcon;
|
|
9143
9895
|
exports.LayerListContainer = LayerListContainer;
|
|
9144
9896
|
exports.LayerTree = LayerTree;
|
|
9145
9897
|
exports.LayersContainer = LayersContainer;
|
|
9146
9898
|
exports.LayersListWrapper = LayersListWrapper;
|
|
9147
9899
|
exports.LinearProgressContainer = LinearProgressContainer;
|
|
9900
|
+
exports.LogoContainer = LogoContainer;
|
|
9148
9901
|
exports.MAX_CHART_WIDTH = MAX_CHART_WIDTH;
|
|
9149
9902
|
exports.Map = Map$1;
|
|
9150
9903
|
exports.MapContext = MapContext;
|
|
@@ -9154,6 +9907,7 @@ exports.NUMERIC_ATTRIBUTE_TYPES = NUMERIC_ATTRIBUTE_TYPES;
|
|
|
9154
9907
|
exports.NoLiveSnapshotContainer = NoLiveSnapshotContainer;
|
|
9155
9908
|
exports.OneColumnContainer = OneColumnContainer;
|
|
9156
9909
|
exports.PageNavigator = PageNavigator;
|
|
9910
|
+
exports.PageTitle = PageTitle;
|
|
9157
9911
|
exports.PagesContainer = PagesContainer;
|
|
9158
9912
|
exports.Pagination = Pagination;
|
|
9159
9913
|
exports.PresentationHeader = PresentationHeader;
|
|
@@ -9167,7 +9921,7 @@ exports.RoundedBackgroundContainer = RoundedBackgroundContainer;
|
|
|
9167
9921
|
exports.ServerNotificationsContext = ServerNotificationsContext;
|
|
9168
9922
|
exports.ServerNotificationsProvider = ServerNotificationsProvider;
|
|
9169
9923
|
exports.SlideshowContainer = SlideshowContainer;
|
|
9170
|
-
exports.SmallPreviewContainer = SmallPreviewContainer;
|
|
9924
|
+
exports.SmallPreviewContainer = SmallPreviewContainer$1;
|
|
9171
9925
|
exports.SmallPreviewControl = SmallPreviewControl;
|
|
9172
9926
|
exports.SmallPreviewCounter = SmallPreviewCounter;
|
|
9173
9927
|
exports.SmallPreviewImages = SmallPreviewImages;
|
|
@@ -9179,6 +9933,8 @@ exports.TIME_ZONE_FORMAT = TIME_ZONE_FORMAT;
|
|
|
9179
9933
|
exports.TabsContainer = TabsContainer;
|
|
9180
9934
|
exports.TextTrim = TextTrim;
|
|
9181
9935
|
exports.TitleContainer = TitleContainer;
|
|
9936
|
+
exports.TopContainer = TopContainer;
|
|
9937
|
+
exports.TopContainerButtons = TopContainerButtons;
|
|
9182
9938
|
exports.TwoColumnContainer = TwoColumnContainer;
|
|
9183
9939
|
exports.TwoColumnsInnerContainer = TwoColumnsInnerContainer;
|
|
9184
9940
|
exports.addDataSource = addDataSource;
|
|
@@ -9216,6 +9972,7 @@ exports.getChartFilterName = getChartFilterName;
|
|
|
9216
9972
|
exports.getChartMarkers = getChartMarkers;
|
|
9217
9973
|
exports.getConfigFilter = getConfigFilter;
|
|
9218
9974
|
exports.getContainerComponent = getContainerComponent;
|
|
9975
|
+
exports.getDashboardHeader = getDashboardHeader;
|
|
9219
9976
|
exports.getDataFromAttributes = getDataFromAttributes;
|
|
9220
9977
|
exports.getDataFromRelatedFeatures = getDataFromRelatedFeatures;
|
|
9221
9978
|
exports.getDataSource = getDataSource;
|
|
@@ -9224,6 +9981,7 @@ exports.getDate = getDate;
|
|
|
9224
9981
|
exports.getDefaultConfig = getDefaultConfig;
|
|
9225
9982
|
exports.getElementValue = getElementValue;
|
|
9226
9983
|
exports.getFeatureAttributes = getFeatureAttributes;
|
|
9984
|
+
exports.getFeatureCardHeader = getFeatureCardHeader;
|
|
9227
9985
|
exports.getFilterComponent = getFilterComponent;
|
|
9228
9986
|
exports.getFilterSelectedItems = getFilterSelectedItems;
|
|
9229
9987
|
exports.getFilterValue = getFilterValue;
|
|
@@ -9275,6 +10033,7 @@ exports.useExpandableContainers = useExpandableContainers;
|
|
|
9275
10033
|
exports.useFeatureFilters = useFeatureFilters;
|
|
9276
10034
|
exports.useGetConfigLayer = useGetConfigLayer;
|
|
9277
10035
|
exports.useGlobalContext = useGlobalContext;
|
|
10036
|
+
exports.useHeaderRender = useHeaderRender;
|
|
9278
10037
|
exports.useLayerParams = useLayerParams;
|
|
9279
10038
|
exports.useMapContext = useMapContext;
|
|
9280
10039
|
exports.useMapDraw = useMapDraw;
|