@evergis/react 4.0.150 → 4.0.151

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.
@@ -0,0 +1,11 @@
1
+ import { WidgetType } from '../../../types';
2
+ /**
3
+ * Видимость диалога модалки. Флаг локальный: у одного `modalId` бывает несколько кнопок (слот
4
+ * `modal` в строках `DataSource`), и общий флаг открыл бы все диалоги сразу. Хост узнаёт об
5
+ * открытии и закрытии через `onModalToggle` — чтобы грузить `dataSources` модалки только пока она открыта.
6
+ */
7
+ export declare const useModalOpen: (type: WidgetType, modalId?: string) => {
8
+ isOpen: boolean;
9
+ handleOpen: () => void;
10
+ handleClose: () => void;
11
+ };
@@ -11,6 +11,7 @@ export * from './useFetchImageWithAuth';
11
11
  export * from './useFetchWithAuth';
12
12
  export * from './useChartChange';
13
13
  export * from './useChartData';
14
+ export * from './useConfigDataSources';
14
15
  export * from './useDashboardHeader';
15
16
  export * from './useDataSourceLoading';
16
17
  export * from './useDataSources';
@@ -0,0 +1,7 @@
1
+ import { ConfigDataSource, WidgetType } from '../types';
2
+ /**
3
+ * Конфиги всех источников, доступных контейнерам виджета: страница с корнем и все модалки.
4
+ * Одноимённый источник модалки перекрывается страничным. Только для поиска по имени — в конфиг
5
+ * страницы не пишется: `currentPage` сохраняется обратно целиком, и модальные источники осели бы в нём.
6
+ */
7
+ export declare const useConfigDataSources: (type?: WidgetType) => ConfigDataSource[];
@@ -37,6 +37,7 @@ export declare const useWidgetContext: <T extends WidgetType = WidgetType.Dashbo
37
37
  config: import('../types').ConfigContainer;
38
38
  isEditing: boolean;
39
39
  onContainerChange: (config: import('../types').ConfigContainerChild) => void;
40
+ onModalToggle: (modalId: string, isOpen: boolean) => void;
40
41
  isLoading: boolean;
41
42
  pageIndex: number;
42
43
  filters: import('../types').SelectedFilters;
@@ -705,6 +705,7 @@ export type ConfigModalContentItem = ConfigContainerChild | ConfigModalContentRe
705
705
  export interface ConfigModal {
706
706
  id: string;
707
707
  options?: ConfigModalOptions;
708
+ dataSources?: ConfigDataSource[];
708
709
  children: ConfigModalContentItem[];
709
710
  }
