github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/ui/dashboard/src/components/dashboards/layout/PanelDetail/index.tsx (about)

     1  import Grid from "../Grid";
     2  import NeutralButton from "../../../forms/NeutralButton";
     3  import PanelDetailData from "./PanelDetailData";
     4  import PanelDetailDataDownloadButton from "./PanelDetailDataDownloadButton";
     5  import PanelDetailDefinition from "./PanelDetailDefinition";
     6  import PanelDetailLog from "./PanelDetailLog";
     7  import PanelDetailPreview from "./PanelDetailPreview";
     8  import PanelDetailQuery from "./PanelDetailQuery";
     9  import { classNames } from "../../../../utils/styles";
    10  import { DashboardDataModeLive, PanelDefinition } from "../../../../types";
    11  import { useDashboard } from "../../../../hooks/useDashboard";
    12  import { useMemo, useState } from "react";
    13  
    14  export type PanelDetailProps = {
    15    definition: PanelDefinition;
    16  };
    17  
    18  const Tabs = {
    19    PREVIEW: {
    20      name: "preview",
    21      label: "Preview",
    22      Component: PanelDetailPreview,
    23    },
    24    QUERY: {
    25      name: "query",
    26      label: "Query",
    27      Component: PanelDetailQuery,
    28    },
    29    DEFINITION: {
    30      name: "definition",
    31      label: "Definition",
    32      Component: PanelDetailDefinition,
    33    },
    34    DATA: {
    35      name: "data",
    36      label: "Data",
    37      Component: PanelDetailData,
    38    },
    39    LOG: {
    40      name: "log",
    41      label: "Log",
    42      Component: PanelDetailLog,
    43    },
    44  };
    45  
    46  const PanelDetail = ({ definition }: PanelDetailProps) => {
    47    const [selectedTab, setSelectedTab] = useState(Tabs.PREVIEW);
    48    const {
    49      breakpointContext: { minBreakpoint },
    50      closePanelDetail,
    51      dataMode,
    52      panelsLog,
    53    } = useDashboard();
    54    const isTablet = minBreakpoint("md");
    55  
    56    const panelLog = panelsLog[definition.name];
    57  
    58    const availableTabs = useMemo(() => {
    59      const tabs = [
    60        {
    61          ...Tabs.PREVIEW,
    62          selected: selectedTab.name === Tabs.PREVIEW.name,
    63        },
    64      ];
    65      if (definition.sql) {
    66        tabs.push({
    67          ...Tabs.QUERY,
    68          selected: selectedTab.name === Tabs.QUERY.name,
    69        });
    70      }
    71      if (definition.source_definition) {
    72        tabs.push({
    73          ...Tabs.DEFINITION,
    74          selected: selectedTab.name === Tabs.DEFINITION.name,
    75        });
    76      }
    77      if (definition.data) {
    78        tabs.push({
    79          ...Tabs.DATA,
    80          selected: selectedTab.name === Tabs.DATA.name,
    81        });
    82      }
    83      if (
    84        dataMode === DashboardDataModeLive &&
    85        definition.panel_type !== "benchmark" &&
    86        definition.panel_type !== "control" &&
    87        !!panelLog
    88      ) {
    89        tabs.push({
    90          ...Tabs.LOG,
    91          selected: selectedTab.name === Tabs.LOG.name,
    92        });
    93      }
    94      return tabs;
    95    }, [dataMode, definition, panelLog, selectedTab]);
    96  
    97    return (
    98      <div className="h-full overflow-y-auto p-4">
    99        <Grid name={definition.name}>
   100          <div className="col-span-6">
   101            <h2 className="break-keep">{definition.title || "Panel Detail"}</h2>
   102          </div>
   103          <div className="col-span-6 space-x-2 text-right">
   104            <PanelDetailDataDownloadButton
   105              panelDefinition={definition}
   106              size={isTablet ? "md" : "sm"}
   107            />
   108            <NeutralButton
   109              onClick={closePanelDetail}
   110              size={isTablet ? "md" : "sm"}
   111            >
   112              <>
   113                Close<span className="ml-2 font-light text-xxs">ESC</span>
   114              </>
   115            </NeutralButton>
   116          </div>
   117          <div className="col-span-12 sm:hidden ">
   118            <label htmlFor="tabs" className="sr-only">
   119              Select a tab
   120            </label>
   121            {/* Use an "onChange" listener to redirect the user to the selected tab URL. */}
   122            <select
   123              id="tabs"
   124              name="tabs"
   125              className="mt-2 block w-full pl-3 pr-10 py-2 bg-dashboard print:bg-white text-foreground border-black-scale-3 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm rounded-md"
   126              defaultValue={selectedTab.name}
   127              onChange={(e) =>
   128                setSelectedTab(
   129                  availableTabs.find((tab) => tab.name === e.target.value) ||
   130                    availableTabs[0]
   131                )
   132              }
   133            >
   134              {availableTabs.map((tab) => (
   135                <option key={tab.name} value={tab.name}>
   136                  {tab.label}
   137                </option>
   138              ))}
   139            </select>
   140          </div>
   141          <div className="col-span-12 hidden sm:block">
   142            <div className="border-b border-black-scale-3">
   143              <nav className="-mb-px flex space-x-6" aria-label="Tabs">
   144                {availableTabs.map((tab) => (
   145                  <span
   146                    key={tab.name}
   147                    className={classNames(
   148                      tab.selected
   149                        ? "border-black-scale-4 text-foreground cursor-pointer"
   150                        : "border-transparent text-foreground-lighter hover:text-foreground cursor-pointer",
   151                      "whitespace-nowrap py-3 px-1 border-b-2 font-medium text-sm"
   152                    )}
   153                    onClick={() => setSelectedTab(tab)}
   154                  >
   155                    {tab.label}
   156                  </span>
   157                ))}
   158              </nav>
   159            </div>
   160          </div>
   161  
   162          <div className="col-span-12 mt-4">
   163            {<selectedTab.Component definition={definition} />}
   164          </div>
   165        </Grid>
   166      </div>
   167    );
   168  };
   169  
   170  export default PanelDetail;