@evergis/react 4.0.41 → 4.0.43

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.
@@ -177,7 +177,7 @@ export interface ConfigOptions {
177
177
  export interface ConfigDataSource {
178
178
  name: string;
179
179
  alias?: string;
180
- condition?: string;
180
+ condition?: string | string[];
181
181
  ds?: string;
182
182
  layerName?: string;
183
183
  limit?: number;
@@ -228,7 +228,7 @@ export interface SelectedFilter {
228
228
  export interface ConfigLayer {
229
229
  name: string;
230
230
  opacity?: number;
231
- condition?: string;
231
+ condition?: string | string[];
232
232
  query?: string;
233
233
  parameters?: Record<string, any>;
234
234
  geometries?: Array<any>;
@@ -241,6 +241,7 @@ export interface ConfigLayer {
241
241
  maxZoomTo?: number;
242
242
  hiddenAttributes?: string[];
243
243
  customFeatureSelect?: CustomFeatureSelect;
244
+ disableDrag?: boolean;
244
245
  }
245
246
  export interface ConfigTask {
246
247
  name: string;
@@ -17,12 +17,15 @@ export declare const applyVarsToCondition: <T extends string | string[]>({ secti
17
17
  geometry?: string;
18
18
  isSetParams?: boolean;
19
19
  }) => T;
20
- export declare const formatDataSourceCondition: ({ condition, configFilters, filters, attributes, eqlParameters, layerParams, geometry, }: {
21
- condition?: string;
20
+ type FormatDataSourceConditionParams = {
22
21
  configFilters?: ConfigFilter[];
23
22
  filters: SelectedFilters;
24
23
  attributes?: ClientFeatureAttribute[];
25
24
  eqlParameters?: QueryLayerServiceConfigurationDc["eqlParameters"];
26
25
  layerParams?: Record<string, string>;
27
26
  geometry?: string;
28
- }) => string;
27
+ };
28
+ export declare const formatDataSourceCondition: ({ condition, ...rest }: FormatDataSourceConditionParams & {
29
+ condition?: string | string[];
30
+ }) => string | string[];
31
+ export {};
@@ -1,4 +1,5 @@
1
1
  import { ProjectContentItemDc } from '@evergis/api';
2
+ import { DraggableTreeNode } from '@evergis/uilib-gl';
2
3
  import { ConfigLayer } from '../Dashboard';
3
4
  export declare const LayersListWrapper: import('styled-components').StyledComponent<"div", any, import('@evergis/uilib-gl').FlexProps, never>;
4
5
  export declare const LayerListContainer: import('styled-components').StyledComponent<"div", any, import('@evergis/uilib-gl').FlexProps, never>;
@@ -9,4 +10,5 @@ export interface LayerItemProps {
9
10
  export interface LayerTreeProps {
10
11
  layers: ConfigLayer[];
11
12
  onlyMainTools?: boolean;
13
+ onUpdate?: (updatedNodes: DraggableTreeNode[]) => void;
12
14
  }
@@ -2,4 +2,8 @@ import { FC } from 'react';
2
2
  import { DraggableTreeNode } from '@evergis/uilib-gl';
3
3
  import { ProjectContentItemDc } from '@evergis/api';
4
4
  import { LayerItemProps } from '../types';
5
- export declare const createTreeNode: (layer: ProjectContentItemDc, Component: FC<LayerItemProps>, onlyMainTools?: boolean) => DraggableTreeNode;
5
+ type CreateTreeNodeLayer = ProjectContentItemDc & {
6
+ disableDrag?: boolean;
7
+ };
8
+ export declare const createTreeNode: (layer: CreateTreeNodeLayer, Component: FC<LayerItemProps>, onlyMainTools?: boolean) => DraggableTreeNode;
9
+ export {};
@@ -1,3 +1,3 @@
1
1
  import { ProjectContentItemDc } from '@evergis/api';
2
2
  import { DraggableTreeNode } from '@evergis/uilib-gl';
3
- export declare const treeNodesToProjectItems: (currentProjectItems?: ProjectContentItemDc[], treeNodes?: DraggableTreeNode[]) => any;
3
+ export declare const treeNodesToProjectItems: (currentProjectItems?: ProjectContentItemDc[], treeNodes?: DraggableTreeNode[]) => any[];
@@ -3,3 +3,5 @@ export declare const SERVER_NOTIFICATION_EVENT: {
3
3
  PythonProgressNotification: string;
4
4
  PythonSandboxStats: string;
5
5
  };
6
+ export declare const POLL_SUBTASK_INTERVAL_MS = 500;
7
+ export declare const POLL_SUBTASK_TIMEOUT_MS = 15000;
@@ -0,0 +1,15 @@
1
+ import { SubTasksDto } from '@evergis/api';
2
+ interface RemoteTaskManagerLike {
3
+ get(id: string): Promise<SubTasksDto[]>;
4
+ }
5
+ interface ApiLike {
6
+ remoteTaskManager: RemoteTaskManagerLike;
7
+ }
8
+ interface PollSubtaskCompletionOptions {
9
+ taskId: string;
10
+ api: ApiLike;
11
+ intervalMs?: number;
12
+ timeoutMs?: number;
13
+ }
14
+ export declare const pollSubtaskCompletion: ({ taskId, api, intervalMs, timeoutMs, }: PollSubtaskCompletionOptions) => Promise<SubTasksDto | null>;
15
+ export {};
package/dist/index.js CHANGED
@@ -11,8 +11,7 @@ var color$1 = require('@evergis/color');
11
11
  var turf = require('@turf/turf');
12
12
  var dateFns = require('date-fns');
13
13
  var lodash = require('lodash');
14
- var ru = require('date-fns/locale/ru');
15
- var enUS = require('date-fns/locale/en-US');
14
+ var locale = require('date-fns/locale');
16
15
  var signalr = require('@microsoft/signalr');
17
16
  var findAnd = require('find-and');
18
17
  var jspdf = require('jspdf');
@@ -3705,7 +3704,7 @@ exports.ScalingFactor = void 0;
3705
3704
  ScalingFactor[ScalingFactor["Acres"] = 0.01] = "Acres";
3706
3705
  ScalingFactor[ScalingFactor["Hectares"] = 0.0001] = "Hectares";
3707
3706
  })(exports.ScalingFactor || (exports.ScalingFactor = {}));
3708
- const formatDate = (str, isRuLocale) => dateFns.format(Date.now(), str, { locale: isRuLocale ? ru.ru : enUS.enUS });
3707
+ const formatDate = (str, isRuLocale) => dateFns.format(Date.now(), str, { locale: isRuLocale ? locale.ru : locale.enUS });
3709
3708
  const timeOptions = [
3710
3709
  {
3711
3710
  text: formatDate("kk:mm:ss"),
@@ -3816,7 +3815,7 @@ const formatDateValue = (stringFormat, dateValue) => {
3816
3815
  const dateOptionValue = dateOption && dateOption.value;
3817
3816
  const dateFormat = value && dateOptionValue
3818
3817
  ? dateFns.format(value, dateOptionValue, {
3819
- locale: ru.ru,
3818
+ locale: locale.ru,
3820
3819
  })
3821
3820
  : "";
3822
3821
  const timeOption = getValueFromOptions(timeOptions, stringFormat.format);
@@ -4704,10 +4703,7 @@ const applyVarsToCondition = ({ section, configFilters, filters, attributes, lay
4704
4703
  });
4705
4704
  return isSingle ? result?.[0] : result;
4706
4705
  };
4707
- const formatDataSourceCondition = ({ condition, configFilters, filters, attributes, eqlParameters, layerParams, geometry, }) => {
4708
- if (!condition) {
4709
- return "";
4710
- }
4706
+ const formatSingleCondition = (condition, { configFilters, filters, attributes, eqlParameters, layerParams, geometry }) => {
4711
4707
  const setParams = condition.match(new RegExp("\\$\\([^)]+\\)", "g"));
4712
4708
  const setParamsSection = applyVarsToCondition({
4713
4709
  section: setParams,
@@ -4736,6 +4732,15 @@ const formatDataSourceCondition = ({ condition, configFilters, filters, attribut
4736
4732
  ? setParamsSection.join("")
4737
4733
  : conditionSection.join(splitter);
4738
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
+ };
4739
4744
 
4740
4745
  const DashboardChipsContainer = styled(uilibGl.Flex) `
4741
4746
  flex-wrap: wrap;
@@ -5100,7 +5105,7 @@ const useMapImages = ({ images }) => {
5100
5105
  else {
5101
5106
  // PNG/другие форматы: используем стандартную загрузку Mapbox
5102
5107
  return new Promise((resolve, reject) => {
5103
- map.current.loadImage(config.url).then((image) => {
5108
+ map.current.loadImage(config.url).then(image => {
5104
5109
  if (image) {
5105
5110
  map.current.addImage(config.name, image, {
5106
5111
  sdf,
@@ -5489,6 +5494,8 @@ const SERVER_NOTIFICATION_EVENT = {
5489
5494
  PythonProgressNotification: "ReceivePythonProgressNotification",
5490
5495
  PythonSandboxStats: "ReceivePythonSandboxStatsNotification",
5491
5496
  };
5497
+ const POLL_SUBTASK_INTERVAL_MS = 500;
5498
+ const POLL_SUBTASK_TIMEOUT_MS = 15_000;
5492
5499
 
5493
5500
  const usePythonSandbox = () => {
5494
5501
  const { api } = useGlobalContext();
@@ -5500,6 +5507,25 @@ const usePythonSandbox = () => {
5500
5507
  return { preparePythonSandbox };
5501
5508
  };
5502
5509
 
5510
+ const FINAL_STATUSES = [
5511
+ api.RemoteTaskStatus.Completed,
5512
+ api.RemoteTaskStatus.Error,
5513
+ api.RemoteTaskStatus.Interrupted,
5514
+ api.RemoteTaskStatus.Timeout,
5515
+ ];
5516
+ const wait = (ms) => new Promise(resolve => window.setTimeout(resolve, ms));
5517
+ const pollSubtaskCompletion = async ({ taskId, api, intervalMs = POLL_SUBTASK_INTERVAL_MS, timeoutMs = POLL_SUBTASK_TIMEOUT_MS, }) => {
5518
+ const deadline = Date.now() + timeoutMs;
5519
+ let subTask = (await api.remoteTaskManager.get(taskId))?.[0] ?? null;
5520
+ while (subTask && !FINAL_STATUSES.includes(subTask.status)) {
5521
+ if (Date.now() >= deadline)
5522
+ return null;
5523
+ await wait(intervalMs);
5524
+ subTask = (await api.remoteTaskManager.get(taskId))?.[0] ?? null;
5525
+ }
5526
+ return subTask;
5527
+ };
5528
+
5503
5529
  const usePythonTask = () => {
5504
5530
  const { api: api$1, t } = useGlobalContext();
5505
5531
  const { addSubscription, connection, unsubscribeById } = useServerNotificationsContext();
@@ -5576,8 +5602,24 @@ const usePythonTask = () => {
5576
5602
  connection.off(SERVER_NOTIFICATION_EVENT.PythonProgressNotification, onNotification);
5577
5603
  }
5578
5604
  if (data.status === api.RemoteTaskStatus.Completed) {
5579
- const subTasks = await api$1.remoteTaskManager.get(newTaskId);
5580
- setResult(subTasks?.[0]?.results?.response ?? null);
5605
+ try {
5606
+ const subTask = await pollSubtaskCompletion({ taskId: newTaskId, api: api$1 });
5607
+ if (subTask?.status === api.RemoteTaskStatus.Completed) {
5608
+ const response = subTask.results?.response;
5609
+ setResult(typeof response === "object" && response !== null
5610
+ ? response
5611
+ : null);
5612
+ }
5613
+ else {
5614
+ setError(new Error(t("taskResultUnavailable", {
5615
+ ns: "devMode",
5616
+ defaultValue: "Не удалось получить результат задачи",
5617
+ })));
5618
+ }
5619
+ }
5620
+ catch (e) {
5621
+ setError(e instanceof Error ? e : new Error(String(e)));
5622
+ }
5581
5623
  }
5582
5624
  }
5583
5625
  };
@@ -5696,6 +5738,7 @@ const createTreeNode = (layer, Component, onlyMainTools) => {
5696
5738
  id: layer.name,
5697
5739
  children: layer.children?.map(child => createTreeNode(child, Component, onlyMainTools)),
5698
5740
  isExpanded: layer.isExpanded,
5741
+ disableDrag: layer.disableDrag,
5699
5742
  render: (node) => {
5700
5743
  return layer.children ? (jsxRuntime.jsx(LayerGroup, { group: {
5701
5744
  ...layer,
@@ -5710,21 +5753,30 @@ const treeNodesToProjectItems = (currentProjectItems, treeNodes) => {
5710
5753
  return currentProjectItems;
5711
5754
  }
5712
5755
  const combineProjectItems = (nodes) => {
5713
- return nodes.map(node => {
5714
- return {
5715
- ...findAnd.returnFound(currentProjectItems, { name: node.id }),
5756
+ return nodes.reduce((result, node) => {
5757
+ const original = findAnd.returnFound(currentProjectItems, { name: node.id });
5758
+ if (!original) {
5759
+ return result;
5760
+ }
5761
+ result.push({
5762
+ ...original,
5716
5763
  children: node.children ? combineProjectItems(node.children) : undefined,
5717
- };
5718
- });
5764
+ });
5765
+ return result;
5766
+ }, []);
5719
5767
  };
5720
5768
  return combineProjectItems(treeNodes);
5721
5769
  };
5722
5770
 
5723
- const LayerTree = ({ layers, onlyMainTools }) => {
5771
+ const LayerTree = ({ layers, onlyMainTools, onUpdate: externalOnUpdate }) => {
5724
5772
  const { projectInfo, updateProject, components: { LayerItem } } = useWidgetContext();
5725
5773
  const { pageIndex } = useWidgetPage();
5726
5774
  const nodes = React.useMemo(() => layers?.map(layer => createTreeNode(layer, LayerItem, onlyMainTools)), [LayerItem, layers, onlyMainTools]);
5727
5775
  const onUpdate = React.useCallback((updatedNodes) => {
5776
+ if (externalOnUpdate) {
5777
+ externalOnUpdate(updatedNodes);
5778
+ return;
5779
+ }
5728
5780
  const newProjectInfo = JSON.parse(JSON.stringify(projectInfo));
5729
5781
  const page = getPagesFromProjectInfo(newProjectInfo)?.[pageIndex - 1];
5730
5782
  if (!page) {
@@ -5732,7 +5784,7 @@ const LayerTree = ({ layers, onlyMainTools }) => {
5732
5784
  }
5733
5785
  page.layers = treeNodesToProjectItems(page.layers, updatedNodes);
5734
5786
  updateProject(newProjectInfo);
5735
- }, [pageIndex, projectInfo, updateProject]);
5787
+ }, [externalOnUpdate, pageIndex, projectInfo, updateProject]);
5736
5788
  return (jsxRuntime.jsx(uilibGl.DraggableTree, { nodes: nodes, disableDrag: onlyMainTools, options: { pastePlaceholderHeight: "0.025rem" }, onUpdate: onUpdate }));
5737
5789
  };
5738
5790
 
@@ -10983,6 +11035,7 @@ const useDashboardHeader = () => {
10983
11035
  };
10984
11036
 
10985
11037
  /* eslint-disable max-lines */
11038
+ const toConditionsArray = (value) => Array.isArray(value) ? value : value ? [value] : [];
10986
11039
  const useDataSources = ({ type: widgetType, config, attributes, filters, layerParams, eqlParameters, }) => {
10987
11040
  const { ewktGeometry, api } = useGlobalContext();
10988
11041
  const { dataSources, layerInfo } = useWidgetContext(widgetType);
@@ -11059,24 +11112,25 @@ const useDataSources = ({ type: widgetType, config, attributes, filters, layerPa
11059
11112
  attributes: descriptionResponse,
11060
11113
  };
11061
11114
  }
11115
+ const formatted = condition
11116
+ ? formatDataSourceCondition({
11117
+ condition,
11118
+ configFilters,
11119
+ filters: selectedFilters,
11120
+ geometry: ewktGeometry,
11121
+ attributes,
11122
+ layerParams,
11123
+ eqlParameters,
11124
+ })
11125
+ : undefined;
11062
11126
  return api.layers.getFeatures(layerName, {
11063
11127
  offset,
11064
11128
  limit: limit || DEFAULT_DATA_SOURCE_LIMIT,
11065
11129
  withGeom: false,
11066
11130
  parameters: newParams,
11067
11131
  conditions: lodash.isEmpty(parameters) && condition
11068
- ? [
11069
- formatDataSourceCondition({
11070
- condition,
11071
- configFilters,
11072
- filters: selectedFilters,
11073
- geometry: ewktGeometry,
11074
- attributes,
11075
- layerParams,
11076
- eqlParameters,
11077
- }),
11078
- ]
11079
- : [condition, query].filter(Boolean),
11132
+ ? toConditionsArray(formatted)
11133
+ : [...toConditionsArray(condition), query].filter(Boolean),
11080
11134
  });
11081
11135
  }, [
11082
11136
  filters,
@@ -11088,6 +11142,8 @@ const useDataSources = ({ type: widgetType, config, attributes, filters, layerPa
11088
11142
  api.eql,
11089
11143
  attributes,
11090
11144
  layerParams,
11145
+ layerInfo,
11146
+ projectDataSources,
11091
11147
  eqlParameters,
11092
11148
  ]);
11093
11149
  const getUpdatingDataSources = React.useCallback(() => {
@@ -12547,6 +12603,8 @@ exports.NO_CONTENT_VALUE = NO_CONTENT_VALUE;
12547
12603
  exports.NUMERIC_ATTRIBUTE_TYPES = NUMERIC_ATTRIBUTE_TYPES;
12548
12604
  exports.NoLiveSnapshotContainer = NoLiveSnapshotContainer;
12549
12605
  exports.OneColumnContainer = OneColumnContainer;
12606
+ exports.POLL_SUBTASK_INTERVAL_MS = POLL_SUBTASK_INTERVAL_MS;
12607
+ exports.POLL_SUBTASK_TIMEOUT_MS = POLL_SUBTASK_TIMEOUT_MS;
12550
12608
  exports.PROVIDER_PREFIX = PROVIDER_PREFIX;
12551
12609
  exports.PageNavigator = PageNavigator;
12552
12610
  exports.PageTitle = PageTitle;