@evergis/react 4.0.62 → 4.0.64
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/componentTypes.d.ts +1 -1
- package/dist/components/Dashboard/containers/TaskContainer/components/LogDialog/types.d.ts +1 -0
- package/dist/components/Dashboard/containers/TaskContainer/useTaskNotifications.d.ts +12 -0
- package/dist/components/Dashboard/containers/TaskContainer/utils/clampDescription.d.ts +2 -0
- package/dist/components/Dashboard/hooks/useGlobalContext.d.ts +7 -0
- package/dist/components/Dashboard/types.d.ts +1 -0
- package/dist/contexts/GlobalContext/types.d.ts +8 -0
- package/dist/hooks/task/usePythonTask.d.ts +1 -0
- package/dist/index.js +136 -17
- package/dist/index.js.map +1 -1
- package/dist/react.esm.js +137 -18
- package/dist/react.esm.js.map +1 -1
- package/package.json +3 -3
package/dist/react.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
2
2
|
import { IconButton, Flex, transition, Chip, Icon, Description, FlexSpan, IconToggle, Popup, Menu, DraggableTree, shadows, Divider, LegendToggler, Tooltip as Tooltip$1, DropdownField, MultiSelectContainer, IconButtonButton, FlatButton, DraggableTreeContainer, Dialog, DialogTitle, ThemeProvider, darkTheme, DialogContent, CircularProgress, Switch, AutoComplete, Input, Slider, Dropdown, Checkbox, DatePicker, getLocale, IconToggleButton, LinearProgress, ActionsGroup, DialogActions, RaisedButton, Preview, H2, Blank, Popover, UploaderItemArea, UploaderTitleWrapper, Uploader, NumberRangeSlider, useAsyncAutocomplete, RangeNumberInput, defaultTheme, dateFormat } from '@evergis/uilib-gl';
|
|
3
|
-
import { createContext, memo, useRef, useState, useCallback, useEffect, useContext, useMemo, isValidElement, Fragment } from 'react';
|
|
3
|
+
import { createContext, memo, useRef, useState, useCallback, useEffect, useContext, useMemo, isValidElement, Fragment, createElement } from 'react';
|
|
4
4
|
import styled, { createGlobalStyle, css, useTheme } from 'styled-components';
|
|
5
5
|
import { lineChartClassNames, BarChart as BarChart$1, barChartClassNames, LineChart, PieChart } from '@evergis/charts';
|
|
6
6
|
import { AttributeType, generateId, STORAGE_TOKEN_KEY, parseJwt, STORAGE_REFRESH_TOKEN_KEY, RemoteTaskStatus, LayerServiceType, OgcGeometryType, StringSubType, AttributeConfigurationType } from '@evergis/api';
|
|
@@ -4215,7 +4215,7 @@ const useAttachmentItems = ({ type, elementConfig, valueOverride, }) => {
|
|
|
4215
4215
|
};
|
|
4216
4216
|
|
|
4217
4217
|
const useGlobalContext = () => {
|
|
4218
|
-
const { t, language, themeName, api, ewktGeometry } = useContext(GlobalContext) || {};
|
|
4218
|
+
const { t, language, themeName, api, ewktGeometry, notification } = useContext(GlobalContext) || {};
|
|
4219
4219
|
const translate = useCallback((value, options) => {
|
|
4220
4220
|
if (t)
|
|
4221
4221
|
return t(value, options);
|
|
@@ -4227,7 +4227,8 @@ const useGlobalContext = () => {
|
|
|
4227
4227
|
themeName,
|
|
4228
4228
|
api,
|
|
4229
4229
|
ewktGeometry,
|
|
4230
|
-
|
|
4230
|
+
notification,
|
|
4231
|
+
}), [language, translate, api, ewktGeometry, themeName, notification]);
|
|
4231
4232
|
};
|
|
4232
4233
|
|
|
4233
4234
|
const GRID_TILE_SIZE = "4.5rem";
|
|
@@ -5620,6 +5621,7 @@ const usePythonTask = () => {
|
|
|
5620
5621
|
const { preparePythonSandbox } = usePythonSandbox();
|
|
5621
5622
|
const [status, setStatus] = useState(RemoteTaskStatus.Unknown);
|
|
5622
5623
|
const [log, setLog] = useState(null);
|
|
5624
|
+
const [lastMessage, setLastMessage] = useState(null);
|
|
5623
5625
|
const [error, setError] = useState(null);
|
|
5624
5626
|
const [loading, setLoading] = useState(false);
|
|
5625
5627
|
const [executionTime, setExecutionTime] = useState(null);
|
|
@@ -5627,7 +5629,6 @@ const usePythonTask = () => {
|
|
|
5627
5629
|
const [subscriptionId, setSubscriptionId] = useState(null);
|
|
5628
5630
|
const [isLogDialogOpen, setIsLogDialogOpen] = useState(false);
|
|
5629
5631
|
const [result, setResult] = useState(null);
|
|
5630
|
-
const logRef = useRef(null);
|
|
5631
5632
|
const reset = useCallback(() => {
|
|
5632
5633
|
setStatus(RemoteTaskStatus.Unknown);
|
|
5633
5634
|
setError(null);
|
|
@@ -5641,6 +5642,7 @@ const usePythonTask = () => {
|
|
|
5641
5642
|
reset();
|
|
5642
5643
|
setStatus(RemoteTaskStatus.Process);
|
|
5643
5644
|
setLog(null);
|
|
5645
|
+
setLastMessage(null);
|
|
5644
5646
|
setLoading(true);
|
|
5645
5647
|
const start = Date.now();
|
|
5646
5648
|
let prototypeId = await api.remoteTaskManager.createTaskPrototype({
|
|
@@ -5680,7 +5682,9 @@ const usePythonTask = () => {
|
|
|
5680
5682
|
if (data?.taskId === newTaskId) {
|
|
5681
5683
|
const isFinished = [RemoteTaskStatus.Completed, RemoteTaskStatus.Error].includes(data.status);
|
|
5682
5684
|
setStatus(data.status);
|
|
5683
|
-
setLog([
|
|
5685
|
+
setLog(prev => [prev, data.log].filter(Boolean).join(""));
|
|
5686
|
+
if (data.log)
|
|
5687
|
+
setLastMessage(data.log);
|
|
5684
5688
|
setExecutionTime(Date.now() - start);
|
|
5685
5689
|
setLoading(false);
|
|
5686
5690
|
setTaskId(isFinished ? null : newTaskId);
|
|
@@ -5724,15 +5728,13 @@ const usePythonTask = () => {
|
|
|
5724
5728
|
const closeLog = useCallback(() => {
|
|
5725
5729
|
setIsLogDialogOpen(false);
|
|
5726
5730
|
}, []);
|
|
5727
|
-
useEffect(() => {
|
|
5728
|
-
logRef.current = log;
|
|
5729
|
-
}, [log]);
|
|
5730
5731
|
return {
|
|
5731
5732
|
taskId,
|
|
5732
5733
|
runTask,
|
|
5733
5734
|
stopTask,
|
|
5734
5735
|
openLog,
|
|
5735
5736
|
log,
|
|
5737
|
+
lastMessage,
|
|
5736
5738
|
error,
|
|
5737
5739
|
status,
|
|
5738
5740
|
loading,
|
|
@@ -7633,17 +7635,17 @@ const STATUS_ICONS = {
|
|
|
7633
7635
|
[RemoteTaskStatus.Unknown]: "play",
|
|
7634
7636
|
};
|
|
7635
7637
|
|
|
7636
|
-
const LogDialog = ({ isOpen, onClose, logs, status, statusColors }) => {
|
|
7638
|
+
const LogDialog = ({ isOpen, onClose, onMinimize, logs, status, statusColors }) => {
|
|
7637
7639
|
const { t } = useGlobalContext();
|
|
7638
|
-
const getStatusTitle = useCallback((
|
|
7639
|
-
const translationKey = STATUS_TRANSLATION_KEYS[
|
|
7640
|
-
const defaultValue = STATUS_TITLES[
|
|
7640
|
+
const getStatusTitle = useCallback((currentStatus) => {
|
|
7641
|
+
const translationKey = STATUS_TRANSLATION_KEYS[currentStatus] || STATUS_TRANSLATION_KEYS[RemoteTaskStatus.Unknown];
|
|
7642
|
+
const defaultValue = STATUS_TITLES[currentStatus] || STATUS_TITLES[RemoteTaskStatus.Unknown];
|
|
7641
7643
|
return t(translationKey, { ns: "dashboard", defaultValue });
|
|
7642
7644
|
}, [t]);
|
|
7643
|
-
const getStatusColor = useCallback((
|
|
7644
|
-
return statusColors?.[
|
|
7645
|
+
const getStatusColor = useCallback((currentStatus) => {
|
|
7646
|
+
return statusColors?.[currentStatus] || STATUS_COLORS[currentStatus] || STATUS_COLORS[RemoteTaskStatus.Unknown];
|
|
7645
7647
|
}, [statusColors]);
|
|
7646
|
-
return (jsxs(Dialog, { isOpen: isOpen, onCloseRequest: onClose, modal: true, maxWidth: "800px", minWidth: "600px", minHeight: "600px", children: [jsx(DialogTitle, { children: jsxs(Flex, { justifyContent: "space-between", alignItems: "center", children: [jsxs(Flex, { alignItems: "center", children: [jsx(FlexSpan, { marginRight: "1rem", children: t("taskLogs", { ns: "dashboard", defaultValue: "Логи выполнения задачи" }) }), jsx(ThemeProvider, { theme: darkTheme, children: jsx(StatusBadge, { text: getStatusTitle(status), bgColor: getStatusColor(status) }) })] }), jsx(IconButton, { kind: "close", onClick: onClose })] }) }), jsx(DialogContent, { children: jsx(Flex, { flexDirection: "column", height: "100%", marginBottom: "2rem", children: jsx(LogTerminal, { log: logs || t("taskLogsEmpty", { ns: "dashboard", defaultValue: "Логи отсутствуют" }) }) }) })] }));
|
|
7648
|
+
return (jsxs(Dialog, { isOpen: isOpen, onCloseRequest: onClose, modal: true, maxWidth: "800px", minWidth: "600px", minHeight: "600px", children: [jsx(DialogTitle, { children: jsxs(Flex, { justifyContent: "space-between", alignItems: "center", children: [jsxs(Flex, { alignItems: "center", children: [jsx(FlexSpan, { marginRight: "1rem", children: t("taskLogs", { ns: "dashboard", defaultValue: "Логи выполнения задачи" }) }), jsx(ThemeProvider, { theme: darkTheme, children: jsx(StatusBadge, { text: getStatusTitle(status), bgColor: getStatusColor(status) }) })] }), jsxs(Flex, { alignItems: "center", width: "auto", children: [onMinimize && jsx(IconButton, { kind: "change_geom", onClick: onMinimize }), jsx(IconButton, { kind: "close", onClick: onClose })] })] }) }), jsx(DialogContent, { children: jsx(Flex, { flexDirection: "column", height: "100%", marginBottom: "2rem", children: jsx(LogTerminal, { log: logs || t("taskLogsEmpty", { ns: "dashboard", defaultValue: "Логи отсутствуют" }) }) }) })] }));
|
|
7647
7649
|
};
|
|
7648
7650
|
|
|
7649
7651
|
var ThemeName;
|
|
@@ -7706,14 +7708,131 @@ const buildFiltersFromResponse = (responseFilters, result) => {
|
|
|
7706
7708
|
return Object.keys(filters).length ? filters : null;
|
|
7707
7709
|
};
|
|
7708
7710
|
|
|
7711
|
+
const ClampedText = styled.div `
|
|
7712
|
+
display: -webkit-box;
|
|
7713
|
+
-webkit-line-clamp: 2;
|
|
7714
|
+
-webkit-box-orient: vertical;
|
|
7715
|
+
overflow: hidden;
|
|
7716
|
+
text-overflow: ellipsis;
|
|
7717
|
+
word-break: break-word;
|
|
7718
|
+
`;
|
|
7719
|
+
const clampDescription = (text) => createElement(ClampedText, null, text);
|
|
7720
|
+
|
|
7721
|
+
const RUN_ID_RADIX = 36;
|
|
7722
|
+
const RUN_ID_LENGTH = 8;
|
|
7723
|
+
const generateRunId = () => `task-${Date.now()}-${Math.random().toString(RUN_ID_RADIX).slice(2, RUN_ID_LENGTH)}`;
|
|
7724
|
+
const useTaskNotifications = ({ enabled, suppressed, status, lastMessage, openLog, }) => {
|
|
7725
|
+
const { t, notification } = useGlobalContext();
|
|
7726
|
+
const runIdRef = useRef(null);
|
|
7727
|
+
const prevStatusRef = useRef(RemoteTaskStatus.Unknown);
|
|
7728
|
+
const isVisibleRef = useRef(false);
|
|
7729
|
+
const [dismissed, setDismissed] = useState(false);
|
|
7730
|
+
useEffect(() => {
|
|
7731
|
+
if (!enabled) {
|
|
7732
|
+
if (runIdRef.current) {
|
|
7733
|
+
notification?.close(runIdRef.current);
|
|
7734
|
+
runIdRef.current = null;
|
|
7735
|
+
}
|
|
7736
|
+
isVisibleRef.current = false;
|
|
7737
|
+
prevStatusRef.current = status;
|
|
7738
|
+
return;
|
|
7739
|
+
}
|
|
7740
|
+
if (status === RemoteTaskStatus.Unknown) {
|
|
7741
|
+
prevStatusRef.current = status;
|
|
7742
|
+
return;
|
|
7743
|
+
}
|
|
7744
|
+
const isFreshRun = status === RemoteTaskStatus.Process && prevStatusRef.current !== RemoteTaskStatus.Process;
|
|
7745
|
+
if (isFreshRun) {
|
|
7746
|
+
runIdRef.current = generateRunId();
|
|
7747
|
+
isVisibleRef.current = false;
|
|
7748
|
+
setDismissed(false);
|
|
7749
|
+
}
|
|
7750
|
+
if (!runIdRef.current) {
|
|
7751
|
+
runIdRef.current = generateRunId();
|
|
7752
|
+
}
|
|
7753
|
+
const id = runIdRef.current;
|
|
7754
|
+
const description = clampDescription(lastMessage || t("taskStarted", { ns: "dashboard", defaultValue: "Запуск задачи…" }));
|
|
7755
|
+
const base = {
|
|
7756
|
+
id,
|
|
7757
|
+
title: "",
|
|
7758
|
+
description,
|
|
7759
|
+
duration: Number.MAX_SAFE_INTEGER,
|
|
7760
|
+
...(lastMessage ? {
|
|
7761
|
+
button: t("details", { ns: "dashboard", defaultValue: "Подробнее" }),
|
|
7762
|
+
buttonIcon: "info",
|
|
7763
|
+
buttonColor: "primary",
|
|
7764
|
+
onButtonClick: openLog,
|
|
7765
|
+
} : {}),
|
|
7766
|
+
};
|
|
7767
|
+
let item = null;
|
|
7768
|
+
if (status === RemoteTaskStatus.Process) {
|
|
7769
|
+
item = {
|
|
7770
|
+
...base,
|
|
7771
|
+
title: t("taskInProgress", { ns: "dashboard", defaultValue: "Выполняется" }),
|
|
7772
|
+
progress: true,
|
|
7773
|
+
};
|
|
7774
|
+
}
|
|
7775
|
+
else if (status === RemoteTaskStatus.Completed) {
|
|
7776
|
+
item = {
|
|
7777
|
+
...base,
|
|
7778
|
+
title: t("taskCompleted", { ns: "dashboard", defaultValue: "Выполнено" }),
|
|
7779
|
+
success: true,
|
|
7780
|
+
progress: false,
|
|
7781
|
+
};
|
|
7782
|
+
}
|
|
7783
|
+
else if (status === RemoteTaskStatus.Error) {
|
|
7784
|
+
item = {
|
|
7785
|
+
...base,
|
|
7786
|
+
title: t("taskError", { ns: "dashboard", defaultValue: "Ошибка" }),
|
|
7787
|
+
error: true,
|
|
7788
|
+
progress: false,
|
|
7789
|
+
};
|
|
7790
|
+
}
|
|
7791
|
+
if (!item) {
|
|
7792
|
+
prevStatusRef.current = status;
|
|
7793
|
+
return;
|
|
7794
|
+
}
|
|
7795
|
+
if (suppressed || dismissed) {
|
|
7796
|
+
if (isVisibleRef.current) {
|
|
7797
|
+
notification?.close(id);
|
|
7798
|
+
isVisibleRef.current = false;
|
|
7799
|
+
}
|
|
7800
|
+
}
|
|
7801
|
+
else if (isVisibleRef.current) {
|
|
7802
|
+
notification?.update(item);
|
|
7803
|
+
}
|
|
7804
|
+
else {
|
|
7805
|
+
notification?.add(item);
|
|
7806
|
+
isVisibleRef.current = true;
|
|
7807
|
+
}
|
|
7808
|
+
prevStatusRef.current = status;
|
|
7809
|
+
}, [enabled, suppressed, dismissed, status, lastMessage, openLog, t, notification]);
|
|
7810
|
+
return { setNotificationDismissed: setDismissed };
|
|
7811
|
+
};
|
|
7812
|
+
|
|
7709
7813
|
const TaskContainer = memo(({ type, elementConfig, renderElement }) => {
|
|
7710
7814
|
const { t, ewktGeometry } = useGlobalContext();
|
|
7711
7815
|
const { dataSources, filters: selectedFilters, attributes, layerInfo, changeFilters, } = useWidgetContext(type);
|
|
7712
7816
|
const { dataSources: projectDataSources } = useWidgetContext(WidgetType.Dashboard);
|
|
7713
7817
|
const { currentPage } = useWidgetPage(type);
|
|
7714
|
-
const { taskId, runTask, stopTask, status, openLog, loading, isLogDialogOpen, closeLog, log, result, } = usePythonTask();
|
|
7818
|
+
const { taskId, runTask, stopTask, status, openLog, loading, isLogDialogOpen, closeLog, log, lastMessage, result, } = usePythonTask();
|
|
7715
7819
|
const { options } = elementConfig || {};
|
|
7716
|
-
const { title, relatedResources, center, icon, statusColors, responseFilters } = options || {};
|
|
7820
|
+
const { title, relatedResources, center, icon, statusColors, responseFilters, useNotifications, } = options || {};
|
|
7821
|
+
const { setNotificationDismissed } = useTaskNotifications({
|
|
7822
|
+
enabled: !!useNotifications,
|
|
7823
|
+
suppressed: isLogDialogOpen,
|
|
7824
|
+
status,
|
|
7825
|
+
lastMessage,
|
|
7826
|
+
openLog,
|
|
7827
|
+
});
|
|
7828
|
+
const onCloseLog = useCallback(() => {
|
|
7829
|
+
setNotificationDismissed(true);
|
|
7830
|
+
closeLog();
|
|
7831
|
+
}, [closeLog, setNotificationDismissed]);
|
|
7832
|
+
const onMinimizeLog = useCallback(() => {
|
|
7833
|
+
setNotificationDismissed(false);
|
|
7834
|
+
closeLog();
|
|
7835
|
+
}, [closeLog, setNotificationDismissed]);
|
|
7717
7836
|
useEffect(() => {
|
|
7718
7837
|
const filtersToApply = buildFiltersFromResponse(responseFilters, result);
|
|
7719
7838
|
if (filtersToApply)
|
|
@@ -7738,7 +7857,7 @@ const TaskContainer = memo(({ type, elementConfig, renderElement }) => {
|
|
|
7738
7857
|
return runTask({ resourceId, parameters: newParams, script, fileName, methodName });
|
|
7739
7858
|
}));
|
|
7740
7859
|
}, [attributes, currentPage.filters, dataSources, ewktGeometry, layerInfo, projectDataSources, relatedResources, runTask, selectedFilters, stopTask, taskId]);
|
|
7741
|
-
return (jsxs(Fragment$1, { children: [jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), jsxs(Flex, { justifyContent: center ? "center" : "flex-start", children: [jsx(StatusWaitingButton, { title: title || t("run", { ns: "dashboard", defaultValue: "Запуск" }), icon: icon, status: status, statusColors: statusColors, isWaiting: loading || !!taskId, isDisabled: !relatedResources?.length, onClick: onClick }), !!(log || taskId) && (jsxs(Fragment$1, { children: [jsx(IconButton, { kind: "info", onClick: openLog }), jsx(LogDialog, { logs: log, status: status, statusColors: statusColors, isOpen: isLogDialogOpen, onClose:
|
|
7860
|
+
return (jsxs(Fragment$1, { children: [jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), jsxs(Flex, { justifyContent: center ? "center" : "flex-start", children: [jsx(StatusWaitingButton, { title: title || t("run", { ns: "dashboard", defaultValue: "Запуск" }), icon: icon, status: status, statusColors: statusColors, isWaiting: loading || !!taskId, isDisabled: !relatedResources?.length, onClick: onClick }), !!(log || taskId) && (jsxs(Fragment$1, { children: [jsx(IconButton, { kind: "info", onClick: openLog }), jsx(LogDialog, { logs: log, status: status, statusColors: statusColors, isOpen: isLogDialogOpen, onClose: onCloseLog, onMinimize: useNotifications ? onMinimizeLog : undefined })] }))] })] }));
|
|
7742
7861
|
});
|
|
7743
7862
|
|
|
7744
7863
|
const EditContainer = ({ type, elementConfig, renderElement }) => {
|