@gen3/workspaces 0.12.66 → 0.12.68

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, Popover, Accordion, Radio, Progress, TextInput, Textarea, Table, Scroller, Tabs, Center } 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,286 @@ 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 CostTracker = ({ workspaceAccountManagerTarget = '' })=>{
2437
+ const { data, isLoading, isFetching, isError, error } = useGetWorkspacePayModelsQuery(undefined, {
2438
+ pollingInterval: 120000,
2439
+ refetchOnMountOrArgChange: true
2440
+ });
2441
+ const [setWorkspacePayModel] = useSetCurrentPayModelMutation();
2442
+ const [selectedPayModel, setSelectedPayModel] = useState(null);
2443
+ const [opened, setOpened] = useState(false);
2444
+ useDeepCompareCallback((id)=>{
2445
+ void setWorkspacePayModel(id); // triggers the call to the service to select the pay model
2446
+ setSelectedPayModel(id); // set the paymodel value for the select component
2447
+ }, [
2448
+ setWorkspacePayModel,
2449
+ selectedPayModel
2450
+ ]);
2451
+ const { usersPayModels, workspaceName, hardLimit, totalUsage } = useDeepCompareMemo(()=>{
2452
+ if (!data) return {
2453
+ usersPayModels: [],
2454
+ selectedPayModel: [],
2455
+ workspaceName: 'Not Set',
2456
+ totalUsage: undefined,
2457
+ hardLimit: undefined
2458
+ };
2459
+ const usersPayModels = data.allPayModels.map((payModel)=>{
2460
+ return {
2461
+ value: payModel.bmh_workspace_id ?? payModel.workspace_type,
2462
+ label: payModel.workspace_type,
2463
+ totalUsage: payModel['total-usage'],
2464
+ currentPayModel: payModel['current_pay_model'],
2465
+ icon: payModel.request_status === 'active' ? /*#__PURE__*/ jsx(FaUser, {}) : /*#__PURE__*/ jsx(FaExclamationCircle, {})
2466
+ };
2467
+ });
2468
+ setSelectedPayModel(data.currentPayModel.bmh_workspace_id ?? data.currentPayModel.workspace_type);
2469
+ return {
2470
+ usersPayModels,
2471
+ workspaceName: data.currentPayModel.bmh_workspace_id.length > 0 ? data.currentPayModel.bmh_workspace_id : data.currentPayModel.workspace_type,
2472
+ totalUsage: data.currentPayModel['total-usage'],
2473
+ hardLimit: data.currentPayModel['hard-limit']
2474
+ };
2475
+ }, [
2476
+ data
2477
+ ]);
2478
+ if (isLoading && isFetching) return /*#__PURE__*/ jsx(Badge, {
2479
+ leftSection: /*#__PURE__*/ jsx(Loader, {
2480
+ size: "xs",
2481
+ type: "dots",
2482
+ className: "m-1"
2483
+ }),
2484
+ variant: "default",
2485
+ children: "Loading..."
2486
+ });
2487
+ const PayModelError = (message)=>{
2488
+ // dropdown error state to provide user access to Account Manager if available
2489
+ if (workspaceAccountManagerTarget) {
2490
+ return /*#__PURE__*/ jsxs(Popover, {
2491
+ width: "target",
2492
+ position: "bottom",
2493
+ shadow: "lg",
2494
+ trapFocus: true,
2495
+ opened: opened,
2496
+ onChange: setOpened,
2497
+ children: [
2498
+ /*#__PURE__*/ jsx(Popover.Target, {
2499
+ children: /*#__PURE__*/ jsx(Button, {
2500
+ onClick: ()=>setOpened((o)=>!o),
2501
+ size: "xs",
2502
+ radius: "xl",
2503
+ className: "h-[--badge-height] uppercase",
2504
+ color: "utility.3",
2505
+ rightSection: /*#__PURE__*/ jsx(MdExpandMore, {
2506
+ size: "1.5em",
2507
+ "aria-label": opened ? 'close' : 'open',
2508
+ style: {
2509
+ transform: opened ? 'rotate(180deg)' : 'rotate(0deg)',
2510
+ transition: 'transform 200ms ease'
2511
+ }
2512
+ }),
2513
+ children: /*#__PURE__*/ jsx("span", {
2514
+ className: "font-black",
2515
+ children: message
2516
+ })
2517
+ })
2518
+ }),
2519
+ /*#__PURE__*/ jsx(Popover.Dropdown, {
2520
+ className: "px-2",
2521
+ children: /*#__PURE__*/ jsx(Button, {
2522
+ component: "a",
2523
+ href: workspaceAccountManagerTarget,
2524
+ target: "_blank",
2525
+ variant: "outline",
2526
+ leftSection: /*#__PURE__*/ jsx(MdOpenInNew, {
2527
+ size: "1.1em",
2528
+ "aria-label": "external"
2529
+ }),
2530
+ size: "xs",
2531
+ className: "w-full",
2532
+ children: "Workspace Account Manager"
2533
+ })
2534
+ })
2535
+ ]
2536
+ });
2537
+ }
2538
+ return /*#__PURE__*/ jsx(Badge, {
2539
+ color: "utility.3",
2540
+ children: message
2541
+ });
2542
+ };
2543
+ if (isError) {
2544
+ if (isNoPayModelError(error)) {
2545
+ return PayModelError('No pay model defined');
2546
+ } else {
2547
+ return PayModelError('Unable to get Payment information');
2548
+ }
2549
+ }
2550
+ const ProgressBar = (className = '')=>/*#__PURE__*/ jsx(Progress, {
2551
+ size: "sm",
2552
+ radius: "xl",
2553
+ "aria-label": "Monthly Workflow Limit",
2554
+ value: !hardLimit ? 100 : hardLimit / totalUsage * 100,
2555
+ color: !hardLimit || totalUsage >= hardLimit ? 'red.5' : 'green.1',
2556
+ className: className
2557
+ });
2558
+ return /*#__PURE__*/ jsxs(Popover, {
2559
+ width: "target",
2560
+ position: "bottom",
2561
+ shadow: "lg",
2562
+ trapFocus: true,
2563
+ opened: opened,
2564
+ onChange: setOpened,
2565
+ children: [
2566
+ /*#__PURE__*/ jsx(Popover.Target, {
2567
+ children: /*#__PURE__*/ jsxs(Button, {
2568
+ onClick: ()=>setOpened((o)=>!o),
2569
+ size: "xs",
2570
+ radius: "xl",
2571
+ variant: "default",
2572
+ className: "h-[--badge-height]",
2573
+ rightSection: /*#__PURE__*/ jsx(MdExpandMore, {
2574
+ className: "text-accent",
2575
+ size: "1.5em",
2576
+ "aria-label": opened ? 'close' : 'open',
2577
+ style: {
2578
+ transform: opened ? 'rotate(180deg)' : 'rotate(0deg)',
2579
+ transition: 'transform 200ms ease'
2580
+ }
2581
+ }),
2582
+ children: [
2583
+ ProgressBar('w-[110px]'),
2584
+ /*#__PURE__*/ jsxs("span", {
2585
+ className: "font-black pl-3 pr-2",
2586
+ children: [
2587
+ "$",
2588
+ PaymentNumberToString(totalUsage)
2589
+ ]
2590
+ }),
2591
+ /*#__PURE__*/ jsxs("span", {
2592
+ className: "font-normal",
2593
+ children: [
2594
+ "/$",
2595
+ PaymentNumberToString(hardLimit)
2596
+ ]
2597
+ })
2598
+ ]
2599
+ })
2600
+ }),
2601
+ /*#__PURE__*/ jsxs(Popover.Dropdown, {
2602
+ className: "px-2",
2603
+ children: [
2604
+ workspaceAccountManagerTarget && /*#__PURE__*/ jsx(Button, {
2605
+ component: "a",
2606
+ href: workspaceAccountManagerTarget,
2607
+ target: "_blank",
2608
+ variant: "outline",
2609
+ leftSection: /*#__PURE__*/ jsx(MdOpenInNew, {
2610
+ size: "1.1em",
2611
+ "aria-label": "external"
2612
+ }),
2613
+ size: "xs",
2614
+ className: "w-full mb-4",
2615
+ children: "Workspace Account Manager"
2616
+ }),
2617
+ /*#__PURE__*/ jsxs(Text, {
2618
+ size: "sm",
2619
+ className: "uppercase pb-2 px-2",
2620
+ children: [
2621
+ "Limit ",
2622
+ /*#__PURE__*/ jsxs("span", {
2623
+ className: "font-black pl-1",
2624
+ children: [
2625
+ "$",
2626
+ PaymentNumberToString(hardLimit)
2627
+ ]
2628
+ })
2629
+ ]
2630
+ }),
2631
+ ProgressBar('mx-2'),
2632
+ /*#__PURE__*/ jsx(Divider, {
2633
+ my: "sm"
2634
+ }),
2635
+ /*#__PURE__*/ jsx(Text, {
2636
+ size: "sm",
2637
+ className: "uppercase pb-2 px-2",
2638
+ children: "Account & Charges"
2639
+ }),
2640
+ /*#__PURE__*/ jsx(Accordion, {
2641
+ variant: "unstyled",
2642
+ classNames: {
2643
+ root: '',
2644
+ control: 'p-0 px-2',
2645
+ label: 'p-0',
2646
+ chevron: 'text-accent',
2647
+ panel: 'p-0',
2648
+ content: 'p-0'
2649
+ },
2650
+ children: /*#__PURE__*/ jsxs(Accordion.Item, {
2651
+ value: "accountInformation",
2652
+ children: [
2653
+ /*#__PURE__*/ jsx(Accordion.Control, {
2654
+ children: /*#__PURE__*/ jsxs(Text, {
2655
+ size: "sm",
2656
+ className: "font-black",
2657
+ children: [
2658
+ workspaceName,
2659
+ " - $",
2660
+ PaymentNumberToString(totalUsage)
2661
+ ]
2662
+ })
2663
+ }),
2664
+ /*#__PURE__*/ jsx(Accordion.Panel, {
2665
+ children: /*#__PURE__*/ jsx(Radio.Group, {
2666
+ className: "pt-2",
2667
+ children: usersPayModels.map((obj)=>/*#__PURE__*/ jsx(Radio.Card, {
2668
+ checked: obj.currentPayModel,
2669
+ disabled: true,
2670
+ className: "p-2 border-none data-checked:bg-primary-lightest data-checked:border-primary-darker data-checked:font-black hover:bg-primary-max ",
2671
+ children: /*#__PURE__*/ jsxs(Group, {
2672
+ wrap: "nowrap",
2673
+ align: "flex-start",
2674
+ children: [
2675
+ /*#__PURE__*/ jsx(Text, {
2676
+ size: "sm",
2677
+ className: "grow",
2678
+ children: obj.label
2679
+ }),
2680
+ /*#__PURE__*/ jsxs(Text, {
2681
+ size: "sm",
2682
+ children: [
2683
+ "$",
2684
+ PaymentNumberToString(obj.totalUsage)
2685
+ ]
2686
+ }),
2687
+ /*#__PURE__*/ jsx(Radio.Indicator, {
2688
+ color: "accent"
2689
+ })
2690
+ ]
2691
+ })
2692
+ }, obj.value))
2693
+ })
2694
+ })
2695
+ ]
2696
+ })
2697
+ })
2698
+ ]
2699
+ })
2700
+ ]
2701
+ });
2702
+ };
2703
+
2428
2704
  const WorkspaceToolbar = /*#__PURE__*/ forwardRef(({ toolbarConfiguration }, ref)=>{
2429
2705
  const workspaceTier = useCoreSelector((state)=>selectWorkspaceTier(state));
2430
2706
  const workspaceStatus = useCoreSelector((state)=>selectJEGActiveWorkspaceStatus(state));
2431
2707
  const isFullscreen = useCoreSelector((state)=>selectWorkspaceFullscreen(state));
2432
- const { showStatus, showStop, tierLabel } = toolbarConfiguration || {};
2708
+ const { showStatus, showStop, tierLabel, requirePayModel, workspaceAccountManagerTarget } = toolbarConfiguration || {};
2433
2709
  const coreDispatch = useCoreDispatch();
2434
2710
  const toggleFullscreen = useCallback(()=>{
2435
2711
  coreDispatch(setWorkspaceFullscreen(!isFullscreen));
@@ -2484,6 +2760,9 @@ const WorkspaceToolbar = /*#__PURE__*/ forwardRef(({ toolbarConfiguration }, ref
2484
2760
  /*#__PURE__*/ jsx(Badge, {
2485
2761
  "aria-label": `Workspace tier: ${tierLabel ?? workspaceTier}`,
2486
2762
  children: tierLabel ?? workspaceTier
2763
+ }),
2764
+ requirePayModel && /*#__PURE__*/ jsx(CostTracker, {
2765
+ workspaceAccountManagerTarget: workspaceAccountManagerTarget
2487
2766
  })
2488
2767
  ]
2489
2768
  })