710
711
  export interface ConfigContainerHeader {
@@ -0,0 +1,6 @@
1
+ import { ConfigContainer, ConfigDataSource } from '../types';
2
+ /**
3
+ * Источники модалок конфига (`config.modals[].dataSources`) без дублей по имени — выигрывает первый.
4
+ * Без `modalIds` — источники всех модалок, иначе только перечисленных.
5
+ */
6
+ export declare const getModalsDataSources: (config?: ConfigContainer, modalIds?: string[]) => ConfigDataSource[];
@@ -39,6 +39,7 @@ export * from './getFilterComponent';
39
39
  export * from './getFilterSelectedItems';
40
40
  export * from './getFilterValue';
41
41
  export * from './getMapViewDataSources';
42
+ export * from './getModalsDataSources';
42
43
  export * from './getFormattedAttributes';
43
44
  export * from './getImageUrl';
44
45
  export * from './getLayerInfo';
@@ -21,6 +21,12 @@ export type DashboardContextProps = PropsWithChildren<{
21
21
  * лежит внутри — применяется как `replaceObject(config, { id }, next)`.
22
22
  */
23
23
  onContainerChange?: (config: ConfigContainerChild) => void;
24
+ /**
25
+ * Модалка `config.modals[].id` открылась или закрылась — хост грузит её `dataSources`, пока она
26
+ * открыта. Видимостью диалога управляет сам `ElementModal`: у одного `modalId` бывает несколько
27
+ * кнопок (слот `modal` в строках `DataSource`), общий флаг открыл бы все диалоги сразу.
28
+ */
29
+ onModalToggle?: (modalId: string, isOpen: boolean) => void;
24
30
  filters?: SelectedFilters;
25
31
  dashboardLayers?: DashboardState["layers"];
26
32
  setDashboardLayer?: (props: DashboardLayerPayload) => void;
@@ -13,6 +13,8 @@ export type FeatureCardContextSettings = PropsWithChildren<{
13
13
  editMode?: boolean;
14
14
  /** Контейнер изменил собственный конфиг — см. одноимённый проп `DashboardProvider`. */
15
15
  onContainerChange?: (config: ConfigContainerChild) => void;
16
+ /** Модалка открылась или закрылась — см. одноимённый проп `DashboardProvider`. */
17
+ onModalToggle?: (modalId: string, isOpen: boolean) => void;
16
18
  isFeatureEditable?: boolean;
17
19
  hasCopyRights?: boolean;
18
20
  editOnly?: boolean;
package/dist/index.js CHANGED
@@ -5752,8 +5752,8 @@ const useAttachmentDownload = (items) => {
5752
5752
  * {@link FeatureCardContext} на пересекающуюся базу и виджет-специфичные расширения.
5753
5753
  */
5754
5754
  const useWidgetContext = (type = exports.WidgetType.Dashboard) => {
5755
- const { toggleLayersVisibility, visibleLayers, projectInfo, updateProject, layerInfos, geometryFilter, dashboardLayers, setDashboardLayer, components: dashboardComponents, selectAttachmentsFromCatalog, config: dashboardConfig, containerIds, pageIndex: projectPageIndex, selectedTabId: projectSelectedTabId, setSelectedTabId: setProjectSelectedTabId, dataSources: projectDataSources, loading: projectLoading, editMode: projectEditMode, onContainerChange: projectOnContainerChange, filters: projectFilters, changeFilters: projectChangeFilters, expandContainer: projectExpandContainer, expandedContainers: projectExpandedContainers, nextPage: projectNextPage, prevPage: projectPrevPage, changePage: projectChangePage, } = React.useContext(DashboardContext) || {};
5756
- const { layerInfo, attributes, feature, controls, changeControls, closeFeatureCard, config: featureConfig, pageIndex: featurePageIndex, selectedTabId: featureSelectedTabId, setSelectedTabId: setFeatureSelectedTabId, dataSources: featureDataSources, loading: featureLoading, editMode: featureEditMode, onContainerChange: featureOnContainerChange, filters: featureFilters, changeFilters: featureChangeFilters, expandContainer: featureExpandContainer, expandedContainers: featureExpandedContainers, nextPage: featureNextPage, prevPage: featurePrevPage, changePage: featureChangePage, } = React.useContext(FeatureCardContext) || {};
5755
+ const { toggleLayersVisibility, visibleLayers, projectInfo, updateProject, layerInfos, geometryFilter, dashboardLayers, setDashboardLayer, components: dashboardComponents, selectAttachmentsFromCatalog, config: dashboardConfig, containerIds, pageIndex: projectPageIndex, selectedTabId: projectSelectedTabId, setSelectedTabId: setProjectSelectedTabId, dataSources: projectDataSources, loading: projectLoading, editMode: projectEditMode, onContainerChange: projectOnContainerChange, onModalToggle: projectOnModalToggle, filters: projectFilters, changeFilters: projectChangeFilters, expandContainer: projectExpandContainer, expandedContainers: projectExpandedContainers, nextPage: projectNextPage, prevPage: projectPrevPage, changePage: projectChangePage, } = React.useContext(DashboardContext) || {};
5756
+ const { layerInfo, attributes, feature, controls, changeControls, closeFeatureCard, config: featureConfig, pageIndex: featurePageIndex, selectedTabId: featureSelectedTabId, setSelectedTabId: setFeatureSelectedTabId, dataSources: featureDataSources, loading: featureLoading, editMode: featureEditMode, onContainerChange: featureOnContainerChange, onModalToggle: featureOnModalToggle, filters: featureFilters, changeFilters: featureChangeFilters, expandContainer: featureExpandContainer, expandedContainers: featureExpandedContainers, nextPage: featureNextPage, prevPage: featurePrevPage, changePage: featureChangePage, } = React.useContext(FeatureCardContext) || {};
5757
5757
  return {
5758
5758
  toggleLayersVisibility,
5759
5759
  visibleLayers,
@@ -5775,6 +5775,7 @@ const useWidgetContext = (type = exports.WidgetType.Dashboard) => {
5775
5775
  config: type === exports.WidgetType.Dashboard ? dashboardConfig : featureConfig,
5776
5776
  isEditing: type === exports.WidgetType.Dashboard ? projectEditMode : featureEditMode,
5777
5777
  onContainerChange: type === exports.WidgetType.Dashboard ? projectOnContainerChange : featureOnContainerChange,
5778
+ onModalToggle: type === exports.WidgetType.Dashboard ? projectOnModalToggle : featureOnModalToggle,
5778
5779
  isLoading: type === exports.WidgetType.Dashboard ? projectLoading : featureLoading,
5779
5780
  pageIndex: type === exports.WidgetType.Dashboard ? projectPageIndex || 1 : featurePageIndex || 1,
5780
5781
  filters: type === exports.WidgetType.Dashboard ? projectFilters : featureFilters,
@@ -7227,6 +7228,14 @@ const useChartChange = ({ dataSources, chartId, width, height, relatedAttributes
7227
7228
  return [customize, onChange];
7228
7229
  };
7229
7230
 
7231
+ /**
7232
+ * Источники модалок конфига (`config.modals[].dataSources`) без дублей по имени — выигрывает первый.
7233
+ * Без `modalIds` — источники всех модалок, иначе только перечисленных.
7234
+ */
7235
+ const getModalsDataSources = (config, modalIds) => lodash.uniqBy((config?.modals ?? [])
7236
+ .filter(({ id }) => !modalIds || modalIds.includes(id))
7237
+ .flatMap(({ dataSources }) => dataSources ?? []), "name");
7238
+
7230
7239
  /**
7231
7240
  * Generic-параметр `T` сейчас идёт как намерение (под какой виджет). Дальнейшее сужение
7232
7241
  * `config` под конкретный виджет — отдельная задача.
@@ -7353,15 +7362,26 @@ const useWidgetPage = (type = exports.WidgetType.Dashboard) => {
7353
7362
  };
7354
7363
  };
7355
7364
 
7365
+ /**
7366
+ * Конфиги всех источников, доступных контейнерам виджета: страница с корнем и все модалки.
7367
+ * Одноимённый источник модалки перекрывается страничным. Только для поиска по имени — в конфиг
7368
+ * страницы не пишется: `currentPage` сохраняется обратно целиком, и модальные источники осели бы в нём.
7369
+ */
7370
+ const useConfigDataSources = (type = exports.WidgetType.Dashboard) => {
7371
+ const { config } = useWidgetConfig(type);
7372
+ const { currentPage } = useWidgetPage(type);
7373
+ return React.useMemo(() => lodash.uniqBy([...(currentPage?.dataSources ?? []), ...getModalsDataSources(config)], "name"), [config, currentPage?.dataSources]);
7374
+ };
7375
+
7356
7376
  const useChartData = ({ element, type }) => {
7357
7377
  const { t } = useGlobalContext();
7358
7378
  const { dataSources, layerInfos, attributes } = useWidgetContext(type);
7359
7379
  const { currentPage } = useWidgetPage(type);
7380
+ const configDataSources = useConfigDataSources(type);
7360
7381
  const relatedAttributes = React.useMemo(() => element?.options?.relatedDataSources || [], [element?.options?.relatedDataSources]);
7361
7382
  const loading = React.useMemo(() => !!relatedAttributes?.length &&
7362
7383
  !dataSources?.some(({ name }) => relatedAttributes.some(({ chartAxis, dataSourceName }) => chartAxis === "y" && dataSourceName === name)), [dataSources, relatedAttributes]);
7363
7384
  const fetchedData = React.useMemo(() => {
7364
- const configDataSources = currentPage?.dataSources || [];
7365
7385
  const isRelated = !!relatedAttributes?.length;
7366
7386
  const filteredAttributes = relatedAttributes.filter(({ chartAxis }) => chartAxis === "y");
7367
7387
  if (!element)
@@ -7412,7 +7432,7 @@ const useChartData = ({ element, type }) => {
7412
7432
  },
7413
7433
  ];
7414
7434
  }, [
7415
- currentPage?.dataSources,
7435
+ configDataSources,
7416
7436
  currentPage?.filters,
7417
7437
  relatedAttributes,
7418
7438
  element,
@@ -8281,11 +8301,11 @@ const useResizeDrag = ({ onStart, onMove, onEnd }) => {
8281
8301
 
8282
8302
  const useRelatedDataSourceAttributes = ({ type = exports.WidgetType.Dashboard, elementConfig, dataSources, feature, }) => {
8283
8303
  const { layerInfos } = useWidgetContext(type);
8284
- const { currentPage } = useWidgetPage(type);
8304
+ const configDataSources = useConfigDataSources(type);
8285
8305
  const { options } = elementConfig || {};
8286
8306
  const { relatedDataSource } = options || {};
8287
8307
  const dataSource = React.useMemo(() => getDataSource(relatedDataSource, dataSources), [dataSources, relatedDataSource]);
8288
- const configDataSource = React.useMemo(() => currentPage?.dataSources?.find(({ name }) => name === relatedDataSource), [currentPage?.dataSources, relatedDataSource]);
8308
+ const configDataSource = React.useMemo(() => configDataSources.find(({ name }) => name === relatedDataSource), [configDataSources, relatedDataSource]);
8289
8309
  const layerInfo = React.useMemo(() => getDataSourceLayerInfo({ layerInfos, configDataSource, fetchedDataSource: dataSource }) ||
8290
8310
  EMPTY_DATA_SOURCE_LAYER_INFO, [configDataSource, dataSource, layerInfos]);
8291
8311
  const attributes = React.useMemo(() => getFeatureAttributes(feature, layerInfo, dataSource), [dataSource, feature, layerInfo]);
@@ -17054,13 +17074,43 @@ const getRenderElement = ({ t, config, elementConfig, attributes = [], layerInfo
17054
17074
  });
17055
17075
  };
17056
17076
 
17077
+ /**
17078
+ * Видимость диалога модалки. Флаг локальный: у одного `modalId` бывает несколько кнопок (слот
17079
+ * `modal` в строках `DataSource`), и общий флаг открыл бы все диалоги сразу. Хост узнаёт об
17080
+ * открытии и закрытии через `onModalToggle` — чтобы грузить `dataSources` модалки только пока она открыта.
17081
+ */
17082
+ const useModalOpen = (type, modalId) => {
17083
+ const { onModalToggle } = useWidgetContext(type);
17084
+ const [isOpen, setIsOpen] = React.useState(false);
17085
+ const isOpenRef = React.useRef(false);
17086
+ const onModalToggleRef = React.useRef(onModalToggle);
17087
+ React.useEffect(() => {
17088
+ onModalToggleRef.current = onModalToggle;
17089
+ }, [onModalToggle]);
17090
+ const changeOpen = React.useCallback((nextIsOpen) => {
17091
+ isOpenRef.current = nextIsOpen;
17092
+ setIsOpen(nextIsOpen);
17093
+ if (modalId)
17094
+ onModalToggleRef.current?.(modalId, nextIsOpen);
17095
+ }, [modalId]);
17096
+ const handleOpen = React.useCallback(() => changeOpen(true), [changeOpen]);
17097
+ const handleClose = React.useCallback(() => changeOpen(false), [changeOpen]);
17098
+ // Размонтирование ОТКРЫТОГО экземпляра (смена страницы, закрытие карточки) — хост перестаёт
17099
+ // грузить модалку. Закрытый экземпляр молчит: иначе «закрыл» бы соседний открытый с тем же id.
17100
+ React.useEffect(() => () => {
17101
+ if (isOpenRef.current && modalId)
17102
+ onModalToggleRef.current?.(modalId, false);
17103
+ }, [modalId]);
17104
+ return { isOpen, handleOpen, handleClose };
17105
+ };
17106
+
17057
17107
  const ElementModal = React.memo(({ type = exports.WidgetType.Dashboard, elementConfig }) => {
17058
17108
  const { config } = useWidgetConfig(type);
17059
17109
  const { expandedContainers, attributes } = useWidgetContext(type);
17060
17110
  const isDataSourceLoading = useDataSourceLoading(type);
17061
- const [isOpen, setIsOpen] = React.useState(false);
17062
17111
  const { options } = elementConfig || {};
17063
17112
  const { modalId, icon } = options || {};
17113
+ const { isOpen, handleOpen, handleClose } = useModalOpen(type, modalId);
17064
17114
  const modalConfig = React.useMemo(() => (config?.modals ?? []).find(({ id }) => id === modalId) ?? null, [config?.modals, modalId]);
17065
17115
  const modalContent = React.useMemo(() => (modalConfig?.children ?? []), [modalConfig]);
17066
17116
  const renderElementConfig = React.useMemo(() => ({ children: modalContent }), [modalContent]);
@@ -17071,8 +17121,6 @@ const ElementModal = React.memo(({ type = exports.WidgetType.Dashboard, elementC
17071
17121
  attributes,
17072
17122
  expandedContainers,
17073
17123
  }), [type, config, renderElementConfig, attributes, expandedContainers]);
17074
- const handleOpen = React.useCallback(() => setIsOpen(true), []);
17075
- const handleClose = React.useCallback(() => setIsOpen(false), []);
17076
17124
  if (!modalConfig)
17077
17125
  return null;
17078
17126
  const { options: modalOptions } = modalConfig;
@@ -17237,6 +17285,7 @@ const RangeNumberFilter = ({ type, filter }) => {
17237
17285
  const TextFilter = ({ type, filter }) => {
17238
17286
  const { filters, changeFilters, dataSources } = useWidgetContext(type);
17239
17287
  const { currentPage } = useWidgetPage(type);
17288
+ const configDataSources = useConfigDataSources(type);
17240
17289
  const suggestRef = React.useRef(null);
17241
17290
  const [totalCount, setTotalCount] = React.useState(0);
17242
17291
  const { attributes, layerInfo } = useRelatedDataSourceAttributes({
@@ -17244,7 +17293,7 @@ const TextFilter = ({ type, filter }) => {
17244
17293
  elementConfig: filter,
17245
17294
  dataSources,
17246
17295
  });
17247
- const { filters: configFilters, dataSources: configDataSources } = currentPage || {};
17296
+ const { filters: configFilters } = currentPage || {};
17248
17297
  const { filterName, searchFilterName, placeholder, width, height, multiSelect, variants, } = filter.options;
17249
17298
  const { eqlParameters } = (layerInfo?.configuration ||
17250
17299
  {});
@@ -18136,10 +18185,11 @@ const assembleTree = (nodes) => {
18136
18185
  const useTreeFilterData = (type, filterName) => {
18137
18186
  const { api } = useGlobalContext();
18138
18187
  const { currentPage } = useWidgetPage(type);
18188
+ const configDataSources = useConfigDataSources(type);
18139
18189
  const configFilter = React.useMemo(() => getConfigFilter(filterName, currentPage?.filters), [filterName, currentPage?.filters]);
18140
18190
  const { relatedDataSource, attributeName = DEFAULT_ATTRIBUTE_NAME, attributeValue, attributeAlias = DEFAULT_ATTRIBUTE_NAME, attributeParentName, attributeLevel, attributeHasChildren, limit = DEFAULT_DATA_SOURCE_LIMIT, } = configFilter ?? {};
18141
18191
  const valueAttribute = attributeValue ?? attributeName;
18142
- const dataSource = React.useMemo(() => currentPage?.dataSources?.find(({ name }) => name === relatedDataSource), [currentPage?.dataSources, relatedDataSource]);
18192
+ const dataSource = React.useMemo(() => configDataSources.find(({ name }) => name === relatedDataSource), [configDataSources, relatedDataSource]);
18143
18193
  const { layerName, query: sourceQuery, ds } = dataSource ?? {};
18144
18194
  const mapNode = React.useCallback(({ properties }) => {
18145
18195
  const hasChildren = attributeHasChildren ? !!properties[attributeHasChildren] : false;
@@ -20248,6 +20298,7 @@ exports.getLayerInfoAttribute = getLayerInfoAttribute;
20248
20298
  exports.getLayerInfoFromDataSources = getLayerInfoFromDataSources;
20249
20299
  exports.getLayoutChildren = getLayoutChildren;
20250
20300
  exports.getMapViewDataSources = getMapViewDataSources;
20301
+ exports.getModalsDataSources = getModalsDataSources;
20251
20302
  exports.getPagesFromConfig = getPagesFromConfig;
20252
20303
  exports.getPagesFromProjectInfo = getPagesFromProjectInfo;
20253
20304
  exports.getProjectValue = getProjectValue;
@@ -20331,6 +20382,7 @@ exports.useBeforeSave = useBeforeSave;
20331
20382
  exports.useBgImageHost = useBgImageHost;
20332
20383
  exports.useChartChange = useChartChange;
20333
20384
  exports.useChartData = useChartData;
20385
+ exports.useConfigDataSources = useConfigDataSources;
20334
20386
  exports.useContainerAttributes = useContainerAttributes;
20335
20387
  exports.useContainerRoot = useContainerRoot;
20336
20388
  exports.useCurrentPageLayers = useCurrentPageLayers;