@gen3/workspaces 0.12.65 → 0.12.67

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.
@@ -1,13 +1,14 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
2
  import React, { useCallback, useMemo, useState, useRef, useEffect, createContext, useImperativeHandle, forwardRef } from 'react';
3
3
  import { mergeDefaultTailwindClassnames, ACTIVITY_CHANNEL, convertSecondsToMilliseconds, InfoRolloverButton, OverflowTooltippedLabel, PanelErrorBoundary, ProtectedContent, FixedNavPageLayout, ContentSource, getNavPageLayoutPropsFromConfig } from '@gen3/frontend';
4
- import { Card, Stack, Badge, Text, List, Group, Tooltip, Button, Container, SimpleGrid, LoadingOverlay, Loader, Alert, Select, Divider, ActionIcon, TextInput, Textarea, Table, Scroller, Tabs, Center } from '@mantine/core';
4
+ import { Card, Stack, Badge, Text, List, Group, Tooltip, Button, Container, SimpleGrid, LoadingOverlay, Loader, Alert, Select, Divider, ActionIcon, Center, Popover, Accordion, Radio, Progress, TextInput, Textarea, Table, Scroller, Tabs } from '@mantine/core';
5
5
  import { Icon } from '@iconify-icon/react';
6
6
  import { useInterval, useElementSize, useDisclosure, useResizeObserver } from '@mantine/hooks';
7
- import { GEN3_API, GEN3_WORKSPACE_API, gen3Api, useCoreSelector, selectJEGActiveWorkspaceStatus, useCoreDispatch, setJEGActiveWorkspaceStatus, WorkspaceStatus, setJEGRequestedWorkspaceStatus, RequestedWorkspaceStatus, setJEGActiveWorkspaceId, isFetchBaseQueryError, selectJEGRequestedWorkspaceStatus, selectJEGRequestedWorkspaceStatusTimestamp, isTimeGreaterThan, formatUptimeInMinutes, selectJEGKernelIds, removeManyJEGActiveKernels, upsertManyJEGActiveKernels, normalizeRtkError, selectAllJEGKernels, addJEGActiveKernel, selectWorkspaceTier, setWorkspaceTier, selectWorkspaceFullscreen, setWorkspaceFullscreen, useGetDictionaryFromUrlQuery, useUserAuth, GEN3_COMMONS_NAME } from '@gen3/core';
8
- import { useDeepCompareEffect } from 'use-deep-compare';
7
+ import { GEN3_API, GEN3_WORKSPACE_API, gen3Api, useCoreSelector, selectJEGActiveWorkspaceStatus, useCoreDispatch, setJEGActiveWorkspaceStatus, WorkspaceStatus, setJEGRequestedWorkspaceStatus, RequestedWorkspaceStatus, setJEGActiveWorkspaceId, isFetchBaseQueryError, selectJEGRequestedWorkspaceStatus, selectJEGRequestedWorkspaceStatusTimestamp, isTimeGreaterThan, formatUptimeInMinutes, selectJEGKernelIds, removeManyJEGActiveKernels, upsertManyJEGActiveKernels, normalizeRtkError, selectAllJEGKernels, addJEGActiveKernel, selectWorkspaceTier, setWorkspaceTier, useGetWorkspacePayModelsQuery, useSetCurrentPayModelMutation, selectWorkspaceFullscreen, setWorkspaceFullscreen, useGetDictionaryFromUrlQuery, useUserAuth, GEN3_COMMONS_NAME } from '@gen3/core';
8
+ import { useDeepCompareEffect, useDeepCompareCallback, useDeepCompareMemo } from 'use-deep-compare';
9
9
  import { notifications } from '@mantine/notifications';
10
- import { MdExpandMore, MdKeyboardArrowDown, MdKeyboardArrowRight } from 'react-icons/md';
10
+ import { MdExpandMore, MdOpenInNew, MdKeyboardArrowDown, MdKeyboardArrowRight } from 'react-icons/md';
11
+ import { FaUser, FaExclamationCircle } from 'react-icons/fa';
11
12
  import { IoSettingsSharp } from 'react-icons/io5';
