@evergis/react 4.0.164 → 4.0.166

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/react.esm.js CHANGED
@@ -14199,21 +14199,124 @@ const StyledButton = styled(FlatButton).withConfig({ displayName: "StyledButton"
14199
14199
  `}
14200
14200
  `;
14201
14201
 
14202
- const StatusWaitingButton = ({ title, icon = "play", status, statusColors, isWaiting, isDisabled, onClick }) => {
14203
- const { t, themeName } = useGlobalContext();
14204
- const renderTitle = useMemo(() => status === RemoteTaskStatus.Process
14205
- ? t("", { ns: "dashboard", defaultValue: "Остановить" })
14206
- : status === RemoteTaskStatus.Unknown ? title : STATUS_TITLES[status], [status, t, title]);
14207
- const renderIcon = useMemo(() => {
14208
- const iconComponent = isWaiting ? (jsx(CircularProgress, { diameter: 1, mono: true }))
14209
- : status !== RemoteTaskStatus.Unknown
14210
- ? jsx(Icon, { kind: STATUS_ICONS[status] })
14211
- : jsx(Icon, { kind: icon });
14212
- return (jsx(Flex, { alignItems: "center", marginRight: renderTitle ? "0.5rem" : 0, children: iconComponent }));
14213
- }, [icon, isWaiting, renderTitle, status]);
14202
+ /** Текст и иконка кнопки запуска: в исходном состоянии — заданные, иначе — по статусу задачи. */
14203
+ const useTaskButtonState = ({ status, title, icon }) => {
14204
+ const { t } = useGlobalContext();
14205
+ const buttonTitle = useMemo(() => {
14206
+ if (status === RemoteTaskStatus.Process)
14207
+ return t("stop", { ns: "dashboard", defaultValue: "Остановить" });
14208
+ if (status === RemoteTaskStatus.Unknown)
14209
+ return title;
14210
+ return STATUS_TITLES[status];
14211
+ }, [status, t, title]);
14212
+ const iconKind = useMemo(() => (status === RemoteTaskStatus.Unknown ? icon : STATUS_ICONS[status]), [icon, status]);
14213
+ return { title: buttonTitle, iconKind };
14214
+ };
14215
+
14216
+ const StatusWaitingButton = ({ title, icon = "play", status, statusColors, isWaiting, isDisabled, onClick, }) => {
14217
+ const { themeName } = useGlobalContext();
14218
+ const { title: renderTitle, iconKind } = useTaskButtonState({ status, title, icon });
14219
+ const renderIcon = useMemo(() => (jsx(Flex, { alignItems: "center", marginRight: renderTitle ? "0.5rem" : 0, children: isWaiting ? jsx(CircularProgress, { diameter: 1, mono: true }) : jsx(Icon, { kind: iconKind }) })), [iconKind, isWaiting, renderTitle]);
14214
14220
  return (jsx(ThemeProvider, { theme: darkTheme, children: jsxs(StyledButton, { status: status, statusColors: statusColors, disabled: isDisabled, themeName: themeName, onClick: onClick, children: [renderIcon, renderTitle] }) }));
14215
14221
  };
14216
14222
 
14223
+ const ImageContainerButton = styled(FlatButton).withConfig({ displayName: "ImageContainerButton", componentId: "sc-nq6mg4" }) `
14224
+ min-height: 1.5rem;
14225
+ border-radius: ${({ theme: { borderRadius } }) => borderRadius.large};
14226
+ background-color: ${({ theme: { palette } }) => palette.primary};
14227
+ text-transform: none;
14228
+
14229
+ :hover {
14230
+ background-color: ${({ theme: { palette } }) => palette.primaryDeep};
14231
+ }
14232
+ `;
14233
+
14234
+ /** Опции внешнего вида: хотя бы одна из них переводит кнопку-ссылку на IconButton. */
14235
+ const ELEMENT_BUTTON_APPEARANCE_KEYS = [
14236
+ "variant",
14237
+ "color",
14238
+ "primary",
14239
+ "secondary",
14240
+ "error",
14241
+ "violet",
14242
+ "size",
14243
+ "shape",
14244
+ "radius",
14245
+ "icon",
14246
+ "iconRight",
14247
+ ];
14248
+ const ELEMENT_BUTTON_COLOR_FLAGS = ["primary", "secondary", "error", "violet"];
14249
+ const DEFAULT_ELEMENT_BUTTON_VARIANT = "solid";
14250
+
14251
+ const hasButtonAppearance = (options) => !!options && ELEMENT_BUTTON_APPEARANCE_KEYS.some(key => options[key] !== undefined);
14252
+ /**
14253
+ * Пропсы IconButton из опций элемента. Без цвета и флагов цвета кнопка — primary;
14254
+ * нейтральная задаётся явным `primary: false`. `color` контейнера перекрывает цвет из опций.
14255
+ */
14256
+ const getElementButtonProps = (options = {}, color) => {
14257
+ const { variant, primary, secondary, error, violet, size, shape, radius, icon, iconRight } = options;
14258
+ const buttonColor = color ?? options.color;
14259
+ const hasColor = buttonColor !== undefined || ELEMENT_BUTTON_COLOR_FLAGS.some(flag => options[flag] !== undefined);
14260
+ return {
14261
+ variant: variant ?? DEFAULT_ELEMENT_BUTTON_VARIANT,
14262
+ color: buttonColor,
14263
+ primary: hasColor ? primary : true,
14264
+ secondary,
14265
+ error,
14266
+ violet,
14267
+ size,
14268
+ shape,
14269
+ radius,
14270
+ kind: icon,
14271
+ iconRight,
14272
+ };
14273
+ };
14274
+
14275
+ const ElementButton = memo(({ type, elementConfig, title, icon, color, disabled, onClick }) => {
14276
+ const { attributes } = useWidgetContext(type);
14277
+ const { value, attributeName, options } = elementConfig || {};
14278
+ const link = useMemo(() => getAttributeByName(attributeName, attributes)?.value, [attributeName, attributes]);
14279
+ const buttonProps = useMemo(() => getElementButtonProps(options, color), [options, color]);
14280
+ const text = useMemo(() => title ?? (value === undefined || value === null ? "" : String(value)), [title, value]);
14281
+ const openLink = useCallback(() => window.open(link), [link]);
14282
+ if (!onClick && (!link || typeof link !== "string"))
14283
+ return null;
14284
+ if (!onClick && !hasButtonAppearance(options)) {
14285
+ return jsx(ImageContainerButton, { onClick: openLink, children: text });
14286
+ }
14287
+ return (jsx(IconButton, { ...buttonProps, icon: icon, disabled: disabled, tabIndex: 0, onClick: onClick ?? openLink, children: text || undefined }));
14288
+ });
14289
+
14290
+ /** Спиннер ожидания в цвете текста кнопки: круг-подложка приглушён, дуга — сплошная. */
14291
+ const TaskButtonSpinner = styled(Flex).withConfig({ displayName: "TaskButtonSpinner", componentId: "sc-192613c" }) `
14292
+ align-items: center;
14293
+
14294
+ circle {
14295
+ stroke: currentColor;
14296
+ }
14297
+
14298
+ circle:first-of-type {
14299
+ opacity: 0.3;
14300
+ }
14301
+ `;
14302
+
14303
+ /** Кнопка запуска из слота `button`: вид — из слота, поведение и статусы — от контейнера. */
14304
+ const TaskButton = ({ type, buttonConfig, title, icon, status, statusColors, isWaiting, isDisabled, onClick, }) => {
14305
+ const { value, options } = buttonConfig;
14306
+ const slotTitle = useMemo(() => (value === undefined || value === null || value === "" ? title : String(value)), [
14307
+ title,
14308
+ value,
14309
+ ]);
14310
+ const { title: buttonTitle, iconKind } = useTaskButtonState({ status, title: slotTitle, icon: options?.icon ?? icon });
14311
+ const buttonIcon = useMemo(() => {
14312
+ if (isWaiting) {
14313
+ return (jsx(TaskButtonSpinner, { children: jsx(CircularProgress, { diameter: 1 }) }));
14314
+ }
14315
+ return iconKind ? jsx(Icon, { kind: iconKind }) : undefined;
14316
+ }, [iconKind, isWaiting]);
14317
+ return (jsx(ElementButton, { type: type, elementConfig: buttonConfig, title: buttonTitle, icon: buttonIcon, color: statusColors?.[status], disabled: isDisabled, onClick: onClick }));
14318
+ };
14319
+
14217
14320
  const TaskContainerWrapper = styled(Flex).withConfig({ displayName: "TaskContainerWrapper", componentId: "sc-1hcp670" }) `
14218
14321
  ${sizeCssMixin};
14219
14322
  `;
@@ -14342,9 +14445,10 @@ const TaskContainer = memo(({ type, elementConfig, renderElement }) => {
14342
14445
  const { currentPage } = useWidgetPage(type);
14343
14446
  const dashboard = useDashboardFilterStore(type);
14344
14447
  const { taskId, runTask, stopTask, status, openLog, loading, isLogDialogOpen, closeLog, log, lastMessage, result, } = usePythonTask();
14345
- const { options } = elementConfig || {};
14448
+ const { options, children } = elementConfig || {};
14346
14449
  const { title, relatedResources, center, icon, statusColors, responseFilters, useNotifications, } = options || {};
14347
14450
  const { root, body } = useContainerRoot({ elementConfig });
14451
+ const buttonConfig = useMemo(() => children?.find((child) => child.id === "button"), [children]);
14348
14452
  const { setNotificationDismissed } = useTaskNotifications({
14349
14453
  enabled: !!useNotifications,
14350
14454
  suppressed: isLogDialogOpen,
@@ -14384,7 +14488,16 @@ const TaskContainer = memo(({ type, elementConfig, renderElement }) => {
14384
14488
  return runTask({ resourceId, parameters: newParams, script, fileName, methodName });
14385
14489
  }));
14386
14490
  }, [attributes, currentPage.filters, dashboard, dataSources, ewktGeometry, layerInfo, relatedResources, runTask, selectedFilters, stopTask, taskId]);
14387
- return (jsxs(ContainerRoot, { ...root, children: [jsx(ContainerBackground, { elementConfig: elementConfig, renderElement: renderElement }), jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), jsxs(TaskContainerWrapper, { ...body, 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 })] }))] })] }));
14491
+ const buttonProps = useMemo(() => ({
14492
+ title: title || t("run", { ns: "dashboard", defaultValue: "Запуск" }),
14493
+ icon,
14494
+ status,
14495
+ statusColors,
14496
+ isWaiting: loading || !!taskId,
14497
+ isDisabled: !relatedResources?.length,
14498
+ onClick,
14499
+ }), [icon, loading, onClick, relatedResources?.length, status, statusColors, t, taskId, title]);
14500
+ return (jsxs(ContainerRoot, { ...root, children: [jsx(ContainerBackground, { elementConfig: elementConfig, renderElement: renderElement }), jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }), jsxs(TaskContainerWrapper, { ...body, justifyContent: center ? "center" : "flex-start", children: [buttonConfig ? (jsx(TaskButton, { type: type, buttonConfig: buttonConfig, ...buttonProps })) : (jsx(StatusWaitingButton, { ...buttonProps })), !!(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 })] }))] })] }));
14388
14501
  });
