@evergis/react 4.0.44 → 4.0.46
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/hooks/index.d.ts +1 -0
- package/dist/components/Dashboard/hooks/useContainerAttributes.d.ts +15 -0
- package/dist/components/Dashboard/types.d.ts +1 -0
- package/dist/index.js +953 -946
- package/dist/index.js.map +1 -1
- package/dist/react.esm.js +956 -950
- package/dist/react.esm.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -12,14 +12,14 @@ var turf = require('@turf/turf');
|
|
|
12
12
|
var dateFns = require('date-fns');
|
|
13
13
|
var lodash = require('lodash');
|
|
14
14
|
var locale = require('date-fns/locale');
|
|
15
|
-
var signalr = require('@microsoft/signalr');
|
|
16
15
|
var findAnd = require('find-and');
|
|
17
|
-
var
|
|
18
|
-
var html2canvas = require('html2canvas');
|
|
16
|
+
var signalr = require('@microsoft/signalr');
|
|
19
17
|
var MapboxDraw = require('@mapbox/mapbox-gl-draw');
|
|
20
18
|
var MapGL = require('react-map-gl/maplibre');
|
|
21
19
|
require('@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css');
|
|
22
20
|
require('mapbox-gl/dist/mapbox-gl.css');
|
|
21
|
+
var jspdf = require('jspdf');
|
|
22
|
+
var html2canvas = require('html2canvas');
|
|
23
23
|
var react = require('swiper/react');
|
|
24
24
|
var ReactMarkdown = require('react-markdown');
|
|
25
25
|
var rehypeRaw = require('rehype-raw');
|
|
@@ -3961,880 +3961,461 @@ const useAutoCompleteControl = (items) => {
|
|
|
3961
3961
|
};
|
|
3962
3962
|
};
|
|
3963
3963
|
|
|
3964
|
-
const
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
const cleanupRef = React.useRef(cleanup);
|
|
3969
|
-
transformRef.current = transform;
|
|
3970
|
-
cleanupRef.current = cleanup;
|
|
3971
|
-
const fetchData = React.useCallback(() => {
|
|
3972
|
-
if (!url || loadingRef.current)
|
|
3973
|
-
return;
|
|
3974
|
-
loadingRef.current = true;
|
|
3975
|
-
const token = window.localStorage.getItem(api.STORAGE_TOKEN_KEY);
|
|
3976
|
-
fetch(url, {
|
|
3977
|
-
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
|
3978
|
-
})
|
|
3979
|
-
.then(res => (res.ok ? transformRef.current(res) : null))
|
|
3980
|
-
.then(setData)
|
|
3981
|
-
.catch(() => {
|
|
3982
|
-
setData(null);
|
|
3983
|
-
})
|
|
3984
|
-
.finally(() => {
|
|
3985
|
-
loadingRef.current = false;
|
|
3986
|
-
});
|
|
3987
|
-
}, [url]);
|
|
3988
|
-
React.useEffect(() => {
|
|
3989
|
-
if (url) {
|
|
3990
|
-
fetchData();
|
|
3991
|
-
}
|
|
3992
|
-
else {
|
|
3993
|
-
setData(null);
|
|
3994
|
-
}
|
|
3995
|
-
}, [url]);
|
|
3996
|
-
React.useEffect(() => () => {
|
|
3997
|
-
if (data !== null)
|
|
3998
|
-
cleanupRef.current?.(data);
|
|
3999
|
-
}, [data]);
|
|
4000
|
-
return data;
|
|
4001
|
-
};
|
|
4002
|
-
|
|
4003
|
-
const toObjectUrl = (res) => res.blob().then(blob => URL.createObjectURL(blob));
|
|
4004
|
-
const useFetchImageWithAuth = (url) => useFetchWithAuth(url, toObjectUrl, URL.revokeObjectURL);
|
|
3964
|
+
const eqlParametersToPayload = (parameters) => Object.keys(parameters).reduce((result, paramName) => ({
|
|
3965
|
+
...result,
|
|
3966
|
+
[paramName]: parameters[paramName].default,
|
|
3967
|
+
}), {});
|
|
4005
3968
|
|
|
4006
|
-
const
|
|
4007
|
-
const
|
|
4008
|
-
|
|
4009
|
-
|
|
3969
|
+
const addDataSource = (dashboardConfiguration, pageIndex, query, additional) => {
|
|
3970
|
+
const newConfig = JSON.parse(JSON.stringify(dashboardConfiguration));
|
|
3971
|
+
if (!newConfig.children[0].children[pageIndex].dataSources) {
|
|
3972
|
+
newConfig.children[0].children[pageIndex].dataSources = [];
|
|
3973
|
+
}
|
|
3974
|
+
const freeId = newConfig.children[0].children[pageIndex].dataSources.length + 1;
|
|
3975
|
+
const parameters = eqlParametersToPayload(additional.parameters);
|
|
3976
|
+
newConfig.children[0].children[pageIndex].dataSources.push({
|
|
3977
|
+
name: `datasource_${freeId}`,
|
|
3978
|
+
query,
|
|
3979
|
+
parameters,
|
|
3980
|
+
offset: 0,
|
|
3981
|
+
limit: DEFAULT_DATA_SOURCE_LIMIT,
|
|
3982
|
+
});
|
|
3983
|
+
return newConfig.children;
|
|
3984
|
+
};
|
|
4010
3985
|
|
|
4011
|
-
const
|
|
4012
|
-
const
|
|
4013
|
-
|
|
4014
|
-
|
|
3986
|
+
const addDataSources = (dashboardConfiguration, pageIndex, layerNames) => {
|
|
3987
|
+
const newConfig = JSON.parse(JSON.stringify(dashboardConfiguration));
|
|
3988
|
+
if (!newConfig.children[0].children[pageIndex].dataSources) {
|
|
3989
|
+
newConfig.children[0].children[pageIndex].dataSources = [];
|
|
3990
|
+
}
|
|
3991
|
+
layerNames.forEach(layerName => {
|
|
3992
|
+
newConfig.children[0].children[pageIndex].dataSources.push({
|
|
3993
|
+
name: layerName.split(".")[1],
|
|
3994
|
+
layerName,
|
|
3995
|
+
query: "",
|
|
3996
|
+
parameters: {},
|
|
3997
|
+
});
|
|
3998
|
+
});
|
|
3999
|
+
return newConfig.children;
|
|
4000
|
+
};
|
|
4015
4001
|
|
|
4016
|
-
const
|
|
4017
|
-
const GlobalProvider = React.memo(({ children, ...props }) => {
|
|
4018
|
-
return jsxRuntime.jsx(GlobalContext.Provider, { value: props, children: children });
|
|
4019
|
-
});
|
|
4002
|
+
const getConfigFilter = (filterName, configFilters) => configFilters?.find(({ name }) => name === filterName);
|
|
4020
4003
|
|
|
4021
|
-
const
|
|
4004
|
+
const getDataSource = (dataSourceName, dataSources) => dataSources?.find(({ name }) => name === dataSourceName);
|
|
4022
4005
|
|
|
4023
|
-
const
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
const
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
loaded,
|
|
4032
|
-
setLoaded,
|
|
4033
|
-
basemapItems,
|
|
4034
|
-
basemapName,
|
|
4035
|
-
setBasemapName,
|
|
4036
|
-
defaultBasemap,
|
|
4037
|
-
}, children: children }));
|
|
4006
|
+
const getDataSourceFilterValue = ({ filterName, filterProp, attributeAlias, dataSource, selectedFilters, }) => {
|
|
4007
|
+
if (lodash.isNil(selectedFilters[filterName]))
|
|
4008
|
+
return null;
|
|
4009
|
+
const feature = dataSource?.features?.find(({ properties }) => properties[attributeAlias] ===
|
|
4010
|
+
(Array.isArray(selectedFilters[filterName].value)
|
|
4011
|
+
? selectedFilters[filterName].value[0]
|
|
4012
|
+
: selectedFilters[filterName].value));
|
|
4013
|
+
return feature?.properties?.[filterProp];
|
|
4038
4014
|
};
|
|
4039
4015
|
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4016
|
+
const getSelectedFilterValue = (filterName, selectedFilters, defaultValue) => {
|
|
4017
|
+
return ((!lodash.isNil(selectedFilters?.[filterName]?.value) &&
|
|
4018
|
+
Array.isArray(defaultValue) &&
|
|
4019
|
+
!Array.isArray(selectedFilters[filterName].value)
|
|
4020
|
+
? [selectedFilters[filterName].value]
|
|
4021
|
+
: selectedFilters?.[filterName]?.value) ?? defaultValue);
|
|
4022
|
+
};
|
|
4047
4023
|
|
|
4048
|
-
const
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4024
|
+
const applyQueryFilters = ({ parameters: configParameters, filters: configFilters, selectedFilters, geometry, attributes, layerInfo, dataSources, projectDataSources, }) => {
|
|
4025
|
+
if (!configParameters) {
|
|
4026
|
+
return {};
|
|
4027
|
+
}
|
|
4028
|
+
return Object.keys(configParameters).reduce((result, key) => {
|
|
4029
|
+
if (typeof configParameters[key] === "string" && configParameters[key].startsWith(PROVIDER_PREFIX)) {
|
|
4030
|
+
const raw = configParameters[key].slice(PROVIDER_PREFIX.length);
|
|
4031
|
+
const [provider, layerName, fieldName] = raw.split(":");
|
|
4032
|
+
if (provider === exports.ProviderPrefix.Card && fieldName && layerInfo.name === layerName && attributes) {
|
|
4033
|
+
const attribute = attributes.find(({ attributeName }) => attributeName === fieldName);
|
|
4034
|
+
const cardValue = attribute?.value ?? null;
|
|
4035
|
+
if (lodash.isNil(cardValue))
|
|
4036
|
+
return result;
|
|
4037
|
+
return { ...result, [key]: cardValue };
|
|
4038
|
+
}
|
|
4039
|
+
if (provider === exports.ProviderPrefix.Left && layerName && fieldName && projectDataSources?.length) {
|
|
4040
|
+
const dataSource = projectDataSources.find(({ layerName: name }) => name === layerName);
|
|
4041
|
+
const leftValue = dataSource?.features?.[0]?.properties?.[fieldName] ?? null;
|
|
4042
|
+
if (lodash.isNil(leftValue))
|
|
4043
|
+
return result;
|
|
4044
|
+
return { ...result, [key]: leftValue };
|
|
4045
|
+
}
|
|
4046
|
+
return result;
|
|
4054
4047
|
}
|
|
4055
|
-
|
|
4056
|
-
.
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4048
|
+
if (typeof configParameters[key] === "string" && configParameters[key].includes("{") && attributes?.length) {
|
|
4049
|
+
const exactAttr = attributes.find(({ attributeName }) => configParameters[key] === `{${attributeName}}`);
|
|
4050
|
+
if (exactAttr) {
|
|
4051
|
+
return { ...result, [key]: exactAttr.value ?? "" };
|
|
4052
|
+
}
|
|
4053
|
+
let interpolated = configParameters[key];
|
|
4054
|
+
attributes.forEach(({ attributeName, value: attrValue }) => {
|
|
4055
|
+
interpolated = interpolated.replace(new RegExp(`\\{${attributeName}\\}`, "g"), attrValue?.toString() ?? "");
|
|
4056
|
+
});
|
|
4057
|
+
return { ...result, [key]: interpolated };
|
|
4063
4058
|
}
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
accessTokenFactory: async () => {
|
|
4070
|
-
let accessToken = window.localStorage.getItem(api.STORAGE_TOKEN_KEY) || "";
|
|
4071
|
-
const { exp } = api.parseJwt(accessToken);
|
|
4072
|
-
const currentTime = new Date().getTime() / 1000;
|
|
4073
|
-
if (currentTime > exp) {
|
|
4074
|
-
const refreshToken = window.localStorage.getItem(api.STORAGE_REFRESH_TOKEN_KEY);
|
|
4075
|
-
if (refreshToken) {
|
|
4076
|
-
const refreshTokenResponse = await apiClient.account.refreshToken({
|
|
4077
|
-
refreshToken,
|
|
4078
|
-
});
|
|
4079
|
-
if (refreshTokenResponse) {
|
|
4080
|
-
accessToken = refreshTokenResponse.token;
|
|
4081
|
-
window.localStorage.setItem(api.STORAGE_TOKEN_KEY, refreshTokenResponse.token);
|
|
4082
|
-
window.localStorage.setItem(api.STORAGE_REFRESH_TOKEN_KEY, refreshTokenResponse.refreshToken);
|
|
4083
|
-
}
|
|
4084
|
-
}
|
|
4085
|
-
else {
|
|
4086
|
-
await apiClient.logout();
|
|
4087
|
-
}
|
|
4088
|
-
}
|
|
4089
|
-
return accessToken;
|
|
4090
|
-
},
|
|
4091
|
-
})
|
|
4092
|
-
.withAutomaticReconnect()
|
|
4093
|
-
.configureLogging(signalr.LogLevel.Information)
|
|
4094
|
-
.build();
|
|
4095
|
-
hubConnection.current
|
|
4096
|
-
.start()
|
|
4097
|
-
.then(() => console.info("Серверные нотификации подключены"))
|
|
4098
|
-
.catch(err => console.info("Ошибка:", err))
|
|
4099
|
-
.finally(() => setConnection(hubConnection.current));
|
|
4100
|
-
}, [initialized]); // eslint-disable-line
|
|
4101
|
-
React.useEffect(() => {
|
|
4102
|
-
if (!connection || connection.state !== "Connected") {
|
|
4103
|
-
return;
|
|
4059
|
+
if (typeof configParameters[key] !== "string" || !configParameters[key].startsWith("%")) {
|
|
4060
|
+
return {
|
|
4061
|
+
...result,
|
|
4062
|
+
[key]: configParameters[key],
|
|
4063
|
+
};
|
|
4104
4064
|
}
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
const connection = useServerNotifications(url, initialized, apiClient);
|
|
4114
|
-
const addSubscription = React.useCallback(async (payload) => {
|
|
4115
|
-
if (!connection || connection.state !== "Connected" || !payload) {
|
|
4116
|
-
return;
|
|
4065
|
+
const filterFullName = configParameters[key].replace("%", "");
|
|
4066
|
+
const [filterName, filterProp] = filterFullName.includes(".") ? filterFullName.split(".") : [filterFullName, null];
|
|
4067
|
+
const { defaultValue, relatedDataSource, attributeAlias } = getConfigFilter(filterName, configFilters) || {};
|
|
4068
|
+
if (filterName === "geometry" && geometry && !geometry.includes("()") && geometry.endsWith(")")) {
|
|
4069
|
+
return {
|
|
4070
|
+
...result,
|
|
4071
|
+
[key]: geometry,
|
|
4072
|
+
};
|
|
4117
4073
|
}
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4074
|
+
if (configParameters[key].endsWith(".max")) {
|
|
4075
|
+
return {
|
|
4076
|
+
...result,
|
|
4077
|
+
[key]: selectedFilters?.[filterName]?.max ?? (Array.isArray(defaultValue) ? defaultValue[1] : defaultValue),
|
|
4078
|
+
};
|
|
4122
4079
|
}
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
const updateSubscription = React.useCallback(async (id, payload) => {
|
|
4129
|
-
if (!connection || connection.state !== "Connected" || !id || !payload) {
|
|
4130
|
-
return;
|
|
4131
|
-
}
|
|
4132
|
-
try {
|
|
4133
|
-
await connection.invoke("UpdateSubscription", id, payload);
|
|
4134
|
-
}
|
|
4135
|
-
catch (err) {
|
|
4136
|
-
console.info(`Ошибка обновления подписки ${id}:`, err);
|
|
4137
|
-
}
|
|
4138
|
-
}, [connection]);
|
|
4139
|
-
const unsubscribeById = React.useCallback(async (id) => {
|
|
4140
|
-
if (!connection || connection.state !== "Connected" || !id) {
|
|
4141
|
-
return;
|
|
4080
|
+
if (configParameters[key].endsWith(".min")) {
|
|
4081
|
+
return {
|
|
4082
|
+
...result,
|
|
4083
|
+
[key]: selectedFilters?.[filterName]?.min ?? (Array.isArray(defaultValue) ? defaultValue[0] : defaultValue),
|
|
4084
|
+
};
|
|
4142
4085
|
}
|
|
4143
|
-
|
|
4144
|
-
|
|
4086
|
+
if (configParameters[key].includes(".")) {
|
|
4087
|
+
return {
|
|
4088
|
+
...result,
|
|
4089
|
+
[key]: getDataSourceFilterValue({
|
|
4090
|
+
filterName,
|
|
4091
|
+
filterProp,
|
|
4092
|
+
selectedFilters,
|
|
4093
|
+
attributeAlias,
|
|
4094
|
+
dataSource: getDataSource(relatedDataSource, dataSources),
|
|
4095
|
+
}) ?? defaultValue,
|
|
4096
|
+
};
|
|
4145
4097
|
}
|
|
4146
|
-
|
|
4147
|
-
|
|
4098
|
+
const value = getSelectedFilterValue(filterName, selectedFilters, defaultValue);
|
|
4099
|
+
if (lodash.isNil(value)) {
|
|
4100
|
+
return result;
|
|
4148
4101
|
}
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
unsubscribeById,
|
|
4155
|
-
}, children: children }));
|
|
4102
|
+
return {
|
|
4103
|
+
...result,
|
|
4104
|
+
[key]: value,
|
|
4105
|
+
};
|
|
4106
|
+
}, {});
|
|
4156
4107
|
};
|
|
4157
4108
|
|
|
4158
|
-
const
|
|
4159
|
-
|
|
4160
|
-
|
|
4109
|
+
const checkEqualOrIncludes = (arrayOrSingle, value) => arrayOrSingle && Array.isArray(arrayOrSingle) ? arrayOrSingle.includes(value) : arrayOrSingle === value;
|
|
4110
|
+
|
|
4111
|
+
const checkIsLoading = (dataSources, config, filters) => config?.children?.some(child => {
|
|
4112
|
+
const filter = filters?.find(({ name }) => name === child.options?.filterName);
|
|
4113
|
+
return (!!filter && !!child.options?.filterName && !dataSources?.some(({ name }) => name === filter.relatedDataSource));
|
|
4114
|
+
});
|
|
4115
|
+
|
|
4116
|
+
const createConfigLayer = (layerName) => ({
|
|
4117
|
+
name: layerName,
|
|
4118
|
+
query: "",
|
|
4119
|
+
parameters: {},
|
|
4120
|
+
opacity: 1,
|
|
4121
|
+
selectable: false,
|
|
4122
|
+
filterZoomTo: false,
|
|
4123
|
+
isVisible: true,
|
|
4124
|
+
});
|
|
4125
|
+
|
|
4126
|
+
const createNewPageId = (pages) => {
|
|
4127
|
+
if (!pages?.length)
|
|
4128
|
+
return 1;
|
|
4129
|
+
const maxPageId = pages.reduce((maxId, page) => {
|
|
4130
|
+
const pageId = parseInt(page.id.replace(CONFIG_PAGE_ID, ""), 10);
|
|
4131
|
+
return Math.max(maxId, pageId);
|
|
4132
|
+
}, 0);
|
|
4133
|
+
return maxPageId + 1;
|
|
4134
|
+
};
|
|
4135
|
+
|
|
4136
|
+
const createConfigPage = (props) => {
|
|
4137
|
+
const { title, defaultTitle, pages, baseMapName, position, resolution /* , srid*/ } = props || {};
|
|
4138
|
+
const pageId = createNewPageId(pages);
|
|
4161
4139
|
return {
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
isEditing: type === exports.WidgetType.Dashboard ? projectEditMode : featureEditMode,
|
|
4180
|
-
isLoading: type === exports.WidgetType.Dashboard ? projectLoading : featureLoading,
|
|
4181
|
-
pageIndex: type === exports.WidgetType.Dashboard ? projectPageIndex || 1 : featurePageIndex || 1,
|
|
4182
|
-
filters: type === exports.WidgetType.Dashboard ? projectFilters : featureFilters,
|
|
4183
|
-
changeFilters: type === exports.WidgetType.Dashboard ? projectChangeFilters : featureChangeFilters,
|
|
4184
|
-
dataSources: type === exports.WidgetType.Dashboard ? projectDataSources : featureDataSources,
|
|
4185
|
-
expandContainer: type === exports.WidgetType.Dashboard ? projectExpandContainer : featureExpandContainer,
|
|
4186
|
-
expandedContainers: type === exports.WidgetType.Dashboard ? projectExpandedContainers : featureExpandedContainers,
|
|
4187
|
-
selectedTabId: type === exports.WidgetType.Dashboard ? projectSelectedTabId : featureSelectedTabId,
|
|
4188
|
-
setSelectedTabId: type === exports.WidgetType.Dashboard ? setProjectSelectedTabId : setFeatureSelectedTabId,
|
|
4189
|
-
nextPage: type === exports.WidgetType.Dashboard ? projectNextPage : featureNextPage,
|
|
4190
|
-
prevPage: type === exports.WidgetType.Dashboard ? projectPrevPage : featurePrevPage,
|
|
4191
|
-
changePage: type === exports.WidgetType.Dashboard ? projectChangePage : featureChangePage,
|
|
4140
|
+
id: `${CONFIG_PAGE_ID}${pageId}`,
|
|
4141
|
+
templateName: exports.ContainerTemplate.ContainersGroup,
|
|
4142
|
+
children: [],
|
|
4143
|
+
layers: [],
|
|
4144
|
+
dataSources: [],
|
|
4145
|
+
filters: [],
|
|
4146
|
+
tasks: [],
|
|
4147
|
+
style: {},
|
|
4148
|
+
options: {
|
|
4149
|
+
title: title || [defaultTitle, pageId].filter(Boolean).join(" "),
|
|
4150
|
+
position: position || [DEFAULT_LNG, DEFAULT_LAT],
|
|
4151
|
+
resolution: resolution || DEFAULT_ZOOM,
|
|
4152
|
+
baseMapName: baseMapName || DEFAULT_BASE_MAP,
|
|
4153
|
+
baseMapSettings: {},
|
|
4154
|
+
expandedLayers: true,
|
|
4155
|
+
// srid: srid || null,
|
|
4156
|
+
},
|
|
4192
4157
|
};
|
|
4193
4158
|
};
|
|
4194
4159
|
|
|
4195
|
-
const
|
|
4196
|
-
const
|
|
4197
|
-
const
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4160
|
+
const getAttributesConfiguration = (layer) => {
|
|
4161
|
+
const layerAttributeConfiguration = layer?.configuration?.attributesConfiguration ?? {};
|
|
4162
|
+
const { geometryAttribute, idAttribute } = layerAttributeConfiguration;
|
|
4163
|
+
const emptyLayerDefinition = {
|
|
4164
|
+
attributes: [],
|
|
4165
|
+
geometryAttribute: geometryAttribute ?? GEOMETRY_ATTRIBUTE,
|
|
4166
|
+
idAttribute: idAttribute ?? DEFAULT_ID_ATTRIBUTE_NAME,
|
|
4167
|
+
titleAttribute: "",
|
|
4168
|
+
};
|
|
4169
|
+
if (!isLayerService(layer)) {
|
|
4170
|
+
return emptyLayerDefinition;
|
|
4171
|
+
}
|
|
4172
|
+
return {
|
|
4173
|
+
...emptyLayerDefinition,
|
|
4174
|
+
...layerAttributeConfiguration,
|
|
4175
|
+
attributes: layerAttributeConfiguration?.attributes ||
|
|
4176
|
+
emptyLayerDefinition.attributes,
|
|
4177
|
+
};
|
|
4209
4178
|
};
|
|
4210
4179
|
|
|
4211
|
-
const
|
|
4212
|
-
const
|
|
4213
|
-
const
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
if (
|
|
4230
|
-
|
|
4180
|
+
const formatChartRelatedValue = (t, value, layerInfo, relatedAttributes) => {
|
|
4181
|
+
const layerDefinition = getAttributesConfiguration(layerInfo);
|
|
4182
|
+
const relatedAxis = relatedAttributes.find(({ chartAxis }) => chartAxis === "y");
|
|
4183
|
+
const attribute = layerDefinition.attributes[relatedAxis.attributeName];
|
|
4184
|
+
return attribute ? formatAttributeValue({ t, type: attribute.type, value, stringFormat: attribute.stringFormat }) : value;
|
|
4185
|
+
};
|
|
4186
|
+
|
|
4187
|
+
const isEmptyValue = (value) => value === "" || value === null || value === undefined;
|
|
4188
|
+
|
|
4189
|
+
const checkIsDateFormat = (value) => value.startsWith("#'") && value.endsWith("'");
|
|
4190
|
+
const checkIfNeedQuotes = (value, attributeType) => {
|
|
4191
|
+
return attributeType
|
|
4192
|
+
? !NUMERIC_ATTRIBUTE_TYPES.includes(attributeType)
|
|
4193
|
+
: typeof value === "number"
|
|
4194
|
+
? false
|
|
4195
|
+
: typeof value === "string" && !isNumeric(value) && !checkIsDateFormat(value);
|
|
4196
|
+
};
|
|
4197
|
+
const formatConditionValue = ({ value, attributeType, defaultValue, checkQuotes = true, isSetParams = false, }) => {
|
|
4198
|
+
if (isEmptyValue(value))
|
|
4199
|
+
return "";
|
|
4200
|
+
const formattedValue = Array.isArray(defaultValue) && !Array.isArray(value) ? [value] : value;
|
|
4201
|
+
const isArray = Array.isArray(formattedValue);
|
|
4202
|
+
let stringValue = formattedValue.toString();
|
|
4203
|
+
if (isArray) {
|
|
4204
|
+
return formattedValue.length && !formattedValue.every(item => !item)
|
|
4205
|
+
? `[${formattedValue
|
|
4206
|
+
.map(item => (checkQuotes && checkIfNeedQuotes(item, attributeType) ? `'${item}'` : item))
|
|
4207
|
+
.join(",")}]`
|
|
4208
|
+
: "";
|
|
4231
4209
|
}
|
|
4232
|
-
|
|
4233
|
-
|
|
4210
|
+
if (isSetParams && checkIsDateFormat(stringValue)) {
|
|
4211
|
+
stringValue = stringValue.slice(2, -1);
|
|
4234
4212
|
}
|
|
4235
|
-
return
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4213
|
+
return checkQuotes && checkIfNeedQuotes(stringValue, attributeType) ? `'${stringValue}'` : stringValue;
|
|
4214
|
+
};
|
|
4215
|
+
|
|
4216
|
+
const applyFiltersToCondition = ({ condition, name, defaultValue, filters, isSingle, isSetParams, }) => {
|
|
4217
|
+
const hasFilter = filters[name] !== undefined && !!filters[name].value?.toString().length;
|
|
4218
|
+
const min = formatConditionValue({
|
|
4219
|
+
value: hasFilter ? filters[name].min : null,
|
|
4220
|
+
checkQuotes: !isSingle,
|
|
4221
|
+
isSetParams,
|
|
4241
4222
|
});
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
const self = select(this);
|
|
4247
|
-
let textLength = self.node().getComputedTextLength();
|
|
4248
|
-
let text = self.text();
|
|
4249
|
-
while (textLength > width - 2 * padding && text.length > 0) {
|
|
4250
|
-
text = text.slice(0, -1);
|
|
4251
|
-
self.text(`${text}...`);
|
|
4252
|
-
textLength = self.node().getComputedTextLength();
|
|
4253
|
-
}
|
|
4254
|
-
}
|
|
4255
|
-
const useChartChange = ({ dataSources, chartId, width, height, relatedAttributes, defaultColor, fontColor, markers, showMarkers, }) => {
|
|
4256
|
-
const { t } = useGlobalContext();
|
|
4257
|
-
const { layerInfos } = useWidgetContext();
|
|
4258
|
-
const strokeColors = relatedAttributes
|
|
4259
|
-
.filter(({ chartAxis }) => chartAxis === "y")
|
|
4260
|
-
.map(({ axisColor }) => axisColor);
|
|
4261
|
-
const ref = React.useRef({
|
|
4262
|
-
path: null,
|
|
4263
|
-
area: null,
|
|
4264
|
-
points: [],
|
|
4223
|
+
const max = formatConditionValue({
|
|
4224
|
+
value: hasFilter ? filters[name].max : null,
|
|
4225
|
+
checkQuotes: !isSingle,
|
|
4226
|
+
isSetParams,
|
|
4265
4227
|
});
|
|
4266
|
-
const
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4228
|
+
const value = formatConditionValue({
|
|
4229
|
+
value: hasFilter ? filters[name].value : filters[name] === undefined ? defaultValue : "",
|
|
4230
|
+
defaultValue,
|
|
4231
|
+
checkQuotes: !isSingle,
|
|
4232
|
+
isSetParams,
|
|
4233
|
+
});
|
|
4234
|
+
const filterName = `${FILTER_PREFIX}${name}`;
|
|
4235
|
+
const hasMin = min !== "" && min !== null && min !== undefined;
|
|
4236
|
+
const hasMax = max !== "" && max !== null && max !== undefined;
|
|
4237
|
+
let result = condition;
|
|
4238
|
+
if (hasMin || hasMax) {
|
|
4239
|
+
if (hasMin) {
|
|
4240
|
+
result = result.replace(new RegExp(`${filterName}\\.min`), min);
|
|
4241
|
+
}
|
|
4242
|
+
if (hasMax) {
|
|
4243
|
+
result = result.replace(new RegExp(`${filterName}\\.max`), max);
|
|
4274
4244
|
}
|
|
4275
|
-
path && path.attr("d", lineGenerator(filteredPoints));
|
|
4276
|
-
area && area.attr("d", areaGenerator(height)(filteredPoints));
|
|
4277
|
-
}, [height, width]);
|
|
4278
|
-
const customize = React.useCallback(({ svg }) => {
|
|
4279
|
-
svg.style("overflow", "visible");
|
|
4280
|
-
svg
|
|
4281
|
-
.selectAll(`.${charts.lineChartClassNames.lineChartXScaleGlobal} line,
|
|
4282
|
-
.${charts.lineChartClassNames.lineChartYScaleGlobal} line,
|
|
4283
|
-
.domain`)
|
|
4284
|
-
.each((_, index, nodes) => {
|
|
4285
|
-
nodes[index].remove();
|
|
4286
|
-
});
|
|
4287
|
-
svg
|
|
4288
|
-
.selectAll(`.${charts.lineChartClassNames.lineChartXScaleGlobal} .tick`)
|
|
4289
|
-
.each((_, index, nodes) => {
|
|
4290
|
-
if (!index) {
|
|
4291
|
-
nodes[index].style.textAnchor = "start";
|
|
4292
|
-
}
|
|
4293
|
-
if (index === nodes.length - 1) {
|
|
4294
|
-
nodes[index].style.textAnchor = "end";
|
|
4295
|
-
}
|
|
4296
|
-
if (markers) {
|
|
4297
|
-
nodes[index].remove();
|
|
4298
|
-
}
|
|
4299
|
-
if (showMarkers) {
|
|
4300
|
-
if (index % showMarkers !== 0) {
|
|
4301
|
-
nodes[index].remove();
|
|
4302
|
-
}
|
|
4303
|
-
}
|
|
4304
|
-
else {
|
|
4305
|
-
if (index && index < nodes.length - 1) {
|
|
4306
|
-
nodes[index].remove();
|
|
4307
|
-
}
|
|
4308
|
-
}
|
|
4309
|
-
});
|
|
4310
|
-
svg
|
|
4311
|
-
.selectAll(`.${charts.lineChartClassNames.lineChartXScaleGlobal} .tick text`)
|
|
4312
|
-
.attr("y", 16);
|
|
4313
|
-
svg
|
|
4314
|
-
.selectAll(`.${charts.lineChartClassNames.lineChartYScaleGlobal} .tick text`)
|
|
4315
|
-
.text(item => {
|
|
4316
|
-
if (!item)
|
|
4317
|
-
return 0;
|
|
4318
|
-
const dataSource = dataSources?.find(({ name }) => name === relatedAttributes[0].dataSourceName);
|
|
4319
|
-
const layerInfo = dataSource
|
|
4320
|
-
? layerInfos.find(({ name }) => name === dataSource.layerName)
|
|
4321
|
-
: null;
|
|
4322
|
-
const attribute = layerInfo?.configuration?.attributesConfiguration?.attributes[relatedAttributes[0].attributeName];
|
|
4323
|
-
return attribute
|
|
4324
|
-
? formatAttributeValue({
|
|
4325
|
-
t,
|
|
4326
|
-
type: attribute.type,
|
|
4327
|
-
value: item,
|
|
4328
|
-
stringFormat: attribute.stringFormat,
|
|
4329
|
-
noUnits: true,
|
|
4330
|
-
})
|
|
4331
|
-
: item;
|
|
4332
|
-
})
|
|
4333
|
-
.each(wrap);
|
|
4334
|
-
svg.selectAll(".tick text").attr("style", `color: ${fontColor}`);
|
|
4335
|
-
const global = svg.select(`.${charts.lineChartClassNames.lineChartLinesGlobal}`);
|
|
4336
|
-
const lineChartLines = svg.selectAll(`.${charts.lineChartClassNames.lineChartLine}`);
|
|
4337
|
-
const defs = [];
|
|
4338
|
-
lineChartLines.each((_, index, nodes) => {
|
|
4339
|
-
const lineChartLine = nodes[index];
|
|
4340
|
-
const gradientId = lodash.uniqueId(`${chartId}-gradient-`);
|
|
4341
|
-
const color = strokeColors[index] || defaultColor;
|
|
4342
|
-
const newPath = global
|
|
4343
|
-
.append("path")
|
|
4344
|
-
.attr("stroke", color)
|
|
4345
|
-
.attr("stroke-width", "0")
|
|
4346
|
-
.attr("class", charts.lineChartClassNames.lineChartLine);
|
|
4347
|
-
const points = getLinePoints(+width, lineChartLine);
|
|
4348
|
-
const area = global
|
|
4349
|
-
.append("path")
|
|
4350
|
-
.attr("fill", `url(#${gradientId})`)
|
|
4351
|
-
.attr("stroke-width", "0")
|
|
4352
|
-
.attr("fill-opacity", FILL_OPACITY);
|
|
4353
|
-
defs.push(`
|
|
4354
|
-
<linearGradient id="${gradientId}" x1="0" y1="0" x2="0" y2="1">
|
|
4355
|
-
<stop offset="0" stop-color="${color}" stop-opacity="1" />
|
|
4356
|
-
<stop offset="1" stop-color="${color}" stop-opacity="0" />
|
|
4357
|
-
</linearGradient>
|
|
4358
|
-
`);
|
|
4359
|
-
ref.current = {
|
|
4360
|
-
path: newPath,
|
|
4361
|
-
area,
|
|
4362
|
-
points,
|
|
4363
|
-
};
|
|
4364
|
-
onChange();
|
|
4365
|
-
});
|
|
4366
|
-
svg.append("defs").html(() => defs.join(""));
|
|
4367
|
-
}, [
|
|
4368
|
-
fontColor,
|
|
4369
|
-
dataSources,
|
|
4370
|
-
layerInfos,
|
|
4371
|
-
relatedAttributes,
|
|
4372
|
-
chartId,
|
|
4373
|
-
strokeColors,
|
|
4374
|
-
defaultColor,
|
|
4375
|
-
width,
|
|
4376
|
-
onChange,
|
|
4377
|
-
showMarkers,
|
|
4378
|
-
markers,
|
|
4379
|
-
]);
|
|
4380
|
-
return [customize, onChange];
|
|
4381
|
-
};
|
|
4382
|
-
|
|
4383
|
-
const eqlParametersToPayload = (parameters) => Object.keys(parameters).reduce((result, paramName) => ({
|
|
4384
|
-
...result,
|
|
4385
|
-
[paramName]: parameters[paramName].default,
|
|
4386
|
-
}), {});
|
|
4387
|
-
|
|
4388
|
-
const addDataSource = (dashboardConfiguration, pageIndex, query, additional) => {
|
|
4389
|
-
const newConfig = JSON.parse(JSON.stringify(dashboardConfiguration));
|
|
4390
|
-
if (!newConfig.children[0].children[pageIndex].dataSources) {
|
|
4391
|
-
newConfig.children[0].children[pageIndex].dataSources = [];
|
|
4392
4245
|
}
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4246
|
+
else if (value) {
|
|
4247
|
+
result = result.replace(new RegExp(filterName), value);
|
|
4248
|
+
}
|
|
4249
|
+
return isSingle && isNumeric(result) ? Number(result) : result;
|
|
4250
|
+
};
|
|
4251
|
+
const applyVarsToCondition = ({ section, configFilters, filters, attributes, layerParams, eqlParameters, geometry, isSetParams, }) => {
|
|
4252
|
+
if (!section?.length)
|
|
4253
|
+
return [];
|
|
4254
|
+
const isSingle = typeof section === "string";
|
|
4255
|
+
const result = isSingle ? [section] : [...section];
|
|
4256
|
+
result.forEach((_, index) => {
|
|
4257
|
+
if (geometry && !geometry.includes("()") && geometry.endsWith(")")) {
|
|
4258
|
+
result[index] = result[index].replace(new RegExp("%geometry"), `'${geometry}'`);
|
|
4259
|
+
}
|
|
4260
|
+
if (configFilters?.length) {
|
|
4261
|
+
configFilters.forEach(filter => {
|
|
4262
|
+
result[index] = applyFiltersToCondition({
|
|
4263
|
+
filters,
|
|
4264
|
+
condition: result[index],
|
|
4265
|
+
name: filter.name,
|
|
4266
|
+
defaultValue: filter.defaultValue,
|
|
4267
|
+
isSetParams,
|
|
4268
|
+
isSingle: isSingle && !Array.isArray(filter.defaultValue),
|
|
4269
|
+
}).toString();
|
|
4270
|
+
});
|
|
4271
|
+
}
|
|
4272
|
+
if (attributes?.length) {
|
|
4273
|
+
attributes.forEach(({ attributeName, value, type: attributeType }) => {
|
|
4274
|
+
result[index] = result[index].replace(new RegExp(`{${attributeName}}`), formatConditionValue({ value: value?.toString(), attributeType, checkQuotes: !isSingle }));
|
|
4275
|
+
});
|
|
4276
|
+
}
|
|
4277
|
+
if (eqlParameters && layerParams) {
|
|
4278
|
+
Object.keys(eqlParameters).forEach(param => {
|
|
4279
|
+
result[index] = result[index].replace(new RegExp(`\\$\\(${param}=`), "***");
|
|
4280
|
+
result[index] = result[index].replace(new RegExp(param), formatConditionValue({ value: layerParams[param], checkQuotes: !isSingle }));
|
|
4281
|
+
result[index] = result[index].replace(new RegExp("\\*\\*\\*"), `$(${param}=`);
|
|
4282
|
+
});
|
|
4283
|
+
}
|
|
4401
4284
|
});
|
|
4402
|
-
return
|
|
4285
|
+
return isSingle ? result?.[0] : result;
|
|
4403
4286
|
};
|
|
4404
|
-
|
|
4405
|
-
const
|
|
4406
|
-
const
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
parameters: {},
|
|
4416
|
-
});
|
|
4287
|
+
const formatSingleCondition = (condition, { configFilters, filters, attributes, eqlParameters, layerParams, geometry }) => {
|
|
4288
|
+
const setParams = condition.match(new RegExp("\\$\\([^)]+\\)", "g"));
|
|
4289
|
+
const setParamsSection = applyVarsToCondition({
|
|
4290
|
+
section: setParams,
|
|
4291
|
+
configFilters,
|
|
4292
|
+
filters,
|
|
4293
|
+
attributes,
|
|
4294
|
+
eqlParameters,
|
|
4295
|
+
layerParams,
|
|
4296
|
+
geometry,
|
|
4297
|
+
isSetParams: true,
|
|
4417
4298
|
});
|
|
4418
|
-
|
|
4299
|
+
const splitter = " AND ";
|
|
4300
|
+
const setParamsLength = setParams?.join("").length || 0;
|
|
4301
|
+
const conditionSection = applyVarsToCondition({
|
|
4302
|
+
section: condition.substring(setParamsLength).split(splitter),
|
|
4303
|
+
configFilters,
|
|
4304
|
+
filters,
|
|
4305
|
+
attributes,
|
|
4306
|
+
eqlParameters,
|
|
4307
|
+
layerParams,
|
|
4308
|
+
geometry,
|
|
4309
|
+
});
|
|
4310
|
+
return setParamsSection?.length && conditionSection.length
|
|
4311
|
+
? [setParamsSection.join(""), conditionSection.join(splitter)].join(" ")
|
|
4312
|
+
: setParamsSection?.length
|
|
4313
|
+
? setParamsSection.join("")
|
|
4314
|
+
: conditionSection.join(splitter);
|
|
4315
|
+
};
|
|
4316
|
+
const formatDataSourceCondition = ({ condition, ...rest }) => {
|
|
4317
|
+
if (Array.isArray(condition)) {
|
|
4318
|
+
return condition.map(item => formatSingleCondition(item, rest));
|
|
4319
|
+
}
|
|
4320
|
+
if (!condition) {
|
|
4321
|
+
return "";
|
|
4322
|
+
}
|
|
4323
|
+
return formatSingleCondition(condition, rest);
|
|
4419
4324
|
};
|
|
4420
4325
|
|
|
4421
|
-
const
|
|
4326
|
+
const DashboardChipsContainer = styled(uilibGl.Flex) `
|
|
4327
|
+
flex-wrap: wrap;
|
|
4328
|
+
`;
|
|
4329
|
+
const DefaultChipColorMixin = styled.css `
|
|
4330
|
+
&& {
|
|
4331
|
+
color: ${({ theme: { palette } }) => palette.textPrimary};
|
|
4332
|
+
}
|
|
4422
4333
|
|
|
4423
|
-
|
|
4334
|
+
&& > * {
|
|
4335
|
+
color: ${({ theme: { palette } }) => palette.textPrimary};
|
|
4336
|
+
}
|
|
4424
4337
|
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
};
|
|
4338
|
+
&& span[kind]:after {
|
|
4339
|
+
color: ${({ theme: { palette } }) => palette.icon};
|
|
4340
|
+
}
|
|
4341
|
+
`;
|
|
4342
|
+
const CustomChipColorMixin = styled.css `
|
|
4343
|
+
&& {
|
|
4344
|
+
color: ${({ $fontColor }) => $fontColor};
|
|
4345
|
+
}
|
|
4434
4346
|
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
!Array.isArray(selectedFilters[filterName].value)
|
|
4439
|
-
? [selectedFilters[filterName].value]
|
|
4440
|
-
: selectedFilters?.[filterName]?.value) ?? defaultValue);
|
|
4441
|
-
};
|
|
4347
|
+
&& > * {
|
|
4348
|
+
color: ${({ $fontColor }) => $fontColor};
|
|
4349
|
+
}
|
|
4442
4350
|
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
if (lodash.isNil(cardValue))
|
|
4455
|
-
return result;
|
|
4456
|
-
return { ...result, [key]: cardValue };
|
|
4457
|
-
}
|
|
4458
|
-
if (provider === exports.ProviderPrefix.Left && layerName && fieldName && projectDataSources?.length) {
|
|
4459
|
-
const dataSource = projectDataSources.find(({ layerName: name }) => name === layerName);
|
|
4460
|
-
const leftValue = dataSource?.features?.[0]?.properties?.[fieldName] ?? null;
|
|
4461
|
-
if (lodash.isNil(leftValue))
|
|
4462
|
-
return result;
|
|
4463
|
-
return { ...result, [key]: leftValue };
|
|
4464
|
-
}
|
|
4465
|
-
return result;
|
|
4466
|
-
}
|
|
4467
|
-
if (typeof configParameters[key] === "string" && configParameters[key].includes("{") && attributes?.length) {
|
|
4468
|
-
const exactAttr = attributes.find(({ attributeName }) => configParameters[key] === `{${attributeName}}`);
|
|
4469
|
-
if (exactAttr) {
|
|
4470
|
-
return { ...result, [key]: exactAttr.value ?? "" };
|
|
4471
|
-
}
|
|
4472
|
-
let interpolated = configParameters[key];
|
|
4473
|
-
attributes.forEach(({ attributeName, value: attrValue }) => {
|
|
4474
|
-
interpolated = interpolated.replace(new RegExp(`\\{${attributeName}\\}`, "g"), attrValue?.toString() ?? "");
|
|
4475
|
-
});
|
|
4476
|
-
return { ...result, [key]: interpolated };
|
|
4477
|
-
}
|
|
4478
|
-
if (typeof configParameters[key] !== "string" || !configParameters[key].startsWith("%")) {
|
|
4479
|
-
return {
|
|
4480
|
-
...result,
|
|
4481
|
-
[key]: configParameters[key],
|
|
4482
|
-
};
|
|
4483
|
-
}
|
|
4484
|
-
const filterFullName = configParameters[key].replace("%", "");
|
|
4485
|
-
const [filterName, filterProp] = filterFullName.includes(".") ? filterFullName.split(".") : [filterFullName, null];
|
|
4486
|
-
const { defaultValue, relatedDataSource, attributeAlias } = getConfigFilter(filterName, configFilters) || {};
|
|
4487
|
-
if (filterName === "geometry" && geometry && !geometry.includes("()") && geometry.endsWith(")")) {
|
|
4488
|
-
return {
|
|
4489
|
-
...result,
|
|
4490
|
-
[key]: geometry,
|
|
4491
|
-
};
|
|
4492
|
-
}
|
|
4493
|
-
if (configParameters[key].endsWith(".max")) {
|
|
4494
|
-
return {
|
|
4495
|
-
...result,
|
|
4496
|
-
[key]: selectedFilters?.[filterName]?.max ?? (Array.isArray(defaultValue) ? defaultValue[1] : defaultValue),
|
|
4497
|
-
};
|
|
4498
|
-
}
|
|
4499
|
-
if (configParameters[key].endsWith(".min")) {
|
|
4500
|
-
return {
|
|
4501
|
-
...result,
|
|
4502
|
-
[key]: selectedFilters?.[filterName]?.min ?? (Array.isArray(defaultValue) ? defaultValue[0] : defaultValue),
|
|
4503
|
-
};
|
|
4504
|
-
}
|
|
4505
|
-
if (configParameters[key].includes(".")) {
|
|
4506
|
-
return {
|
|
4507
|
-
...result,
|
|
4508
|
-
[key]: getDataSourceFilterValue({
|
|
4509
|
-
filterName,
|
|
4510
|
-
filterProp,
|
|
4511
|
-
selectedFilters,
|
|
4512
|
-
attributeAlias,
|
|
4513
|
-
dataSource: getDataSource(relatedDataSource, dataSources),
|
|
4514
|
-
}) ?? defaultValue,
|
|
4515
|
-
};
|
|
4516
|
-
}
|
|
4517
|
-
const value = getSelectedFilterValue(filterName, selectedFilters, defaultValue);
|
|
4518
|
-
if (lodash.isNil(value)) {
|
|
4519
|
-
return result;
|
|
4520
|
-
}
|
|
4521
|
-
return {
|
|
4522
|
-
...result,
|
|
4523
|
-
[key]: value,
|
|
4524
|
-
};
|
|
4525
|
-
}, {});
|
|
4526
|
-
};
|
|
4351
|
+
&& span[kind]:after {
|
|
4352
|
+
color: ${({ $fontColor }) => $fontColor};
|
|
4353
|
+
}
|
|
4354
|
+
`;
|
|
4355
|
+
const DashboardChip$1 = styled(uilibGl.Chip) `
|
|
4356
|
+
margin: 0 0.25rem 0.25rem 0;
|
|
4357
|
+
background: ${({ $isDefault, $bgColor, theme: { palette } }) => $isDefault ? palette.element : $bgColor || palette.primary};
|
|
4358
|
+
border-radius: ${({ $radius, theme: { borderRadius } }) => $radius || borderRadius.medium};
|
|
4359
|
+
white-space: nowrap;
|
|
4360
|
+
font-size: ${({ $fontSize }) => $fontSize || "0.875rem"};
|
|
4361
|
+
color: ${({ theme: { palette } }) => palette.iconContrast};
|
|
4527
4362
|
|
|
4528
|
-
|
|
4363
|
+
> * {
|
|
4364
|
+
font-size: ${({ $fontSize }) => $fontSize || "0.875rem"};
|
|
4365
|
+
}
|
|
4529
4366
|
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
return (!!filter && !!child.options?.filterName && !dataSources?.some(({ name }) => name === filter.relatedDataSource));
|
|
4533
|
-
});
|
|
4367
|
+
span[kind] {
|
|
4368
|
+
height: 0.875rem;
|
|
4534
4369
|
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
opacity: 1,
|
|
4540
|
-
selectable: false,
|
|
4541
|
-
filterZoomTo: false,
|
|
4542
|
-
isVisible: true,
|
|
4543
|
-
});
|
|
4370
|
+
:after {
|
|
4371
|
+
font-size: 0.875rem;
|
|
4372
|
+
}
|
|
4373
|
+
}
|
|
4544
4374
|
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
const pageId = parseInt(page.id.replace(CONFIG_PAGE_ID, ""), 10);
|
|
4550
|
-
return Math.max(maxId, pageId);
|
|
4551
|
-
}, 0);
|
|
4552
|
-
return maxPageId + 1;
|
|
4553
|
-
};
|
|
4375
|
+
button {
|
|
4376
|
+
width: auto;
|
|
4377
|
+
padding: 0 0.5rem;
|
|
4378
|
+
}
|
|
4554
4379
|
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
return {
|
|
4559
|
-
id: `${CONFIG_PAGE_ID}${pageId}`,
|
|
4560
|
-
templateName: exports.ContainerTemplate.ContainersGroup,
|
|
4561
|
-
children: [],
|
|
4562
|
-
layers: [],
|
|
4563
|
-
dataSources: [],
|
|
4564
|
-
filters: [],
|
|
4565
|
-
tasks: [],
|
|
4566
|
-
style: {},
|
|
4567
|
-
options: {
|
|
4568
|
-
title: title || [defaultTitle, pageId].filter(Boolean).join(" "),
|
|
4569
|
-
position: position || [DEFAULT_LNG, DEFAULT_LAT],
|
|
4570
|
-
resolution: resolution || DEFAULT_ZOOM,
|
|
4571
|
-
baseMapName: baseMapName || DEFAULT_BASE_MAP,
|
|
4572
|
-
baseMapSettings: {},
|
|
4573
|
-
expandedLayers: true,
|
|
4574
|
-
// srid: srid || null,
|
|
4575
|
-
},
|
|
4576
|
-
};
|
|
4577
|
-
};
|
|
4380
|
+
${({ $isDefault }) => $isDefault && DefaultChipColorMixin}
|
|
4381
|
+
${({ $fontColor, $isDefault }) => !!$fontColor && !$isDefault && CustomChipColorMixin}
|
|
4382
|
+
`;
|
|
4578
4383
|
|
|
4579
|
-
const
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
emptyLayerDefinition.attributes,
|
|
4596
|
-
};
|
|
4597
|
-
};
|
|
4384
|
+
const LayerGroupContainer = styled(uilibGl.Flex) `
|
|
4385
|
+
display: flex;
|
|
4386
|
+
justify-content: center;
|
|
4387
|
+
position: relative;
|
|
4388
|
+
flex-direction: column;
|
|
4389
|
+
padding: 0 0.25rem 0 1rem;
|
|
4390
|
+
box-sizing: border-box;
|
|
4391
|
+
transition: opacity ${uilibGl.transition.hover}, background-color ${uilibGl.transition.hover};
|
|
4392
|
+
font-family: "NunitoSans", sans-serif;
|
|
4393
|
+
`;
|
|
4394
|
+
const LayerGroupMain = styled(uilibGl.Flex) `
|
|
4395
|
+
flex-direction: row;
|
|
4396
|
+
flex-wrap: nowrap;
|
|
4397
|
+
align-items: center;
|
|
4398
|
+
justify-content: space-between;
|
|
4399
|
+
width: 100%;
|
|
4598
4400
|
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4401
|
+
${uilibGl.Icon} {
|
|
4402
|
+
width: 2rem;
|
|
4403
|
+
min-width: 2rem;
|
|
4404
|
+
height: 2rem;
|
|
4405
|
+
display: inline-flex;
|
|
4406
|
+
align-items: center;
|
|
4407
|
+
justify-content: center;
|
|
4408
|
+
margin-right: 0.75rem;
|
|
4409
|
+
}
|
|
4605
4410
|
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
: typeof value === "string" && !isNumeric(value) && !checkIsDateFormat(value);
|
|
4615
|
-
};
|
|
4616
|
-
const formatConditionValue = ({ value, attributeType, defaultValue, checkQuotes = true, isSetParams = false, }) => {
|
|
4617
|
-
if (isEmptyValue(value))
|
|
4618
|
-
return "";
|
|
4619
|
-
const formattedValue = Array.isArray(defaultValue) && !Array.isArray(value) ? [value] : value;
|
|
4620
|
-
const isArray = Array.isArray(formattedValue);
|
|
4621
|
-
let stringValue = formattedValue.toString();
|
|
4622
|
-
if (isArray) {
|
|
4623
|
-
return formattedValue.length && !formattedValue.every(item => !item)
|
|
4624
|
-
? `[${formattedValue
|
|
4625
|
-
.map(item => (checkQuotes && checkIfNeedQuotes(item, attributeType) ? `'${item}'` : item))
|
|
4626
|
-
.join(",")}]`
|
|
4627
|
-
: "";
|
|
4628
|
-
}
|
|
4629
|
-
if (isSetParams && checkIsDateFormat(stringValue)) {
|
|
4630
|
-
stringValue = stringValue.slice(2, -1);
|
|
4631
|
-
}
|
|
4632
|
-
return checkQuotes && checkIfNeedQuotes(stringValue, attributeType) ? `'${stringValue}'` : stringValue;
|
|
4633
|
-
};
|
|
4634
|
-
|
|
4635
|
-
const applyFiltersToCondition = ({ condition, name, defaultValue, filters, isSingle, isSetParams, }) => {
|
|
4636
|
-
const hasFilter = filters[name] !== undefined && !!filters[name].value?.toString().length;
|
|
4637
|
-
const min = formatConditionValue({
|
|
4638
|
-
value: hasFilter ? filters[name].min : null,
|
|
4639
|
-
checkQuotes: !isSingle,
|
|
4640
|
-
isSetParams,
|
|
4641
|
-
});
|
|
4642
|
-
const max = formatConditionValue({
|
|
4643
|
-
value: hasFilter ? filters[name].max : null,
|
|
4644
|
-
checkQuotes: !isSingle,
|
|
4645
|
-
isSetParams,
|
|
4646
|
-
});
|
|
4647
|
-
const value = formatConditionValue({
|
|
4648
|
-
value: hasFilter ? filters[name].value : filters[name] === undefined ? defaultValue : "",
|
|
4649
|
-
defaultValue,
|
|
4650
|
-
checkQuotes: !isSingle,
|
|
4651
|
-
isSetParams,
|
|
4652
|
-
});
|
|
4653
|
-
const filterName = `${FILTER_PREFIX}${name}`;
|
|
4654
|
-
const hasMin = min !== "" && min !== null && min !== undefined;
|
|
4655
|
-
const hasMax = max !== "" && max !== null && max !== undefined;
|
|
4656
|
-
let result = condition;
|
|
4657
|
-
if (hasMin || hasMax) {
|
|
4658
|
-
if (hasMin) {
|
|
4659
|
-
result = result.replace(new RegExp(`${filterName}\\.min`), min);
|
|
4660
|
-
}
|
|
4661
|
-
if (hasMax) {
|
|
4662
|
-
result = result.replace(new RegExp(`${filterName}\\.max`), max);
|
|
4663
|
-
}
|
|
4664
|
-
}
|
|
4665
|
-
else if (value) {
|
|
4666
|
-
result = result.replace(new RegExp(filterName), value);
|
|
4667
|
-
}
|
|
4668
|
-
return isSingle && isNumeric(result) ? Number(result) : result;
|
|
4669
|
-
};
|
|
4670
|
-
const applyVarsToCondition = ({ section, configFilters, filters, attributes, layerParams, eqlParameters, geometry, isSetParams, }) => {
|
|
4671
|
-
if (!section?.length)
|
|
4672
|
-
return [];
|
|
4673
|
-
const isSingle = typeof section === "string";
|
|
4674
|
-
const result = isSingle ? [section] : [...section];
|
|
4675
|
-
result.forEach((_, index) => {
|
|
4676
|
-
if (geometry && !geometry.includes("()") && geometry.endsWith(")")) {
|
|
4677
|
-
result[index] = result[index].replace(new RegExp("%geometry"), `'${geometry}'`);
|
|
4678
|
-
}
|
|
4679
|
-
if (configFilters?.length) {
|
|
4680
|
-
configFilters.forEach(filter => {
|
|
4681
|
-
result[index] = applyFiltersToCondition({
|
|
4682
|
-
filters,
|
|
4683
|
-
condition: result[index],
|
|
4684
|
-
name: filter.name,
|
|
4685
|
-
defaultValue: filter.defaultValue,
|
|
4686
|
-
isSetParams,
|
|
4687
|
-
isSingle: isSingle && !Array.isArray(filter.defaultValue),
|
|
4688
|
-
}).toString();
|
|
4689
|
-
});
|
|
4690
|
-
}
|
|
4691
|
-
if (attributes?.length) {
|
|
4692
|
-
attributes.forEach(({ attributeName, value, type: attributeType }) => {
|
|
4693
|
-
result[index] = result[index].replace(new RegExp(`{${attributeName}}`), formatConditionValue({ value: value?.toString(), attributeType, checkQuotes: !isSingle }));
|
|
4694
|
-
});
|
|
4695
|
-
}
|
|
4696
|
-
if (eqlParameters && layerParams) {
|
|
4697
|
-
Object.keys(eqlParameters).forEach(param => {
|
|
4698
|
-
result[index] = result[index].replace(new RegExp(`\\$\\(${param}=`), "***");
|
|
4699
|
-
result[index] = result[index].replace(new RegExp(param), formatConditionValue({ value: layerParams[param], checkQuotes: !isSingle }));
|
|
4700
|
-
result[index] = result[index].replace(new RegExp("\\*\\*\\*"), `$(${param}=`);
|
|
4701
|
-
});
|
|
4702
|
-
}
|
|
4703
|
-
});
|
|
4704
|
-
return isSingle ? result?.[0] : result;
|
|
4705
|
-
};
|
|
4706
|
-
const formatSingleCondition = (condition, { configFilters, filters, attributes, eqlParameters, layerParams, geometry }) => {
|
|
4707
|
-
const setParams = condition.match(new RegExp("\\$\\([^)]+\\)", "g"));
|
|
4708
|
-
const setParamsSection = applyVarsToCondition({
|
|
4709
|
-
section: setParams,
|
|
4710
|
-
configFilters,
|
|
4711
|
-
filters,
|
|
4712
|
-
attributes,
|
|
4713
|
-
eqlParameters,
|
|
4714
|
-
layerParams,
|
|
4715
|
-
geometry,
|
|
4716
|
-
isSetParams: true,
|
|
4717
|
-
});
|
|
4718
|
-
const splitter = " AND ";
|
|
4719
|
-
const setParamsLength = setParams?.join("").length || 0;
|
|
4720
|
-
const conditionSection = applyVarsToCondition({
|
|
4721
|
-
section: condition.substring(setParamsLength).split(splitter),
|
|
4722
|
-
configFilters,
|
|
4723
|
-
filters,
|
|
4724
|
-
attributes,
|
|
4725
|
-
eqlParameters,
|
|
4726
|
-
layerParams,
|
|
4727
|
-
geometry,
|
|
4728
|
-
});
|
|
4729
|
-
return setParamsSection?.length && conditionSection.length
|
|
4730
|
-
? [setParamsSection.join(""), conditionSection.join(splitter)].join(" ")
|
|
4731
|
-
: setParamsSection?.length
|
|
4732
|
-
? setParamsSection.join("")
|
|
4733
|
-
: conditionSection.join(splitter);
|
|
4734
|
-
};
|
|
4735
|
-
const formatDataSourceCondition = ({ condition, ...rest }) => {
|
|
4736
|
-
if (Array.isArray(condition)) {
|
|
4737
|
-
return condition.map(item => formatSingleCondition(item, rest));
|
|
4738
|
-
}
|
|
4739
|
-
if (!condition) {
|
|
4740
|
-
return "";
|
|
4741
|
-
}
|
|
4742
|
-
return formatSingleCondition(condition, rest);
|
|
4743
|
-
};
|
|
4744
|
-
|
|
4745
|
-
const DashboardChipsContainer = styled(uilibGl.Flex) `
|
|
4746
|
-
flex-wrap: wrap;
|
|
4747
|
-
`;
|
|
4748
|
-
const DefaultChipColorMixin = styled.css `
|
|
4749
|
-
&& {
|
|
4750
|
-
color: ${({ theme: { palette } }) => palette.textPrimary};
|
|
4751
|
-
}
|
|
4752
|
-
|
|
4753
|
-
&& > * {
|
|
4754
|
-
color: ${({ theme: { palette } }) => palette.textPrimary};
|
|
4755
|
-
}
|
|
4756
|
-
|
|
4757
|
-
&& span[kind]:after {
|
|
4758
|
-
color: ${({ theme: { palette } }) => palette.icon};
|
|
4759
|
-
}
|
|
4760
|
-
`;
|
|
4761
|
-
const CustomChipColorMixin = styled.css `
|
|
4762
|
-
&& {
|
|
4763
|
-
color: ${({ $fontColor }) => $fontColor};
|
|
4764
|
-
}
|
|
4765
|
-
|
|
4766
|
-
&& > * {
|
|
4767
|
-
color: ${({ $fontColor }) => $fontColor};
|
|
4768
|
-
}
|
|
4769
|
-
|
|
4770
|
-
&& span[kind]:after {
|
|
4771
|
-
color: ${({ $fontColor }) => $fontColor};
|
|
4772
|
-
}
|
|
4773
|
-
`;
|
|
4774
|
-
const DashboardChip$1 = styled(uilibGl.Chip) `
|
|
4775
|
-
margin: 0 0.25rem 0.25rem 0;
|
|
4776
|
-
background: ${({ $isDefault, $bgColor, theme: { palette } }) => $isDefault ? palette.element : $bgColor || palette.primary};
|
|
4777
|
-
border-radius: ${({ $radius, theme: { borderRadius } }) => $radius || borderRadius.medium};
|
|
4778
|
-
white-space: nowrap;
|
|
4779
|
-
font-size: ${({ $fontSize }) => $fontSize || "0.875rem"};
|
|
4780
|
-
color: ${({ theme: { palette } }) => palette.iconContrast};
|
|
4781
|
-
|
|
4782
|
-
> * {
|
|
4783
|
-
font-size: ${({ $fontSize }) => $fontSize || "0.875rem"};
|
|
4784
|
-
}
|
|
4785
|
-
|
|
4786
|
-
span[kind] {
|
|
4787
|
-
height: 0.875rem;
|
|
4788
|
-
|
|
4789
|
-
:after {
|
|
4790
|
-
font-size: 0.875rem;
|
|
4791
|
-
}
|
|
4792
|
-
}
|
|
4793
|
-
|
|
4794
|
-
button {
|
|
4795
|
-
width: auto;
|
|
4796
|
-
padding: 0 0.5rem;
|
|
4797
|
-
}
|
|
4798
|
-
|
|
4799
|
-
${({ $isDefault }) => $isDefault && DefaultChipColorMixin}
|
|
4800
|
-
${({ $fontColor, $isDefault }) => !!$fontColor && !$isDefault && CustomChipColorMixin}
|
|
4801
|
-
`;
|
|
4802
|
-
|
|
4803
|
-
const LayerGroupContainer = styled(uilibGl.Flex) `
|
|
4804
|
-
display: flex;
|
|
4805
|
-
justify-content: center;
|
|
4806
|
-
position: relative;
|
|
4807
|
-
flex-direction: column;
|
|
4808
|
-
padding: 0 0.25rem 0 1rem;
|
|
4809
|
-
box-sizing: border-box;
|
|
4810
|
-
transition: opacity ${uilibGl.transition.hover}, background-color ${uilibGl.transition.hover};
|
|
4811
|
-
font-family: "NunitoSans", sans-serif;
|
|
4812
|
-
`;
|
|
4813
|
-
const LayerGroupMain = styled(uilibGl.Flex) `
|
|
4814
|
-
flex-direction: row;
|
|
4815
|
-
flex-wrap: nowrap;
|
|
4816
|
-
align-items: center;
|
|
4817
|
-
justify-content: space-between;
|
|
4818
|
-
width: 100%;
|
|
4819
|
-
|
|
4820
|
-
${uilibGl.Icon} {
|
|
4821
|
-
width: 2rem;
|
|
4822
|
-
min-width: 2rem;
|
|
4823
|
-
height: 2rem;
|
|
4824
|
-
display: inline-flex;
|
|
4825
|
-
align-items: center;
|
|
4826
|
-
justify-content: center;
|
|
4827
|
-
margin-right: 0.75rem;
|
|
4828
|
-
}
|
|
4829
|
-
|
|
4830
|
-
${uilibGl.Description} {
|
|
4831
|
-
display: flex;
|
|
4832
|
-
align-items: center;
|
|
4833
|
-
flex-grow: 1;
|
|
4834
|
-
width: 100%;
|
|
4835
|
-
margin-right: 0.25rem;
|
|
4836
|
-
color: ${({ theme }) => theme.palette.textPrimary};
|
|
4837
|
-
}
|
|
4411
|
+
${uilibGl.Description} {
|
|
4412
|
+
display: flex;
|
|
4413
|
+
align-items: center;
|
|
4414
|
+
flex-grow: 1;
|
|
4415
|
+
width: 100%;
|
|
4416
|
+
margin-right: 0.25rem;
|
|
4417
|
+
color: ${({ theme }) => theme.palette.textPrimary};
|
|
4418
|
+
}
|
|
4838
4419
|
|
|
4839
4420
|
button {
|
|
4840
4421
|
width: 2.25rem;
|
|
@@ -4971,41 +4552,193 @@ const customStyles = [
|
|
|
4971
4552
|
},
|
|
4972
4553
|
];
|
|
4973
4554
|
|
|
4974
|
-
const
|
|
4975
|
-
|
|
4976
|
-
};
|
|
4555
|
+
const DashboardContext = React.createContext({});
|
|
4556
|
+
const DashboardProvider = React.memo(({ children, ...props }) => {
|
|
4557
|
+
return jsxRuntime.jsx(DashboardContext.Provider, { value: props, children: children });
|
|
4558
|
+
});
|
|
4977
4559
|
|
|
4978
|
-
const
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
modes: customModes,
|
|
4982
|
-
defaultMode: "static",
|
|
4983
|
-
controls: {
|
|
4984
|
-
trash: true,
|
|
4985
|
-
},
|
|
4560
|
+
const FeatureCardContext = React.createContext({});
|
|
4561
|
+
const FeatureCardProvider = React.memo(({ children, ...props }) => {
|
|
4562
|
+
return jsxRuntime.jsx(FeatureCardContext.Provider, { value: props, children: children });
|
|
4986
4563
|
});
|
|
4987
|
-
const useMapDraw = (triggerDeps = []) => {
|
|
4988
|
-
const { map, draw: drawContext, loaded, basemapName } = useMapContext();
|
|
4989
|
-
React.useEffect(() => {
|
|
4990
|
-
if (!loaded || !map.current) {
|
|
4991
|
-
return;
|
|
4992
|
-
}
|
|
4993
|
-
drawContext.current = draw;
|
|
4994
|
-
map.current.addControl(drawContext.current);
|
|
4995
|
-
}, [loaded]); // eslint-disable-line
|
|
4996
|
-
React.useEffect(() => {
|
|
4997
|
-
if (map.current && map.current.hasControl(drawContext.current)) {
|
|
4998
|
-
map.current.removeControl(drawContext.current);
|
|
4999
|
-
map.current.addControl(drawContext.current);
|
|
5000
|
-
}
|
|
5001
|
-
}, [basemapName, ...triggerDeps]); // eslint-disable-line
|
|
5002
|
-
};
|
|
5003
4564
|
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
4565
|
+
const GlobalContext = React.createContext({});
|
|
4566
|
+
const GlobalProvider = React.memo(({ children, ...props }) => {
|
|
4567
|
+
return jsxRuntime.jsx(GlobalContext.Provider, { value: props, children: children });
|
|
4568
|
+
});
|
|
4569
|
+
|
|
4570
|
+
const MapContext = React.createContext({});
|
|
4571
|
+
|
|
4572
|
+
const MapProvider = ({ basemapItems, defaultBasemap, children }) => {
|
|
4573
|
+
const map = React.useRef();
|
|
4574
|
+
const draw = React.useRef();
|
|
4575
|
+
const [loaded, setLoaded] = React.useState(false);
|
|
4576
|
+
const [basemapName, setBasemapName] = React.useState(defaultBasemap);
|
|
4577
|
+
return (jsxRuntime.jsx(MapContext.Provider, { value: {
|
|
4578
|
+
map,
|
|
4579
|
+
draw,
|
|
4580
|
+
loaded,
|
|
4581
|
+
setLoaded,
|
|
4582
|
+
basemapItems,
|
|
4583
|
+
basemapName,
|
|
4584
|
+
setBasemapName,
|
|
4585
|
+
defaultBasemap,
|
|
4586
|
+
}, children: children }));
|
|
4587
|
+
};
|
|
4588
|
+
|
|
4589
|
+
exports.BaseMapTheme = void 0;
|
|
4590
|
+
(function (BaseMapTheme) {
|
|
4591
|
+
BaseMapTheme["Light"] = "light";
|
|
4592
|
+
BaseMapTheme["Dark"] = "dark";
|
|
4593
|
+
})(exports.BaseMapTheme || (exports.BaseMapTheme = {}));
|
|
4594
|
+
|
|
4595
|
+
const ServerNotificationsContext = React.createContext({});
|
|
4596
|
+
|
|
4597
|
+
const useServerNotifications = (url, initialized, apiClient) => {
|
|
4598
|
+
const hubConnection = React.useRef(null);
|
|
4599
|
+
const [connection, setConnection] = React.useState(null);
|
|
4600
|
+
const subscribeNotifications = React.useCallback(() => {
|
|
4601
|
+
if (!connection || connection.state !== "Connected") {
|
|
4602
|
+
return;
|
|
4603
|
+
}
|
|
4604
|
+
connection
|
|
4605
|
+
.invoke("SubscribeNotifications", [])
|
|
4606
|
+
.then(() => console.info("Подписка `SubscribeNotifications` оформлена"))
|
|
4607
|
+
.catch(err => console.info("Ошибка подписки `SubscribeNotifications`:", err));
|
|
4608
|
+
}, [connection]);
|
|
4609
|
+
React.useEffect(() => {
|
|
4610
|
+
if (!initialized) {
|
|
4611
|
+
return;
|
|
4612
|
+
}
|
|
4613
|
+
hubConnection.current = new signalr.HubConnectionBuilder()
|
|
4614
|
+
.withUrl(`${url}?clientId=${api.generateId()}`, {
|
|
4615
|
+
withCredentials: true,
|
|
4616
|
+
skipNegotiation: true,
|
|
4617
|
+
transport: signalr.HttpTransportType.WebSockets,
|
|
4618
|
+
accessTokenFactory: async () => {
|
|
4619
|
+
let accessToken = window.localStorage.getItem(api.STORAGE_TOKEN_KEY) || "";
|
|
4620
|
+
const { exp } = api.parseJwt(accessToken);
|
|
4621
|
+
const currentTime = new Date().getTime() / 1000;
|
|
4622
|
+
if (currentTime > exp) {
|
|
4623
|
+
const refreshToken = window.localStorage.getItem(api.STORAGE_REFRESH_TOKEN_KEY);
|
|
4624
|
+
if (refreshToken) {
|
|
4625
|
+
const refreshTokenResponse = await apiClient.account.refreshToken({
|
|
4626
|
+
refreshToken,
|
|
4627
|
+
});
|
|
4628
|
+
if (refreshTokenResponse) {
|
|
4629
|
+
accessToken = refreshTokenResponse.token;
|
|
4630
|
+
window.localStorage.setItem(api.STORAGE_TOKEN_KEY, refreshTokenResponse.token);
|
|
4631
|
+
window.localStorage.setItem(api.STORAGE_REFRESH_TOKEN_KEY, refreshTokenResponse.refreshToken);
|
|
4632
|
+
}
|
|
4633
|
+
}
|
|
4634
|
+
else {
|
|
4635
|
+
await apiClient.logout();
|
|
4636
|
+
}
|
|
4637
|
+
}
|
|
4638
|
+
return accessToken;
|
|
4639
|
+
},
|
|
4640
|
+
})
|
|
4641
|
+
.withAutomaticReconnect()
|
|
4642
|
+
.configureLogging(signalr.LogLevel.Information)
|
|
4643
|
+
.build();
|
|
4644
|
+
hubConnection.current
|
|
4645
|
+
.start()
|
|
4646
|
+
.then(() => console.info("Серверные нотификации подключены"))
|
|
4647
|
+
.catch(err => console.info("Ошибка:", err))
|
|
4648
|
+
.finally(() => setConnection(hubConnection.current));
|
|
4649
|
+
}, [initialized]); // eslint-disable-line
|
|
4650
|
+
React.useEffect(() => {
|
|
4651
|
+
if (!connection || connection.state !== "Connected") {
|
|
4652
|
+
return;
|
|
4653
|
+
}
|
|
4654
|
+
connection.onreconnecting(() => console.info("Переподключение к серверным нотификациям"));
|
|
4655
|
+
connection.onreconnected(subscribeNotifications);
|
|
4656
|
+
subscribeNotifications();
|
|
4657
|
+
}, [connection]);
|
|
4658
|
+
return connection;
|
|
4659
|
+
};
|
|
4660
|
+
|
|
4661
|
+
const ServerNotificationsProvider = ({ url, initialized, apiClient, children }) => {
|
|
4662
|
+
const connection = useServerNotifications(url, initialized, apiClient);
|
|
4663
|
+
const addSubscription = React.useCallback(async (payload) => {
|
|
4664
|
+
if (!connection || connection.state !== "Connected" || !payload) {
|
|
4665
|
+
return;
|
|
4666
|
+
}
|
|
4667
|
+
try {
|
|
4668
|
+
const id = await connection.invoke("AddSubscription", payload);
|
|
4669
|
+
console.info("Подписка добавлена, id:", id);
|
|
4670
|
+
return id;
|
|
4671
|
+
}
|
|
4672
|
+
catch (err) {
|
|
4673
|
+
console.info("Ошибка добавления подписки:", err);
|
|
4674
|
+
return Promise.resolve(null);
|
|
4675
|
+
}
|
|
4676
|
+
}, [connection]);
|
|
4677
|
+
const updateSubscription = React.useCallback(async (id, payload) => {
|
|
4678
|
+
if (!connection || connection.state !== "Connected" || !id || !payload) {
|
|
4679
|
+
return;
|
|
4680
|
+
}
|
|
4681
|
+
try {
|
|
4682
|
+
await connection.invoke("UpdateSubscription", id, payload);
|
|
4683
|
+
}
|
|
4684
|
+
catch (err) {
|
|
4685
|
+
console.info(`Ошибка обновления подписки ${id}:`, err);
|
|
4686
|
+
}
|
|
4687
|
+
}, [connection]);
|
|
4688
|
+
const unsubscribeById = React.useCallback(async (id) => {
|
|
4689
|
+
if (!connection || connection.state !== "Connected" || !id) {
|
|
4690
|
+
return;
|
|
4691
|
+
}
|
|
4692
|
+
try {
|
|
4693
|
+
await connection.invoke("Unsubscribe", [id]);
|
|
4694
|
+
}
|
|
4695
|
+
catch (err) {
|
|
4696
|
+
console.info(`Ошибка отписки по ${id}:`, err);
|
|
4697
|
+
}
|
|
4698
|
+
}, [connection]);
|
|
4699
|
+
return (jsxRuntime.jsx(ServerNotificationsContext.Provider, { value: {
|
|
4700
|
+
connection,
|
|
4701
|
+
addSubscription,
|
|
4702
|
+
updateSubscription,
|
|
4703
|
+
unsubscribeById,
|
|
4704
|
+
}, children: children }));
|
|
4705
|
+
};
|
|
4706
|
+
|
|
4707
|
+
const useMapContext = () => {
|
|
4708
|
+
return React.useContext(MapContext);
|
|
4709
|
+
};
|
|
4710
|
+
|
|
4711
|
+
const draw = new MapboxDraw({
|
|
4712
|
+
displayControlsDefault: false,
|
|
4713
|
+
styles: customStyles,
|
|
4714
|
+
modes: customModes,
|
|
4715
|
+
defaultMode: "static",
|
|
4716
|
+
controls: {
|
|
4717
|
+
trash: true,
|
|
4718
|
+
},
|
|
4719
|
+
});
|
|
4720
|
+
const useMapDraw = (triggerDeps = []) => {
|
|
4721
|
+
const { map, draw: drawContext, loaded, basemapName } = useMapContext();
|
|
4722
|
+
React.useEffect(() => {
|
|
4723
|
+
if (!loaded || !map.current) {
|
|
4724
|
+
return;
|
|
4725
|
+
}
|
|
4726
|
+
drawContext.current = draw;
|
|
4727
|
+
map.current.addControl(drawContext.current);
|
|
4728
|
+
}, [loaded]); // eslint-disable-line
|
|
4729
|
+
React.useEffect(() => {
|
|
4730
|
+
if (map.current && map.current.hasControl(drawContext.current)) {
|
|
4731
|
+
map.current.removeControl(drawContext.current);
|
|
4732
|
+
map.current.addControl(drawContext.current);
|
|
4733
|
+
}
|
|
4734
|
+
}, [basemapName, ...triggerDeps]); // eslint-disable-line
|
|
4735
|
+
};
|
|
4736
|
+
|
|
4737
|
+
/**
|
|
4738
|
+
* Определяет, является ли URL ссылкой на SVG файл.
|
|
4739
|
+
*/
|
|
4740
|
+
const isSvgUrl = (url) => {
|
|
4741
|
+
const lowercaseUrl = url.toLowerCase();
|
|
5009
4742
|
return lowercaseUrl.endsWith(".svg") || lowercaseUrl.startsWith("data:image/svg");
|
|
5010
4743
|
};
|
|
5011
4744
|
/**
|
|
@@ -5385,6 +5118,7 @@ const useZoomToFeatures = () => {
|
|
|
5385
5118
|
map.current.fitBounds([minX, minY, maxX, maxY], {
|
|
5386
5119
|
...options,
|
|
5387
5120
|
padding: options?.padding ?? 150,
|
|
5121
|
+
maxZoom: options?.maxZoom ?? SINGLE_FEATURE_FALLBACK_ZOOM,
|
|
5388
5122
|
});
|
|
5389
5123
|
}, [map]);
|
|
5390
5124
|
};
|
|
@@ -6338,71 +6072,12 @@ const TwoColumnContainerWrapper = styled(uilibGl.Flex) `
|
|
|
6338
6072
|
}
|
|
6339
6073
|
`;
|
|
6340
6074
|
|
|
6341
|
-
const useRenderContainerItem = (type, renderElement) => {
|
|
6342
|
-
const { config, layerInfo, selectedTabId, attributes } = useWidgetContext(type);
|
|
6343
|
-
return React.useCallback((elementConfig, attribute) => {
|
|
6344
|
-
const { id, options, style, children } = elementConfig || {};
|
|
6345
|
-
const { hideEmpty, innerTemplateStyle } = options || {};
|
|
6346
|
-
const hasUnits = children?.some(item => item.id === "units");
|
|
6347
|
-
const iconIndex = children?.findIndex(item => item.id === "icon");
|
|
6348
|
-
const icon = children?.[iconIndex];
|
|
6349
|
-
const hasIcon = !!icon;
|
|
6350
|
-
const elementChildren = elementConfig?.children?.map(child => ({
|
|
6351
|
-
type: "attributeValue",
|
|
6352
|
-
...child,
|
|
6353
|
-
attributeName: attribute,
|
|
6354
|
-
options: { noUnits: hasUnits, ...child.options },
|
|
6355
|
-
}));
|
|
6356
|
-
const attr = attribute
|
|
6357
|
-
? layerInfo?.configuration?.attributesConfiguration?.attributes?.find(({ attributeName }) => attributeName === attribute)
|
|
6358
|
-
: null;
|
|
6359
|
-
if (hasIcon) {
|
|
6360
|
-
elementChildren[iconIndex] = {
|
|
6361
|
-
...elementChildren[iconIndex],
|
|
6362
|
-
type: attr?.icon?.type?.toLowerCase(),
|
|
6363
|
-
value: attr?.icon?.resourceId || attr?.icon?.url || attr?.icon?.iconName,
|
|
6364
|
-
attributeName: null,
|
|
6365
|
-
};
|
|
6366
|
-
}
|
|
6367
|
-
const render = attribute
|
|
6368
|
-
? getRenderElement({
|
|
6369
|
-
config,
|
|
6370
|
-
elementConfig: {
|
|
6371
|
-
...elementConfig,
|
|
6372
|
-
children: elementChildren,
|
|
6373
|
-
},
|
|
6374
|
-
selectedTabId,
|
|
6375
|
-
attributes,
|
|
6376
|
-
layerInfo,
|
|
6377
|
-
type,
|
|
6378
|
-
})
|
|
6379
|
-
: renderElement;
|
|
6380
|
-
const value = render({ id: "value" });
|
|
6381
|
-
return {
|
|
6382
|
-
id,
|
|
6383
|
-
value,
|
|
6384
|
-
hideEmpty,
|
|
6385
|
-
style: innerTemplateStyle || style,
|
|
6386
|
-
hasIcon,
|
|
6387
|
-
hasUnits,
|
|
6388
|
-
render,
|
|
6389
|
-
};
|
|
6390
|
-
}, [config, layerInfo, selectedTabId, attributes, type, renderElement]);
|
|
6391
|
-
};
|
|
6392
|
-
|
|
6393
6075
|
const OneColumnContainer = React.memo(({ type, elementConfig, renderElement }) => {
|
|
6394
|
-
const getRenderContainerItem =
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
if (!optionAttributes)
|
|
6400
|
-
return null;
|
|
6401
|
-
if (optionAttributes.length === 0) {
|
|
6402
|
-
return contextAttributes?.map(({ attributeName }) => attributeName) ?? [];
|
|
6403
|
-
}
|
|
6404
|
-
return optionAttributes;
|
|
6405
|
-
}, [optionAttributes, contextAttributes]);
|
|
6076
|
+
const { getRenderContainerItem, attributesToRender } = useContainerAttributes({
|
|
6077
|
+
elementConfig,
|
|
6078
|
+
type,
|
|
6079
|
+
renderElement,
|
|
6080
|
+
});
|
|
6406
6081
|
const renderContainer = React.useCallback((attribute) => {
|
|
6407
6082
|
const { id, value, hideEmpty, style, hasUnits, render } = getRenderContainerItem(elementConfig, attribute);
|
|
6408
6083
|
if (!value && hideEmpty)
|
|
@@ -6413,18 +6088,11 @@ const OneColumnContainer = React.memo(({ type, elementConfig, renderElement }) =
|
|
|
6413
6088
|
});
|
|
6414
6089
|
|
|
6415
6090
|
const TwoColumnContainer = React.memo(({ elementConfig, type, renderElement }) => {
|
|
6416
|
-
const getRenderContainerItem =
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
if (!renderAttributes)
|
|
6422
|
-
return null;
|
|
6423
|
-
if (renderAttributes.length === 0) {
|
|
6424
|
-
return contextAttributes?.map(({ attributeName }) => attributeName) ?? [];
|
|
6425
|
-
}
|
|
6426
|
-
return renderAttributes;
|
|
6427
|
-
}, [renderAttributes, contextAttributes]);
|
|
6091
|
+
const { getRenderContainerItem, attributesToRender } = useContainerAttributes({
|
|
6092
|
+
elementConfig,
|
|
6093
|
+
type,
|
|
6094
|
+
renderElement,
|
|
6095
|
+
});
|
|
6428
6096
|
const renderContainer = React.useCallback((attribute) => {
|
|
6429
6097
|
const { id, value, hideEmpty, style, hasIcon, hasUnits, render } = getRenderContainerItem(elementConfig, attribute);
|
|
6430
6098
|
if (!value && hideEmpty)
|
|
@@ -7739,14 +7407,51 @@ const EditGroupContainer = React.memo(({ type, elementConfig, renderElement }) =
|
|
|
7739
7407
|
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: controls.map(({ targetAttributeName }) => renderContainer(targetAttributeName)) }));
|
|
7740
7408
|
});
|
|
7741
7409
|
|
|
7742
|
-
const
|
|
7743
|
-
const {
|
|
7744
|
-
const {
|
|
7745
|
-
|
|
7746
|
-
|
|
7747
|
-
|
|
7748
|
-
|
|
7749
|
-
|
|
7410
|
+
const useWidgetContext = (type = exports.WidgetType.Dashboard) => {
|
|
7411
|
+
const { toggleLayersVisibility, visibleLayers, projectInfo, updateProject, layerInfos, geometryFilter, dashboardLayers, setDashboardLayer, components: dashboardComponents, config: dashboardConfig, containerIds, pageIndex: projectPageIndex, selectedTabId: projectSelectedTabId, setSelectedTabId: setProjectSelectedTabId, dataSources: projectDataSources, loading: projectLoading, editMode: projectEditMode, filters: projectFilters, changeFilters: projectChangeFilters, expandContainer: projectExpandContainer, expandedContainers: projectExpandedContainers, nextPage: projectNextPage, prevPage: projectPrevPage, changePage: projectChangePage, } = React.useContext(DashboardContext) || {};
|
|
7412
|
+
const { layerInfo, attributes, feature, controls, changeControls, closeFeatureCard, config: featureConfig, pageIndex: featurePageIndex, selectedTabId: featureSelectedTabId, setSelectedTabId: setFeatureSelectedTabId, dataSources: featureDataSources, loading: featureLoading, editMode: featureEditMode, filters: featureFilters, changeFilters: featureChangeFilters, expandContainer: featureExpandContainer, expandedContainers: featureExpandedContainers, nextPage: featureNextPage, prevPage: featurePrevPage, changePage: featureChangePage, } = React.useContext(FeatureCardContext) || {};
|
|
7413
|
+
return {
|
|
7414
|
+
toggleLayersVisibility,
|
|
7415
|
+
visibleLayers,
|
|
7416
|
+
projectInfo,
|
|
7417
|
+
layerInfos,
|
|
7418
|
+
updateProject,
|
|
7419
|
+
dashboardLayers,
|
|
7420
|
+
setDashboardLayer,
|
|
7421
|
+
geometryFilter,
|
|
7422
|
+
layerInfo,
|
|
7423
|
+
attributes,
|
|
7424
|
+
feature,
|
|
7425
|
+
closeFeatureCard,
|
|
7426
|
+
containerIds,
|
|
7427
|
+
controls,
|
|
7428
|
+
changeControls,
|
|
7429
|
+
components: dashboardComponents,
|
|
7430
|
+
config: type === exports.WidgetType.Dashboard ? dashboardConfig : featureConfig,
|
|
7431
|
+
isEditing: type === exports.WidgetType.Dashboard ? projectEditMode : featureEditMode,
|
|
7432
|
+
isLoading: type === exports.WidgetType.Dashboard ? projectLoading : featureLoading,
|
|
7433
|
+
pageIndex: type === exports.WidgetType.Dashboard ? projectPageIndex || 1 : featurePageIndex || 1,
|
|
7434
|
+
filters: type === exports.WidgetType.Dashboard ? projectFilters : featureFilters,
|
|
7435
|
+
changeFilters: type === exports.WidgetType.Dashboard ? projectChangeFilters : featureChangeFilters,
|
|
7436
|
+
dataSources: type === exports.WidgetType.Dashboard ? projectDataSources : featureDataSources,
|
|
7437
|
+
expandContainer: type === exports.WidgetType.Dashboard ? projectExpandContainer : featureExpandContainer,
|
|
7438
|
+
expandedContainers: type === exports.WidgetType.Dashboard ? projectExpandedContainers : featureExpandedContainers,
|
|
7439
|
+
selectedTabId: type === exports.WidgetType.Dashboard ? projectSelectedTabId : featureSelectedTabId,
|
|
7440
|
+
setSelectedTabId: type === exports.WidgetType.Dashboard ? setProjectSelectedTabId : setFeatureSelectedTabId,
|
|
7441
|
+
nextPage: type === exports.WidgetType.Dashboard ? projectNextPage : featureNextPage,
|
|
7442
|
+
prevPage: type === exports.WidgetType.Dashboard ? projectPrevPage : featurePrevPage,
|
|
7443
|
+
changePage: type === exports.WidgetType.Dashboard ? projectChangePage : featureChangePage,
|
|
7444
|
+
};
|
|
7445
|
+
};
|
|
7446
|
+
|
|
7447
|
+
const useEditControl = (type, elementConfig) => {
|
|
7448
|
+
const { attributes, controls, dataSources, changeControls } = useWidgetContext(type);
|
|
7449
|
+
const { children, options } = elementConfig || {};
|
|
7450
|
+
const { controls: controlsOption } = options || {};
|
|
7451
|
+
const valueElement = React.useMemo(() => children.find(({ id }) => id === "value"), [children]);
|
|
7452
|
+
const control = React.useMemo(() => controlsOption?.find(item => item.targetAttributeName === valueElement.attributeName), [controlsOption, valueElement.attributeName]);
|
|
7453
|
+
const attributeName = (control?.targetAttributeName ?? valueElement?.attributeName);
|
|
7454
|
+
const value = React.useMemo(() => {
|
|
7750
7455
|
const currentValue = controls[attributeName] === undefined
|
|
7751
7456
|
? attributes.find(({ attributeName: name }) => name === attributeName)?.value
|
|
7752
7457
|
: controls[attributeName];
|
|
@@ -10773,6 +10478,307 @@ const tooltipValueFromRelatedFeatures = (t, value, relatedAttributes, layerInfo)
|
|
|
10773
10478
|
return formatChartRelatedValue(t, value, layerInfo, relatedAttributes);
|
|
10774
10479
|
};
|
|
10775
10480
|
|
|
10481
|
+
const useRenderContainerItem = (type, renderElement) => {
|
|
10482
|
+
const { config, layerInfo, selectedTabId, attributes } = useWidgetContext(type);
|
|
10483
|
+
return React.useCallback((elementConfig, attribute) => {
|
|
10484
|
+
const { id, options, style, children } = elementConfig || {};
|
|
10485
|
+
const { hideEmpty, innerTemplateStyle } = options || {};
|
|
10486
|
+
const hasUnits = children?.some(item => item.id === "units");
|
|
10487
|
+
const iconIndex = children?.findIndex(item => item.id === "icon");
|
|
10488
|
+
const icon = children?.[iconIndex];
|
|
10489
|
+
const hasIcon = !!icon;
|
|
10490
|
+
const elementChildren = elementConfig?.children?.map(child => ({
|
|
10491
|
+
type: "attributeValue",
|
|
10492
|
+
...child,
|
|
10493
|
+
attributeName: attribute,
|
|
10494
|
+
options: { noUnits: hasUnits, ...child.options },
|
|
10495
|
+
}));
|
|
10496
|
+
const attr = attribute
|
|
10497
|
+
? layerInfo?.configuration?.attributesConfiguration?.attributes?.find(({ attributeName }) => attributeName === attribute)
|
|
10498
|
+
: null;
|
|
10499
|
+
if (hasIcon) {
|
|
10500
|
+
elementChildren[iconIndex] = {
|
|
10501
|
+
...elementChildren[iconIndex],
|
|
10502
|
+
type: attr?.icon?.type?.toLowerCase(),
|
|
10503
|
+
value: attr?.icon?.resourceId || attr?.icon?.url || attr?.icon?.iconName,
|
|
10504
|
+
attributeName: null,
|
|
10505
|
+
};
|
|
10506
|
+
}
|
|
10507
|
+
const render = attribute
|
|
10508
|
+
? getRenderElement({
|
|
10509
|
+
config,
|
|
10510
|
+
elementConfig: {
|
|
10511
|
+
...elementConfig,
|
|
10512
|
+
children: elementChildren,
|
|
10513
|
+
},
|
|
10514
|
+
selectedTabId,
|
|
10515
|
+
attributes,
|
|
10516
|
+
layerInfo,
|
|
10517
|
+
type,
|
|
10518
|
+
})
|
|
10519
|
+
: renderElement;
|
|
10520
|
+
const value = render({ id: "value" });
|
|
10521
|
+
return {
|
|
10522
|
+
id,
|
|
10523
|
+
value,
|
|
10524
|
+
hideEmpty,
|
|
10525
|
+
style: innerTemplateStyle || style,
|
|
10526
|
+
hasIcon,
|
|
10527
|
+
hasUnits,
|
|
10528
|
+
render,
|
|
10529
|
+
};
|
|
10530
|
+
}, [config, layerInfo, selectedTabId, attributes, type, renderElement]);
|
|
10531
|
+
};
|
|
10532
|
+
|
|
10533
|
+
const useContainerAttributes = ({ elementConfig, type, renderElement }) => {
|
|
10534
|
+
const getRenderContainerItem = useRenderContainerItem(type, renderElement);
|
|
10535
|
+
const { options } = elementConfig || {};
|
|
10536
|
+
const { attributes: optionAttributes, useProjectHiddenAttributes } = options || {};
|
|
10537
|
+
const { attributes: contextAttributes, layerInfo } = useWidgetContext(type);
|
|
10538
|
+
const [hiddenAttributes] = useLayerHiddenAttributes(layerInfo?.name ?? "");
|
|
10539
|
+
const attributesToRender = React.useMemo(() => {
|
|
10540
|
+
if (!optionAttributes)
|
|
10541
|
+
return null;
|
|
10542
|
+
const baseList = optionAttributes.length === 0
|
|
10543
|
+
? contextAttributes?.map(({ attributeName }) => attributeName) ?? []
|
|
10544
|
+
: optionAttributes;
|
|
10545
|
+
if (!useProjectHiddenAttributes)
|
|
10546
|
+
return baseList;
|
|
10547
|
+
return baseList.filter(attribute => !hiddenAttributes.includes(attribute));
|
|
10548
|
+
}, [optionAttributes, contextAttributes, hiddenAttributes, useProjectHiddenAttributes]);
|
|
10549
|
+
return { getRenderContainerItem, attributesToRender };
|
|
10550
|
+
};
|
|
10551
|
+
|
|
10552
|
+
const useFetchWithAuth = (url, transform, cleanup) => {
|
|
10553
|
+
const [data, setData] = React.useState(null);
|
|
10554
|
+
const loadingRef = React.useRef(false);
|
|
10555
|
+
const transformRef = React.useRef(transform);
|
|
10556
|
+
const cleanupRef = React.useRef(cleanup);
|
|
10557
|
+
transformRef.current = transform;
|
|
10558
|
+
cleanupRef.current = cleanup;
|
|
10559
|
+
const fetchData = React.useCallback(() => {
|
|
10560
|
+
if (!url || loadingRef.current)
|
|
10561
|
+
return;
|
|
10562
|
+
loadingRef.current = true;
|
|
10563
|
+
const token = window.localStorage.getItem(api.STORAGE_TOKEN_KEY);
|
|
10564
|
+
fetch(url, {
|
|
10565
|
+
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
|
10566
|
+
})
|
|
10567
|
+
.then(res => (res.ok ? transformRef.current(res) : null))
|
|
10568
|
+
.then(setData)
|
|
10569
|
+
.catch(() => {
|
|
10570
|
+
setData(null);
|
|
10571
|
+
})
|
|
10572
|
+
.finally(() => {
|
|
10573
|
+
loadingRef.current = false;
|
|
10574
|
+
});
|
|
10575
|
+
}, [url]);
|
|
10576
|
+
React.useEffect(() => {
|
|
10577
|
+
if (url) {
|
|
10578
|
+
fetchData();
|
|
10579
|
+
}
|
|
10580
|
+
else {
|
|
10581
|
+
setData(null);
|
|
10582
|
+
}
|
|
10583
|
+
}, [url]);
|
|
10584
|
+
React.useEffect(() => () => {
|
|
10585
|
+
if (data !== null)
|
|
10586
|
+
cleanupRef.current?.(data);
|
|
10587
|
+
}, [data]);
|
|
10588
|
+
return data;
|
|
10589
|
+
};
|
|
10590
|
+
|
|
10591
|
+
const toObjectUrl = (res) => res.blob().then(blob => URL.createObjectURL(blob));
|
|
10592
|
+
const useFetchImageWithAuth = (url) => useFetchWithAuth(url, toObjectUrl, URL.revokeObjectURL);
|
|
10593
|
+
|
|
10594
|
+
const useGlobalContext = () => {
|
|
10595
|
+
const { t, language, themeName, api, ewktGeometry } = React.useContext(GlobalContext) || {};
|
|
10596
|
+
const translate = React.useCallback((value, options) => {
|
|
10597
|
+
if (t)
|
|
10598
|
+
return t(value, options);
|
|
10599
|
+
return options?.defaultValue ?? value;
|
|
10600
|
+
}, [t]);
|
|
10601
|
+
return React.useMemo(() => ({
|
|
10602
|
+
t: translate,
|
|
10603
|
+
language,
|
|
10604
|
+
themeName,
|
|
10605
|
+
api,
|
|
10606
|
+
ewktGeometry,
|
|
10607
|
+
}), [language, translate, api, ewktGeometry, themeName]);
|
|
10608
|
+
};
|
|
10609
|
+
|
|
10610
|
+
const HEIGHT_OFFSET = 20;
|
|
10611
|
+
const FILL_OPACITY = 0.28;
|
|
10612
|
+
const lineGenerator = line()
|
|
10613
|
+
.x(d => d[0])
|
|
10614
|
+
.y(d => d[1])
|
|
10615
|
+
.curve(monotoneX);
|
|
10616
|
+
const areaGenerator = (height) => area()
|
|
10617
|
+
.defined(d => d !== null)
|
|
10618
|
+
.x(d => d[0])
|
|
10619
|
+
.y0(height - HEIGHT_OFFSET)
|
|
10620
|
+
.y1(d => d[1])
|
|
10621
|
+
.curve(monotoneX);
|
|
10622
|
+
function getLinePoints(numPoints, svgLine) {
|
|
10623
|
+
if (!svgLine?.getTotalLength) {
|
|
10624
|
+
return [];
|
|
10625
|
+
}
|
|
10626
|
+
const lineLength = svgLine.getTotalLength();
|
|
10627
|
+
let interval;
|
|
10628
|
+
if (numPoints === 1) {
|
|
10629
|
+
interval = 0;
|
|
10630
|
+
}
|
|
10631
|
+
else {
|
|
10632
|
+
interval = lineLength / (numPoints - 1);
|
|
10633
|
+
}
|
|
10634
|
+
return range(numPoints)
|
|
10635
|
+
.filter(d => d * interval)
|
|
10636
|
+
.map(d => {
|
|
10637
|
+
const value = d * interval;
|
|
10638
|
+
const { x, y } = svgLine.getPointAtLength(value);
|
|
10639
|
+
return [x, y];
|
|
10640
|
+
});
|
|
10641
|
+
}
|
|
10642
|
+
function wrap() {
|
|
10643
|
+
const width = 80;
|
|
10644
|
+
const padding = 10;
|
|
10645
|
+
const self = select(this);
|
|
10646
|
+
let textLength = self.node().getComputedTextLength();
|
|
10647
|
+
let text = self.text();
|
|
10648
|
+
while (textLength > width - 2 * padding && text.length > 0) {
|
|
10649
|
+
text = text.slice(0, -1);
|
|
10650
|
+
self.text(`${text}...`);
|
|
10651
|
+
textLength = self.node().getComputedTextLength();
|
|
10652
|
+
}
|
|
10653
|
+
}
|
|
10654
|
+
const useChartChange = ({ dataSources, chartId, width, height, relatedAttributes, defaultColor, fontColor, markers, showMarkers, }) => {
|
|
10655
|
+
const { t } = useGlobalContext();
|
|
10656
|
+
const { layerInfos } = useWidgetContext();
|
|
10657
|
+
const strokeColors = relatedAttributes
|
|
10658
|
+
.filter(({ chartAxis }) => chartAxis === "y")
|
|
10659
|
+
.map(({ axisColor }) => axisColor);
|
|
10660
|
+
const ref = React.useRef({
|
|
10661
|
+
path: null,
|
|
10662
|
+
area: null,
|
|
10663
|
+
points: [],
|
|
10664
|
+
});
|
|
10665
|
+
const onChange = React.useCallback((range) => {
|
|
10666
|
+
const { path, area, points } = ref.current;
|
|
10667
|
+
let filteredPoints = [...points];
|
|
10668
|
+
if (range) {
|
|
10669
|
+
const hundred = 100;
|
|
10670
|
+
const x1 = +width * (range[0] / hundred);
|
|
10671
|
+
const x2 = +width * (range[1] / hundred);
|
|
10672
|
+
filteredPoints = points.filter(([x]) => x >= x1 && x <= x2);
|
|
10673
|
+
}
|
|
10674
|
+
path && path.attr("d", lineGenerator(filteredPoints));
|
|
10675
|
+
area && area.attr("d", areaGenerator(height)(filteredPoints));
|
|
10676
|
+
}, [height, width]);
|
|
10677
|
+
const customize = React.useCallback(({ svg }) => {
|
|
10678
|
+
svg.style("overflow", "visible");
|
|
10679
|
+
svg
|
|
10680
|
+
.selectAll(`.${charts.lineChartClassNames.lineChartXScaleGlobal} line,
|
|
10681
|
+
.${charts.lineChartClassNames.lineChartYScaleGlobal} line,
|
|
10682
|
+
.domain`)
|
|
10683
|
+
.each((_, index, nodes) => {
|
|
10684
|
+
nodes[index].remove();
|
|
10685
|
+
});
|
|
10686
|
+
svg
|
|
10687
|
+
.selectAll(`.${charts.lineChartClassNames.lineChartXScaleGlobal} .tick`)
|
|
10688
|
+
.each((_, index, nodes) => {
|
|
10689
|
+
if (!index) {
|
|
10690
|
+
nodes[index].style.textAnchor = "start";
|
|
10691
|
+
}
|
|
10692
|
+
if (index === nodes.length - 1) {
|
|
10693
|
+
nodes[index].style.textAnchor = "end";
|
|
10694
|
+
}
|
|
10695
|
+
if (markers) {
|
|
10696
|
+
nodes[index].remove();
|
|
10697
|
+
}
|
|
10698
|
+
if (showMarkers) {
|
|
10699
|
+
if (index % showMarkers !== 0) {
|
|
10700
|
+
nodes[index].remove();
|
|
10701
|
+
}
|
|
10702
|
+
}
|
|
10703
|
+
else {
|
|
10704
|
+
if (index && index < nodes.length - 1) {
|
|
10705
|
+
nodes[index].remove();
|
|
10706
|
+
}
|
|
10707
|
+
}
|
|
10708
|
+
});
|
|
10709
|
+
svg
|
|
10710
|
+
.selectAll(`.${charts.lineChartClassNames.lineChartXScaleGlobal} .tick text`)
|
|
10711
|
+
.attr("y", 16);
|
|
10712
|
+
svg
|
|
10713
|
+
.selectAll(`.${charts.lineChartClassNames.lineChartYScaleGlobal} .tick text`)
|
|
10714
|
+
.text(item => {
|
|
10715
|
+
if (!item)
|
|
10716
|
+
return 0;
|
|
10717
|
+
const dataSource = dataSources?.find(({ name }) => name === relatedAttributes[0].dataSourceName);
|
|
10718
|
+
const layerInfo = dataSource
|
|
10719
|
+
? layerInfos.find(({ name }) => name === dataSource.layerName)
|
|
10720
|
+
: null;
|
|
10721
|
+
const attribute = layerInfo?.configuration?.attributesConfiguration?.attributes[relatedAttributes[0].attributeName];
|
|
10722
|
+
return attribute
|
|
10723
|
+
? formatAttributeValue({
|
|
10724
|
+
t,
|
|
10725
|
+
type: attribute.type,
|
|
10726
|
+
value: item,
|
|
10727
|
+
stringFormat: attribute.stringFormat,
|
|
10728
|
+
noUnits: true,
|
|
10729
|
+
})
|
|
10730
|
+
: item;
|
|
10731
|
+
})
|
|
10732
|
+
.each(wrap);
|
|
10733
|
+
svg.selectAll(".tick text").attr("style", `color: ${fontColor}`);
|
|
10734
|
+
const global = svg.select(`.${charts.lineChartClassNames.lineChartLinesGlobal}`);
|
|
10735
|
+
const lineChartLines = svg.selectAll(`.${charts.lineChartClassNames.lineChartLine}`);
|
|
10736
|
+
const defs = [];
|
|
10737
|
+
lineChartLines.each((_, index, nodes) => {
|
|
10738
|
+
const lineChartLine = nodes[index];
|
|
10739
|
+
const gradientId = lodash.uniqueId(`${chartId}-gradient-`);
|
|
10740
|
+
const color = strokeColors[index] || defaultColor;
|
|
10741
|
+
const newPath = global
|
|
10742
|
+
.append("path")
|
|
10743
|
+
.attr("stroke", color)
|
|
10744
|
+
.attr("stroke-width", "0")
|
|
10745
|
+
.attr("class", charts.lineChartClassNames.lineChartLine);
|
|
10746
|
+
const points = getLinePoints(+width, lineChartLine);
|
|
10747
|
+
const area = global
|
|
10748
|
+
.append("path")
|
|
10749
|
+
.attr("fill", `url(#${gradientId})`)
|
|
10750
|
+
.attr("stroke-width", "0")
|
|
10751
|
+
.attr("fill-opacity", FILL_OPACITY);
|
|
10752
|
+
defs.push(`
|
|
10753
|
+
<linearGradient id="${gradientId}" x1="0" y1="0" x2="0" y2="1">
|
|
10754
|
+
<stop offset="0" stop-color="${color}" stop-opacity="1" />
|
|
10755
|
+
<stop offset="1" stop-color="${color}" stop-opacity="0" />
|
|
10756
|
+
</linearGradient>
|
|
10757
|
+
`);
|
|
10758
|
+
ref.current = {
|
|
10759
|
+
path: newPath,
|
|
10760
|
+
area,
|
|
10761
|
+
points,
|
|
10762
|
+
};
|
|
10763
|
+
onChange();
|
|
10764
|
+
});
|
|
10765
|
+
svg.append("defs").html(() => defs.join(""));
|
|
10766
|
+
}, [
|
|
10767
|
+
fontColor,
|
|
10768
|
+
dataSources,
|
|
10769
|
+
layerInfos,
|
|
10770
|
+
relatedAttributes,
|
|
10771
|
+
chartId,
|
|
10772
|
+
strokeColors,
|
|
10773
|
+
defaultColor,
|
|
10774
|
+
width,
|
|
10775
|
+
onChange,
|
|
10776
|
+
showMarkers,
|
|
10777
|
+
markers,
|
|
10778
|
+
]);
|
|
10779
|
+
return [customize, onChange];
|
|
10780
|
+
};
|
|
10781
|
+
|
|
10776
10782
|
const useWidgetConfig = (type = exports.WidgetType.Dashboard) => {
|
|
10777
10783
|
const { config: configProp, containerIds, projectInfo, layerInfo, isEditing } = useWidgetContext(type);
|
|
10778
10784
|
const config = React.useMemo(() => {
|
|
@@ -12741,6 +12747,7 @@ exports.useAppHeight = useAppHeight;
|
|
|
12741
12747
|
exports.useAutoCompleteControl = useAutoCompleteControl;
|
|
12742
12748
|
exports.useChartChange = useChartChange;
|
|
12743
12749
|
exports.useChartData = useChartData;
|
|
12750
|
+
exports.useContainerAttributes = useContainerAttributes;
|
|
12744
12751
|
exports.useCurrentPageLayers = useCurrentPageLayers;
|
|
12745
12752
|
exports.useCustomFeatureSelect = useCustomFeatureSelect;
|
|
12746
12753
|
exports.useDashboardHeader = useDashboardHeader;
|