12
13
  import { BsFillInfoCircleFill } from 'react-icons/bs';
13
14
  import { merge } from 'lodash';
@@ -2425,11 +2426,239 @@ const SettingsPanel = ({ showKernels, expanded, setExpanded, width = 380 })=>{
2425
2426
  });
2426
2427
  };
2427
2428
 
2429
+ const PaymentNumberToString = (x, undefinedValue = 'N/A', precision = 2)=>{
2430
+ if (typeof x !== 'number' || Number.isNaN(x)) return undefinedValue;
2431
+ return x.toFixed(precision);
2432
+ };
2433
+ const isNoPayModelError = (error)=>{
2434
+ return 'status' in error && error.status === 'PARSING_ERROR' && error.originalStatus === 404;
2435
+ };
2436
+ const NoPayModel = ()=>{
2437
+ return /*#__PURE__*/ jsx(Group, {
2438
+ className: "p-2 border-1 border-l-0 border-r-0 border-base-lighter w-full h-16",
2439
+ justify: "space-between",
2440
+ children: /*#__PURE__*/ jsx(Text, {
2441
+ className: "pl-4",
2442
+ size: "md",
2443
+ classNames: {
2444
+ root: 'font-heading text-utility-warning'
2445
+ },
2446
+ children: "No pay model defined"
2447
+ })
2448
+ });
2449
+ };
2450
+ const CostTracker = ({ workspaceAccountManagerTarget = '' })=>{
2451
+ const { data, isLoading, isFetching, isError, error } = useGetWorkspacePayModelsQuery(undefined, {
2452
+ pollingInterval: 120000,
2453
+ refetchOnMountOrArgChange: true
2454
+ });
2455
+ const [setWorkspacePayModel] = useSetCurrentPayModelMutation();
2456
+ const [selectedPayModel, setSelectedPayModel] = useState(null);
2457
+ const [opened, setOpened] = useState(false);
2458
+ useDeepCompareCallback((id)=>{
2459
+ void setWorkspacePayModel(id); // triggers the call to the service to select the pay model
2460
+ setSelectedPayModel(id); // set the paymodel value for the select component
2461
+ }, [
2462
+ setWorkspacePayModel,
2463
+ selectedPayModel
2464
+ ]);
2465
+ const { usersPayModels, workspaceName, hardLimit, totalUsage } = useDeepCompareMemo(()=>{
2466
+ if (!data) return {
2467
+ usersPayModels: [],
2468
+ selectedPayModel: [],
2469
+ workspaceName: 'Not Set',
2470
+ totalUsage: undefined,
2471
+ hardLimit: undefined
2472
+ };
2473
+ const usersPayModels = data.allPayModels.map((payModel)=>{
2474
+ return {
2475
+ value: payModel.bmh_workspace_id ?? payModel.workspace_type,
2476
+ label: payModel.workspace_type,
2477
+ totalUsage: payModel['total-usage'],
2478
+ currentPayModel: payModel['current_pay_model'],
2479
+ icon: payModel.request_status === 'active' ? /*#__PURE__*/ jsx(FaUser, {}) : /*#__PURE__*/ jsx(FaExclamationCircle, {})
2480
+ };
2481
+ });
2482
+ setSelectedPayModel(data.currentPayModel.bmh_workspace_id ?? data.currentPayModel.workspace_type);
2483
+ return {
2484
+ usersPayModels,
2485
+ workspaceName: data.currentPayModel.bmh_workspace_id.length > 0 ? data.currentPayModel.bmh_workspace_id : data.currentPayModel.workspace_type,
2486
+ totalUsage: data.currentPayModel['total-usage'],
2487
+ hardLimit: data.currentPayModel['hard-limit']
2488
+ };
2489
+ }, [
2490
+ data
2491
+ ]);
2492
+ if (isLoading && isFetching) return /*#__PURE__*/ jsx("div", {
2493
+ className: "flex justify-center p-2 border-1 border-l-0 border-r-0 border-base-lighter w-full h-14",
2494
+ children: /*#__PURE__*/ jsx(Loader, {})
2495
+ });
2496
+ if (isError) {
2497
+ if (isNoPayModelError(error)) {
2498
+ return /*#__PURE__*/ jsx(NoPayModel, {});
2499
+ } else return /*#__PURE__*/ jsx(Center, {
2500
+ children: "Unable to get Payment information"
2501
+ });
2502
+ }
2503
+ const ProgressBar = (className = '')=>/*#__PURE__*/ jsx(Progress, {
2504
+ size: "sm",
2505
+ radius: "xl",
2506
+ "aria-label": "Monthly Workflow Limit",
2507
+ value: !hardLimit ? 100 : hardLimit / totalUsage * 100,
2508
+ color: !hardLimit || totalUsage >= hardLimit ? 'red.5' : 'green.1',
2509
+ className: className
2510
+ });
2511
+ return /*#__PURE__*/ jsxs(Popover, {
2512
+ width: "target",
2513
+ position: "bottom",
2514
+ shadow: "lg",
2515
+ trapFocus: true,
2516
+ opened: opened,
2517
+ onChange: setOpened,
2518
+ children: [
2519
+ /*#__PURE__*/ jsx(Popover.Target, {
2520
+ children: /*#__PURE__*/ jsxs(Button, {
2521
+ onClick: ()=>setOpened((o)=>!o),
2522
+ size: "xs",
2523
+ radius: "xl",
2524
+ variant: "default",
2525
+ className: "h-[--badge-height]",
2526
+ rightSection: /*#__PURE__*/ jsx(MdExpandMore, {
2527
+ className: "text-accent",
2528
+ size: "1.5em",
2529
+ "aria-label": opened ? 'close' : 'open',
2530
+ style: {
2531
+ transform: opened ? 'rotate(180deg)' : 'rotate(0deg)',
2532
+ transition: 'transform 200ms ease'
2533
+ }
2534
+ }),
2535
+ children: [
2536
+ ProgressBar('w-[110px]'),
2537
+ /*#__PURE__*/ jsxs("span", {
2538
+ className: "font-black pl-3 pr-2",
2539
+ children: [
2540
+ "$",
2541
+ PaymentNumberToString(totalUsage)
2542
+ ]
2543
+ }),
2544
+ /*#__PURE__*/ jsxs("span", {
2545
+ className: "font-normal",
2546
+ children: [
2547
+ "/$",
2548
+ PaymentNumberToString(hardLimit)
2549
+ ]
2550
+ })
2551
+ ]
2552
+ })
2553
+ }),
2554
+ /*#__PURE__*/ jsxs(Popover.Dropdown, {
2555
+ className: "px-2",
2556
+ children: [
2557
+ workspaceAccountManagerTarget && /*#__PURE__*/ jsx(Button, {
2558
+ component: "a",
2559
+ href: workspaceAccountManagerTarget,
2560
+ target: "_blank",
2561
+ variant: "outline",
2562
+ leftSection: /*#__PURE__*/ jsx(MdOpenInNew, {
2563
+ size: "1.1em",
2564
+ "aria-label": "external"
2565
+ }),
2566
+ size: "xs",
2567
+ className: "w-full mb-4",
2568
+ children: "Workspace Account Manager"
2569
+ }),
2570
+ /*#__PURE__*/ jsxs(Text, {
2571
+ size: "sm",
2572
+ className: "uppercase pb-2 px-2",
2573
+ children: [
2574
+ "Limit ",
2575
+ /*#__PURE__*/ jsxs("span", {
2576
+ className: "font-black pl-1",
2577
+ children: [
2578
+ "$",
2579
+ PaymentNumberToString(hardLimit)
2580
+ ]
2581
+ })
2582
+ ]
2583
+ }),
2584
+ ProgressBar('mx-2'),
2585
+ /*#__PURE__*/ jsx(Divider, {
2586
+ my: "sm"
2587
+ }),
2588
+ /*#__PURE__*/ jsx(Text, {
2589
+ size: "sm",
2590
+ className: "uppercase pb-2 px-2",
2591
+ children: "Account & Charges"
2592
+ }),
2593
+ /*#__PURE__*/ jsx(Accordion, {
2594
+ variant: "unstyled",
2595
+ classNames: {
2596
+ root: '',
2597
+ control: 'p-0 px-2',
2598
+ label: 'p-0',
2599
+ chevron: 'text-accent',
2600
+ panel: 'p-0',
2601
+ content: 'p-0'
2602
+ },
2603
+ children: /*#__PURE__*/ jsxs(Accordion.Item, {
2604
+ value: "accountInformation",
2605
+ children: [
2606
+ /*#__PURE__*/ jsx(Accordion.Control, {
2607
+ children: /*#__PURE__*/ jsxs(Text, {
2608
+ size: "sm",
2609
+ className: "font-black",
2610
+ children: [
2611
+ workspaceName,
2612
+ " - $",
2613
+ PaymentNumberToString(totalUsage)
2614
+ ]
2615
+ })
2616
+ }),
2617
+ /*#__PURE__*/ jsx(Accordion.Panel, {
2618
+ children: /*#__PURE__*/ jsx(Radio.Group, {
2619
+ className: "pt-2",
2620
+ children: usersPayModels.map((obj)=>/*#__PURE__*/ jsx(Radio.Card, {
2621
+ checked: obj.currentPayModel,
2622
+ disabled: true,
2623
+ className: "p-2 border-none data-checked:bg-primary-lightest data-checked:border-primary-darker data-checked:font-black hover:bg-primary-max ",
2624
+ children: /*#__PURE__*/ jsxs(Group, {
2625
+ wrap: "nowrap",
2626
+ align: "flex-start",
2627
+ children: [
2628
+ /*#__PURE__*/ jsx(Text, {
2629
+ size: "sm",
2630
+ className: "grow",
2631
+ children: obj.label
2632
+ }),
2633
+ /*#__PURE__*/ jsxs(Text, {
2634
+ size: "sm",
2635
+ children: [
2636
+ "$",
2637
+ PaymentNumberToString(obj.totalUsage)
2638
+ ]
2639
+ }),
2640
+ /*#__PURE__*/ jsx(Radio.Indicator, {
2641
+ color: "accent"
2642
+ })
2643
+ ]
2644
+ })
2645
+ }, obj.value))
2646
+ })
2647
+ })
2648
+ ]
2649
+ })
2650
+ })
2651
+ ]
2652
+ })
2653
+ ]
2654
+ });
2655
+ };
2656
+
2428
2657
  const WorkspaceToolbar = /*#__PURE__*/ forwardRef(({ toolbarConfiguration }, ref)=>{
2429
2658
  const workspaceTier = useCoreSelector((state)=>selectWorkspaceTier(state));
2430
2659
  const workspaceStatus = useCoreSelector((state)=>selectJEGActiveWorkspaceStatus(state));
2431
2660
  const isFullscreen = useCoreSelector((state)=>selectWorkspaceFullscreen(state));
2432
- const { showStatus, showStop, tierLabel } = toolbarConfiguration || {};
2661
+ const { showStatus, showStop, tierLabel, requirePayModel, workspaceAccountManagerTarget } = toolbarConfiguration || {};
2433
2662
  const coreDispatch = useCoreDispatch();
2434
2663
  const toggleFullscreen = useCallback(()=>{
2435
2664
  coreDispatch(setWorkspaceFullscreen(!isFullscreen));
@@ -2484,6 +2713,9 @@ const WorkspaceToolbar = /*#__PURE__*/ forwardRef(({ toolbarConfiguration }, ref
2484
2713
  /*#__PURE__*/ jsx(Badge, {
2485
2714
  "aria-label": `Workspace tier: ${tierLabel ?? workspaceTier}`,
2486
2715
  children: tierLabel ?? workspaceTier
2716
+ }),
2717
+ requirePayModel && /*#__PURE__*/ jsx(CostTracker, {
2718
+ workspaceAccountManagerTarget: workspaceAccountManagerTarget
2487
2719
  })
2488
2720
  ]
2489
2721
  })