14389
14502
 
14390
14503
  const EditContainer = ({ type, elementConfig, renderElement }) => {
@@ -15440,26 +15553,6 @@ const FeatureCardBackgroundHeader = () => {
15440
15553
  }) })] }) }) }));
15441
15554
  };
15442
15555
 
15443
- const ImageContainerButton = styled(FlatButton).withConfig({ displayName: "ImageContainerButton", componentId: "sc-nq6mg4" }) `
15444
- min-height: 1.5rem;
15445
- border-radius: ${({ theme: { borderRadius } }) => borderRadius.large};
15446
- background-color: ${({ theme: { palette } }) => palette.primary};
15447
- text-transform: none;
15448
-
15449
- :hover {
15450
- background-color: ${({ theme: { palette } }) => palette.primaryDeep};
15451
- }
15452
- `;
15453
-
15454
- const ElementButton = memo(({ type, elementConfig }) => {
15455
- const { attributes } = useWidgetContext(type);
15456
- const attribute = getAttributeByName(elementConfig?.attributeName, attributes);
15457
- const link = attribute?.value;
15458
- if (!link || typeof link !== "string")
15459
- return null;
15460
- return (jsx(ImageContainerButton, { onClick: () => window.open(attribute?.value), children: elementConfig.value || "" }));
15461
- });
15462
-
15463
15556
  const AttributeGalleryContainer = styled.div.withConfig({ displayName: "AttributeGalleryContainer", componentId: "sc-mhke7l" }) `
15464
15557
  && {
15465
15558
  width: calc(100% + 3rem);